A lone zero-width character in the first column occupies 1 column #22634

Open
opened 2026-01-31 08:19:09 +00:00 by claunia · 0 comments
Owner

Originally created by @lhecker on GitHub (Dec 9, 2024).

Windows Terminal version

1.23.3411.0

Windows build number

No response

Other Software

No response

Steps to reproduce

In PowerShell:

"`r`u{200B}foo"

Expected Behavior

foo

Actual Behavior

 foo

The reason it happens is because before inserting anything in our text buffer we check if it joins with the already existing character and then merge it together with the new input. For any other characters we clamp the width of each grapheme cluster to a value between 1 and 2. Since a zero-width character can't join with anything in the first column it will be measured as its own cluster which results in a width of 1.
The reason we do this is primarily because of our architecture which assumes O(1) lookups in the text buffer. The only way to make that work is by assuming that each grapheme cluster has a width of 1-2. The secondary reason for that is because inserting the ZWSP there puts it in front of the first column, assigning it column -1, which is not something that should be possible. Put differently, if you're at column 1 and iterate to the previous grapheme cluster, you would end up at column 0 (the start of the line), but after the ZWSP. It's a problem I don't have a good solution for except "add a bunch of special conditions" which gave me the gut feeling of "the problem has not been fundamentally solved".

https://github.com/microsoft/terminal/issues/18267#issuecomment-2529077871

Originally created by @lhecker on GitHub (Dec 9, 2024). ### Windows Terminal version 1.23.3411.0 ### Windows build number _No response_ ### Other Software _No response_ ### Steps to reproduce In PowerShell: ```pwsh "`r`u{200B}foo" ``` ### Expected Behavior ``` foo ``` ### Actual Behavior ``` foo ``` > The reason it happens is because before inserting anything in our text buffer we check if it joins with the already existing character and then merge it together with the new input. For any other characters we clamp the width of each grapheme cluster to a value between 1 and 2. Since a zero-width character can't join with anything in the first column it will be measured as its own cluster which results in a width of 1. > The reason we do this is primarily because of our architecture which assumes O(1) lookups in the text buffer. The only way to make that work is by assuming that each grapheme cluster has a width of 1-2. The secondary reason for that is because inserting the ZWSP there puts it in front of the first column, assigning it column -1, which is not something that should be possible. Put differently, if you're at column 1 and iterate to the previous grapheme cluster, you would end up at column 0 (the start of the line), but after the ZWSP. It's a problem I don't have a good solution for except "add a bunch of special conditions" which gave me the gut feeling of "the problem has not been fundamentally solved". https://github.com/microsoft/terminal/issues/18267#issuecomment-2529077871
claunia added the Area-OutputIssue-BugPriority-3Needs-Tag-Fix labels 2026-01-31 08:19:09 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#22634