fix(src/ui.zig): render UTF-8 in the sidebar and status row#49
Merged
Conversation
The sidebar and status row replaced every non-ASCII byte with '?', so UTF-8 text such as a Mandarin window title rendered as a run of question marks. Decode UTF-8 in appendClipped and pass valid printable sequences through intact, clipping by display columns: East Asian wide characters take two columns and combining marks take none, so rows keep their exact width and never bleed into the separator. Control bytes and invalid sequences still render as '?'. Session content in the viewport already rendered through libghostty's formatter and was unaffected. Fixes #48
ghostty-vt computes exact cell widths internally, but the table is generated at build time and not exported through the module, so the sidebar's chrome measurement cannot reuse it.
This was referenced Jun 12, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #48
The
boo uisidebar and status row replaced every non-ASCII byte with?, so UTF-8 text (e.g. a Mandarin window title, 3 bytes per character) rendered as a run of question marks.Changes
appendClippednow decodes UTF-8 and passes valid printable sequences through intact, clipping by display columns instead of bytes: East Asian wide/fullwidth characters count as two columns, combining marks as zero (compact wcwidth-style table). Rows keep their exact width, so the sidebar never bleeds into the separator or viewport; a wide character that would straddle the clip boundary is dropped and padded.?, preserving the old guarantee that no raw control bytes reach the row being composed.Entry.titlecomment ("sanitized to printable ASCII"): the daemon only strips control bytes, titles may contain any UTF-8.Session content in the viewport already rendered through libghostty's formatter and was unaffected; a regression test now pins that down too.
Testing
appendTermRow.zig build test-all(unit + PTY integration) passes;zig fmtclean.你好世界OSC title in a live session; the daemon reports it intact inboo lsand the sidebar renders it.Investigation notes
[a-zA-Z0-9._-], so the non-ASCII text in the sidebar comes from window titles (OSC 2) and status-row text;appendClippedwas the single choke point that mangled them.daemon.zig) only strips bytes< 0x20and0x7f, so multi-byte UTF-8 already arrived intact at the UI.lib_vt.zig, so the fix uses a compact wcwidth-style approximation covering the common zero-width and wide ranges; only sidebar/status chrome is measured with it, session content goes through libghostty.This PR was generated by Coder Agents on behalf of @kylecarbs.