[GH-ISSUE #278] ™ leads to rendering bugs #215

Closed
opened 2026-03-04 01:03:03 +03:00 by kerem · 4 comments
Owner

Originally created by @SoMuchForSubtlety on GitHub (Apr 25, 2019).
Original GitHub issue: https://github.com/rivo/tview/issues/278

displaying a string with in it can lead to rendering bugs.
I recorded two examples with slightly different bahaviour.

https://streamable.com/d6cmq

https://streamable.com/k5vp9

Originally created by @SoMuchForSubtlety on GitHub (Apr 25, 2019). Original GitHub issue: https://github.com/rivo/tview/issues/278 displaying a string with `™` in it can lead to rendering bugs. I recorded two examples with slightly different bahaviour. https://streamable.com/d6cmq https://streamable.com/k5vp9
kerem closed this issue 2026-03-04 01:03:03 +03:00
Author
Owner

@calzoneman commented on GitHub (May 14, 2019):

I actually ran into this recently.

The root of the problem is in go-runewidth, which tview uses to compute the screen cell width of characters/strings. is in the Unicode standard Emoji class, and go-runewidth considers all emoji to be of width 2, however, some terminals seem to only treat codepoints in the Emoji_Presentation block to be double-width, and ™ is not one of those (I cannot discern what rhyme or reason was used to decide which codepoints are Emoji_Presentation and which are not; hence, my terminal emulator tends to cut a lot of glyphs that should be double wide in half). As far as I can tell, no standard prescribes monospace character width of Unicode codepoints, which is unfortunate and results in not just emoji rendering glitches but also numerous hacks to attempt to get Asian character sets to render correctly.

Personally, I am using this patch to go-runewidth which at least makes the emoji width consistent with my terminal, although as stated above I'm still unsatisfied with the resulting rendering glitches since my symbol font and my terminal emulator seem to disagree on which codepoints should be double width or not:

diff --git a/runewidth.go b/runewidth.go
index 3cb9410..569f021 100644
--- a/runewidth.go
+++ b/runewidth.go
@@ -272,54 +272,50 @@ var ambiguous = table{
 }
 
 var emoji = table{
-	{0x203C, 0x203C}, {0x2049, 0x2049}, {0x2122, 0x2122},
-	{0x2139, 0x2139}, {0x2194, 0x2199}, {0x21A9, 0x21AA},
-	{0x231A, 0x231B}, {0x2328, 0x2328}, {0x23CF, 0x23CF},
-	{0x23E9, 0x23F3}, {0x23F8, 0x23FA}, {0x24C2, 0x24C2},
-	{0x25AA, 0x25AB}, {0x25B6, 0x25B6}, {0x25C0, 0x25C0},
-	{0x25FB, 0x25FE}, {0x2600, 0x2604}, {0x260E, 0x260E},
-	{0x2611, 0x2611}, {0x2614, 0x2615}, {0x2618, 0x2618},
-	{0x261D, 0x261D}, {0x2620, 0x2620}, {0x2622, 0x2623},
-	{0x2626, 0x2626}, {0x262A, 0x262A}, {0x262E, 0x262F},
-	{0x2638, 0x263A}, {0x2640, 0x2640}, {0x2642, 0x2642},
-	{0x2648, 0x2653}, {0x265F, 0x2660}, {0x2663, 0x2663},
-	{0x2665, 0x2666}, {0x2668, 0x2668}, {0x267B, 0x267B},
-	{0x267E, 0x267F}, {0x2692, 0x2697}, {0x2699, 0x2699},
-	{0x269B, 0x269C}, {0x26A0, 0x26A1}, {0x26AA, 0x26AB},
-	{0x26B0, 0x26B1}, {0x26BD, 0x26BE}, {0x26C4, 0x26C5},
-	{0x26C8, 0x26C8}, {0x26CE, 0x26CF}, {0x26D1, 0x26D1},
-	{0x26D3, 0x26D4}, {0x26E9, 0x26EA}, {0x26F0, 0x26F5},
-	{0x26F7, 0x26FA}, {0x26FD, 0x26FD}, {0x2702, 0x2702},
-	{0x2705, 0x2705}, {0x2708, 0x270D}, {0x270F, 0x270F},
-	{0x2712, 0x2712}, {0x2714, 0x2714}, {0x2716, 0x2716},
-	{0x271D, 0x271D}, {0x2721, 0x2721}, {0x2728, 0x2728},
-	{0x2733, 0x2734}, {0x2744, 0x2744}, {0x2747, 0x2747},
-	{0x274C, 0x274C}, {0x274E, 0x274E}, {0x2753, 0x2755},
-	{0x2757, 0x2757}, {0x2763, 0x2764}, {0x2795, 0x2797},
-	{0x27A1, 0x27A1}, {0x27B0, 0x27B0}, {0x27BF, 0x27BF},
-	{0x2934, 0x2935}, {0x2B05, 0x2B07}, {0x2B1B, 0x2B1C},
-	{0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x3030, 0x3030},
-	{0x303D, 0x303D}, {0x3297, 0x3297}, {0x3299, 0x3299},
-	{0x1F004, 0x1F004}, {0x1F0CF, 0x1F0CF}, {0x1F170, 0x1F171},
-	{0x1F17E, 0x1F17F}, {0x1F18E, 0x1F18E}, {0x1F191, 0x1F19A},
-	{0x1F1E6, 0x1F1FF}, {0x1F201, 0x1F202}, {0x1F21A, 0x1F21A},
-	{0x1F22F, 0x1F22F}, {0x1F232, 0x1F23A}, {0x1F250, 0x1F251},
-	{0x1F300, 0x1F321}, {0x1F324, 0x1F393}, {0x1F396, 0x1F397},
-	{0x1F399, 0x1F39B}, {0x1F39E, 0x1F3F0}, {0x1F3F3, 0x1F3F5},
-	{0x1F3F7, 0x1F4FD}, {0x1F4FF, 0x1F53D}, {0x1F549, 0x1F54E},
-	{0x1F550, 0x1F567}, {0x1F56F, 0x1F570}, {0x1F573, 0x1F57A},
-	{0x1F587, 0x1F587}, {0x1F58A, 0x1F58D}, {0x1F590, 0x1F590},
-	{0x1F595, 0x1F596}, {0x1F5A4, 0x1F5A5}, {0x1F5A8, 0x1F5A8},
-	{0x1F5B1, 0x1F5B2}, {0x1F5BC, 0x1F5BC}, {0x1F5C2, 0x1F5C4},
-	{0x1F5D1, 0x1F5D3}, {0x1F5DC, 0x1F5DE}, {0x1F5E1, 0x1F5E1},
-	{0x1F5E3, 0x1F5E3}, {0x1F5E8, 0x1F5E8}, {0x1F5EF, 0x1F5EF},
-	{0x1F5F3, 0x1F5F3}, {0x1F5FA, 0x1F64F}, {0x1F680, 0x1F6C5},
-	{0x1F6CB, 0x1F6D2}, {0x1F6E0, 0x1F6E5}, {0x1F6E9, 0x1F6E9},
-	{0x1F6EB, 0x1F6EC}, {0x1F6F0, 0x1F6F0}, {0x1F6F3, 0x1F6F9},
-	{0x1F910, 0x1F93A}, {0x1F93C, 0x1F93E}, {0x1F940, 0x1F945},
-	{0x1F947, 0x1F970}, {0x1F973, 0x1F976}, {0x1F97A, 0x1F97A},
-	{0x1F97C, 0x1F9A2}, {0x1F9B0, 0x1F9B9}, {0x1F9C0, 0x1F9C2},
-	{0x1F9D0, 0x1F9FF},
+	{0x231A, 0x231B}, {0x23E9, 0x23EC}, {0x23F0, 0x23F0},
+	{0x23F3, 0x23F3}, {0x25FD, 0x25FE}, {0x2614, 0x2615},
+	{0x2648, 0x2653}, {0x267F, 0x267F}, {0x2693, 0x2693},
+	{0x26A1, 0x26A1}, {0x26AA, 0x26AB}, {0x26BD, 0x26BE},
+	{0x26C4, 0x26C5}, {0x26CE, 0x26CE}, {0x26D4, 0x26D4},
+	{0x26EA, 0x26EA}, {0x26F2, 0x26F3}, {0x26F5, 0x26F5},
+	{0x26FA, 0x26FA}, {0x26FD, 0x26FD}, {0x2705, 0x2705},
+	{0x270A, 0x270B}, {0x2728, 0x2728}, {0x274C, 0x274C},
+	{0x274E, 0x274E}, {0x2753, 0x2755}, {0x2757, 0x2757},
+	{0x2795, 0x2797}, {0x27B0, 0x27B0}, {0x27BF, 0x27BF},
+	{0x2B1B, 0x2B1C}, {0x2B50, 0x2B50}, {0x2B55, 0x2B55},
+	{0x1F004, 0x1F004}, {0x1F0CF, 0x1F0CF}, {0x1F18E, 0x1F18E},
+	{0x1F191, 0x1F19A}, {0x1F1E6, 0x1F1FF}, {0x1F201, 0x1F201},
+	{0x1F21A, 0x1F21A}, {0x1F22F, 0x1F22F}, {0x1F232, 0x1F236},
+	{0x1F238, 0x1F23A}, {0x1F250, 0x1F251}, {0x1F300, 0x1F320},
+	{0x1F32D, 0x1F32F}, {0x1F330, 0x1F335}, {0x1F337, 0x1F37C},
+	{0x1F37E, 0x1F37F}, {0x1F380, 0x1F393}, {0x1F3A0, 0x1F3C4},
+	{0x1F3C5, 0x1F3C5}, {0x1F3C6, 0x1F3CA}, {0x1F3CF, 0x1F3D3},
+	{0x1F3E0, 0x1F3F0}, {0x1F3F4, 0x1F3F4}, {0x1F3F8, 0x1F3FF},
+	{0x1F400, 0x1F43E}, {0x1F440, 0x1F440}, {0x1F442, 0x1F4F7},
+	{0x1F4F8, 0x1F4F8}, {0x1F4F9, 0x1F4FC}, {0x1F4FF, 0x1F4FF},
+	{0x1F500, 0x1F53D}, {0x1F54B, 0x1F54E}, {0x1F550, 0x1F567},
+	{0x1F57A, 0x1F57A}, {0x1F595, 0x1F596}, {0x1F5A4, 0x1F5A4},
+	{0x1F5FB, 0x1F5FF}, {0x1F600, 0x1F600}, {0x1F601, 0x1F610},
+	{0x1F611, 0x1F611}, {0x1F612, 0x1F614}, {0x1F615, 0x1F615},
+	{0x1F616, 0x1F616}, {0x1F617, 0x1F617}, {0x1F618, 0x1F618},
+	{0x1F619, 0x1F619}, {0x1F61A, 0x1F61A}, {0x1F61B, 0x1F61B},
+	{0x1F61C, 0x1F61E}, {0x1F61F, 0x1F61F}, {0x1F620, 0x1F625},
+	{0x1F626, 0x1F627}, {0x1F628, 0x1F62B}, {0x1F62C, 0x1F62C},
+	{0x1F62D, 0x1F62D}, {0x1F62E, 0x1F62F}, {0x1F630, 0x1F633},
+	{0x1F634, 0x1F634}, {0x1F635, 0x1F640}, {0x1F641, 0x1F642},
+	{0x1F643, 0x1F644}, {0x1F645, 0x1F64F}, {0x1F680, 0x1F6C5},
+	{0x1F6CC, 0x1F6CC}, {0x1F6D0, 0x1F6D0}, {0x1F6D1, 0x1F6D2},
+	{0x1F6EB, 0x1F6EC}, {0x1F6F4, 0x1F6F6}, {0x1F6F7, 0x1F6F8},
+	{0x1F6F9, 0x1F6F9}, {0x1F910, 0x1F918}, {0x1F919, 0x1F91E},
+	{0x1F91F, 0x1F91F}, {0x1F920, 0x1F927}, {0x1F928, 0x1F92F},
+	{0x1F930, 0x1F930}, {0x1F931, 0x1F932}, {0x1F933, 0x1F93A},
+	{0x1F93C, 0x1F93E}, {0x1F940, 0x1F945}, {0x1F947, 0x1F94B},
+	{0x1F94C, 0x1F94C}, {0x1F94D, 0x1F94F}, {0x1F950, 0x1F95E},
+	{0x1F95F, 0x1F96B}, {0x1F96C, 0x1F970}, {0x1F973, 0x1F976},
+	{0x1F97A, 0x1F97A}, {0x1F97C, 0x1F97F}, {0x1F980, 0x1F984},
+	{0x1F985, 0x1F991}, {0x1F992, 0x1F997}, {0x1F998, 0x1F9A2},
+	{0x1F9B0, 0x1F9B9}, {0x1F9C0, 0x1F9C0}, {0x1F9C1, 0x1F9C2},
+	{0x1F9D0, 0x1F9E6}, {0x1F9E7, 0x1F9FF},
 }
 
 var notassigned = table{

Patch was built by having go-runewidth only treat Emoji_Presentation as double-wide, not all Emoji. See: https://unicode.org/Public/emoji/12.0/emoji-data.txt

<!-- gh-comment-id:492079066 --> @calzoneman commented on GitHub (May 14, 2019): I actually ran into this recently. The root of the problem is in `go-runewidth`, which `tview` uses to compute the screen cell width of characters/strings. `™` is in the Unicode standard Emoji class, and `go-runewidth` [considers all emoji to be of width 2](https://github.com/mattn/go-runewidth/blob/master/runewidth.go#L829), however, some terminals seem to only treat codepoints in the *Emoji\_Presentation* block to be double-width, and ™ is not one of those (I cannot discern what rhyme or reason was used to decide which codepoints are Emoji\_Presentation and which are not; hence, my terminal emulator tends to cut a lot of glyphs that should be double wide in half). As far as I can tell, no standard prescribes monospace character width of Unicode codepoints, which is unfortunate and results in not just emoji rendering glitches but also numerous hacks to attempt to get Asian character sets to render correctly. Personally, I am using this patch to `go-runewidth` which at least makes the emoji width consistent with my terminal, although as stated above I'm still unsatisfied with the resulting rendering glitches since my symbol font and my terminal emulator seem to disagree on which codepoints should be double width or not: ```diff diff --git a/runewidth.go b/runewidth.go index 3cb9410..569f021 100644 --- a/runewidth.go +++ b/runewidth.go @@ -272,54 +272,50 @@ var ambiguous = table{ } var emoji = table{ - {0x203C, 0x203C}, {0x2049, 0x2049}, {0x2122, 0x2122}, - {0x2139, 0x2139}, {0x2194, 0x2199}, {0x21A9, 0x21AA}, - {0x231A, 0x231B}, {0x2328, 0x2328}, {0x23CF, 0x23CF}, - {0x23E9, 0x23F3}, {0x23F8, 0x23FA}, {0x24C2, 0x24C2}, - {0x25AA, 0x25AB}, {0x25B6, 0x25B6}, {0x25C0, 0x25C0}, - {0x25FB, 0x25FE}, {0x2600, 0x2604}, {0x260E, 0x260E}, - {0x2611, 0x2611}, {0x2614, 0x2615}, {0x2618, 0x2618}, - {0x261D, 0x261D}, {0x2620, 0x2620}, {0x2622, 0x2623}, - {0x2626, 0x2626}, {0x262A, 0x262A}, {0x262E, 0x262F}, - {0x2638, 0x263A}, {0x2640, 0x2640}, {0x2642, 0x2642}, - {0x2648, 0x2653}, {0x265F, 0x2660}, {0x2663, 0x2663}, - {0x2665, 0x2666}, {0x2668, 0x2668}, {0x267B, 0x267B}, - {0x267E, 0x267F}, {0x2692, 0x2697}, {0x2699, 0x2699}, - {0x269B, 0x269C}, {0x26A0, 0x26A1}, {0x26AA, 0x26AB}, - {0x26B0, 0x26B1}, {0x26BD, 0x26BE}, {0x26C4, 0x26C5}, - {0x26C8, 0x26C8}, {0x26CE, 0x26CF}, {0x26D1, 0x26D1}, - {0x26D3, 0x26D4}, {0x26E9, 0x26EA}, {0x26F0, 0x26F5}, - {0x26F7, 0x26FA}, {0x26FD, 0x26FD}, {0x2702, 0x2702}, - {0x2705, 0x2705}, {0x2708, 0x270D}, {0x270F, 0x270F}, - {0x2712, 0x2712}, {0x2714, 0x2714}, {0x2716, 0x2716}, - {0x271D, 0x271D}, {0x2721, 0x2721}, {0x2728, 0x2728}, - {0x2733, 0x2734}, {0x2744, 0x2744}, {0x2747, 0x2747}, - {0x274C, 0x274C}, {0x274E, 0x274E}, {0x2753, 0x2755}, - {0x2757, 0x2757}, {0x2763, 0x2764}, {0x2795, 0x2797}, - {0x27A1, 0x27A1}, {0x27B0, 0x27B0}, {0x27BF, 0x27BF}, - {0x2934, 0x2935}, {0x2B05, 0x2B07}, {0x2B1B, 0x2B1C}, - {0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x3030, 0x3030}, - {0x303D, 0x303D}, {0x3297, 0x3297}, {0x3299, 0x3299}, - {0x1F004, 0x1F004}, {0x1F0CF, 0x1F0CF}, {0x1F170, 0x1F171}, - {0x1F17E, 0x1F17F}, {0x1F18E, 0x1F18E}, {0x1F191, 0x1F19A}, - {0x1F1E6, 0x1F1FF}, {0x1F201, 0x1F202}, {0x1F21A, 0x1F21A}, - {0x1F22F, 0x1F22F}, {0x1F232, 0x1F23A}, {0x1F250, 0x1F251}, - {0x1F300, 0x1F321}, {0x1F324, 0x1F393}, {0x1F396, 0x1F397}, - {0x1F399, 0x1F39B}, {0x1F39E, 0x1F3F0}, {0x1F3F3, 0x1F3F5}, - {0x1F3F7, 0x1F4FD}, {0x1F4FF, 0x1F53D}, {0x1F549, 0x1F54E}, - {0x1F550, 0x1F567}, {0x1F56F, 0x1F570}, {0x1F573, 0x1F57A}, - {0x1F587, 0x1F587}, {0x1F58A, 0x1F58D}, {0x1F590, 0x1F590}, - {0x1F595, 0x1F596}, {0x1F5A4, 0x1F5A5}, {0x1F5A8, 0x1F5A8}, - {0x1F5B1, 0x1F5B2}, {0x1F5BC, 0x1F5BC}, {0x1F5C2, 0x1F5C4}, - {0x1F5D1, 0x1F5D3}, {0x1F5DC, 0x1F5DE}, {0x1F5E1, 0x1F5E1}, - {0x1F5E3, 0x1F5E3}, {0x1F5E8, 0x1F5E8}, {0x1F5EF, 0x1F5EF}, - {0x1F5F3, 0x1F5F3}, {0x1F5FA, 0x1F64F}, {0x1F680, 0x1F6C5}, - {0x1F6CB, 0x1F6D2}, {0x1F6E0, 0x1F6E5}, {0x1F6E9, 0x1F6E9}, - {0x1F6EB, 0x1F6EC}, {0x1F6F0, 0x1F6F0}, {0x1F6F3, 0x1F6F9}, - {0x1F910, 0x1F93A}, {0x1F93C, 0x1F93E}, {0x1F940, 0x1F945}, - {0x1F947, 0x1F970}, {0x1F973, 0x1F976}, {0x1F97A, 0x1F97A}, - {0x1F97C, 0x1F9A2}, {0x1F9B0, 0x1F9B9}, {0x1F9C0, 0x1F9C2}, - {0x1F9D0, 0x1F9FF}, + {0x231A, 0x231B}, {0x23E9, 0x23EC}, {0x23F0, 0x23F0}, + {0x23F3, 0x23F3}, {0x25FD, 0x25FE}, {0x2614, 0x2615}, + {0x2648, 0x2653}, {0x267F, 0x267F}, {0x2693, 0x2693}, + {0x26A1, 0x26A1}, {0x26AA, 0x26AB}, {0x26BD, 0x26BE}, + {0x26C4, 0x26C5}, {0x26CE, 0x26CE}, {0x26D4, 0x26D4}, + {0x26EA, 0x26EA}, {0x26F2, 0x26F3}, {0x26F5, 0x26F5}, + {0x26FA, 0x26FA}, {0x26FD, 0x26FD}, {0x2705, 0x2705}, + {0x270A, 0x270B}, {0x2728, 0x2728}, {0x274C, 0x274C}, + {0x274E, 0x274E}, {0x2753, 0x2755}, {0x2757, 0x2757}, + {0x2795, 0x2797}, {0x27B0, 0x27B0}, {0x27BF, 0x27BF}, + {0x2B1B, 0x2B1C}, {0x2B50, 0x2B50}, {0x2B55, 0x2B55}, + {0x1F004, 0x1F004}, {0x1F0CF, 0x1F0CF}, {0x1F18E, 0x1F18E}, + {0x1F191, 0x1F19A}, {0x1F1E6, 0x1F1FF}, {0x1F201, 0x1F201}, + {0x1F21A, 0x1F21A}, {0x1F22F, 0x1F22F}, {0x1F232, 0x1F236}, + {0x1F238, 0x1F23A}, {0x1F250, 0x1F251}, {0x1F300, 0x1F320}, + {0x1F32D, 0x1F32F}, {0x1F330, 0x1F335}, {0x1F337, 0x1F37C}, + {0x1F37E, 0x1F37F}, {0x1F380, 0x1F393}, {0x1F3A0, 0x1F3C4}, + {0x1F3C5, 0x1F3C5}, {0x1F3C6, 0x1F3CA}, {0x1F3CF, 0x1F3D3}, + {0x1F3E0, 0x1F3F0}, {0x1F3F4, 0x1F3F4}, {0x1F3F8, 0x1F3FF}, + {0x1F400, 0x1F43E}, {0x1F440, 0x1F440}, {0x1F442, 0x1F4F7}, + {0x1F4F8, 0x1F4F8}, {0x1F4F9, 0x1F4FC}, {0x1F4FF, 0x1F4FF}, + {0x1F500, 0x1F53D}, {0x1F54B, 0x1F54E}, {0x1F550, 0x1F567}, + {0x1F57A, 0x1F57A}, {0x1F595, 0x1F596}, {0x1F5A4, 0x1F5A4}, + {0x1F5FB, 0x1F5FF}, {0x1F600, 0x1F600}, {0x1F601, 0x1F610}, + {0x1F611, 0x1F611}, {0x1F612, 0x1F614}, {0x1F615, 0x1F615}, + {0x1F616, 0x1F616}, {0x1F617, 0x1F617}, {0x1F618, 0x1F618}, + {0x1F619, 0x1F619}, {0x1F61A, 0x1F61A}, {0x1F61B, 0x1F61B}, + {0x1F61C, 0x1F61E}, {0x1F61F, 0x1F61F}, {0x1F620, 0x1F625}, + {0x1F626, 0x1F627}, {0x1F628, 0x1F62B}, {0x1F62C, 0x1F62C}, + {0x1F62D, 0x1F62D}, {0x1F62E, 0x1F62F}, {0x1F630, 0x1F633}, + {0x1F634, 0x1F634}, {0x1F635, 0x1F640}, {0x1F641, 0x1F642}, + {0x1F643, 0x1F644}, {0x1F645, 0x1F64F}, {0x1F680, 0x1F6C5}, + {0x1F6CC, 0x1F6CC}, {0x1F6D0, 0x1F6D0}, {0x1F6D1, 0x1F6D2}, + {0x1F6EB, 0x1F6EC}, {0x1F6F4, 0x1F6F6}, {0x1F6F7, 0x1F6F8}, + {0x1F6F9, 0x1F6F9}, {0x1F910, 0x1F918}, {0x1F919, 0x1F91E}, + {0x1F91F, 0x1F91F}, {0x1F920, 0x1F927}, {0x1F928, 0x1F92F}, + {0x1F930, 0x1F930}, {0x1F931, 0x1F932}, {0x1F933, 0x1F93A}, + {0x1F93C, 0x1F93E}, {0x1F940, 0x1F945}, {0x1F947, 0x1F94B}, + {0x1F94C, 0x1F94C}, {0x1F94D, 0x1F94F}, {0x1F950, 0x1F95E}, + {0x1F95F, 0x1F96B}, {0x1F96C, 0x1F970}, {0x1F973, 0x1F976}, + {0x1F97A, 0x1F97A}, {0x1F97C, 0x1F97F}, {0x1F980, 0x1F984}, + {0x1F985, 0x1F991}, {0x1F992, 0x1F997}, {0x1F998, 0x1F9A2}, + {0x1F9B0, 0x1F9B9}, {0x1F9C0, 0x1F9C0}, {0x1F9C1, 0x1F9C2}, + {0x1F9D0, 0x1F9E6}, {0x1F9E7, 0x1F9FF}, } var notassigned = table{ ``` Patch was built by having `go-runewidth` only treat Emoji\_Presentation as double-wide, not all Emoji. See: https://unicode.org/Public/emoji/12.0/emoji-data.txt
Author
Owner

@rivo commented on GitHub (Jun 9, 2019):

@calzoneman Interesting observation. Are you sure this is due to tview using go-runewidth or rather tcell using it? These screencasts show misplaced border characters but tview actually places them into specific screen positions and leaves it up to tcell to render them out correctly.

The go-runewidth project says it's a Golang implementation of the POSIX C function wcwidth. (This Javascript port provides some background.)

I wonder if your patch improves go-runewidth generally or if it breaks on some terminals. I think it makes sense to post this as an issue over at https://github.com/mattn/go-runewidth/. If it's an improvement, maybe as a PR?

I'm closing this as it looks like I cannot fix this on my end.

<!-- gh-comment-id:500239633 --> @rivo commented on GitHub (Jun 9, 2019): @calzoneman Interesting observation. Are you sure this is due to `tview` using `go-runewidth` or rather [`tcell`](https://github.com/gdamore/tcell) using it? These screencasts show misplaced border characters but `tview` actually places them into specific screen positions and leaves it up to `tcell` to render them out correctly. The [`go-runewidth` project](https://github.com/mattn/go-runewidth/) says it's a Golang implementation of the [POSIX C function `wcwidth`](http://man7.org/linux/man-pages/man3/wcwidth.3.html). ([This Javascript port](https://github.com/timoxley/wcwidth/blob/5f7935f7df9d4146e001829ed14d1629ced210ba/docs/index.md) provides some background.) I wonder if your patch improves `go-runewidth` generally or if it breaks on some terminals. I think it makes sense to post this as an issue over at https://github.com/mattn/go-runewidth/. If it's an improvement, maybe as a PR? I'm closing this as it looks like I cannot fix this on my end.
Author
Owner

@calzoneman commented on GitHub (Jun 9, 2019):

Are you sure this is due to tview using go-runewidth or rather tcell using it?

In my case, I narrowed down the problem to TextView.draw:

			// Draw the character.
			for offset := screenWidth - 1; offset >= 0; offset-- {
				if offset == 0 {
					screen.SetContent(x+posX+offset, y+line-t.lineOffset, main, comb, style)
				} else {
					screen.SetContent(x+posX+offset, y+line-t.lineOffset, ' ', nil, style)
				}
			}

In this case, screenWidth is calculated by iterateString() which internally calls screenWidth() in util.go, which depends on runewidth directly.

The resulting problem in my terminal was that the cell immediately to the right of the would "stick" to whatever character was previously there, since the text view draw method thinks it is 2 cells wide and thus doesn't clear that cell. Of course, even if tview did clear that cell, there would still be a rendering glitch in that there would be an extra space in terminals that render as one cell, so that's why I opted to patch go-runewidth for my use case.

I wonder if your patch improves go-runewidth generally or if it breaks on some terminals.

I posted it here in case it helps anyone who is searching in this repository -- I agree it might make sense as a runewidth patch but I'm not exactly sure whether it breaks some terminals. As far as I can tell, no one has successfully standardized which characters are double wide, so the whole situation is sort of a mess.

<!-- gh-comment-id:500241133 --> @calzoneman commented on GitHub (Jun 9, 2019): >Are you sure this is due to tview using go-runewidth or rather tcell using it? In my case, I narrowed down the problem to [`TextView.draw`](https://github.com/rivo/tview/blob/8d5eba0c2f51d8ae971c5a470e354bbc2aae6777/textview.go#L923-L930): ```go // Draw the character. for offset := screenWidth - 1; offset >= 0; offset-- { if offset == 0 { screen.SetContent(x+posX+offset, y+line-t.lineOffset, main, comb, style) } else { screen.SetContent(x+posX+offset, y+line-t.lineOffset, ' ', nil, style) } } ``` In this case, `screenWidth` is calculated by `iterateString()` which internally calls `screenWidth()` in util.go, which [depends on `runewidth` directly](https://github.com/rivo/tview/blob/8d5eba0c2f51d8ae971c5a470e354bbc2aae6777/util.go#L427). The resulting problem in my terminal was that the cell immediately to the right of the `™` would "stick" to whatever character was previously there, since the text view draw method thinks it is 2 cells wide and thus doesn't clear that cell. Of course, even if tview did clear that cell, there would still be a rendering glitch in that there would be an extra space in terminals that render `™` as one cell, so that's why I opted to patch go-runewidth for my use case. >I wonder if your patch improves go-runewidth generally or if it breaks on some terminals. I posted it here in case it helps anyone who is searching in this repository -- I agree it might make sense as a runewidth patch but I'm not exactly sure whether it breaks some terminals. As far as I can tell, no one has successfully standardized which characters are double wide, so the whole situation is sort of a mess.
Author
Owner

@rivo commented on GitHub (Jun 9, 2019):

I understand what you're getting at and what you're describing is most likely an issue with tview's dependence on go-runewidth. But from I can see in @SoMuchForSubtlety's screenshots, the problem is bigger than that. Look at this part:

image

The left border characters of the "Info" box don't line up. In some of the lines that contain the symbol, they are shifted to the left by one character. When I draw the Box borders, I place the characters at specific screen positions, as you do in tcell. The fact that they don't end up where they should points to a problem in tcell as well (and it could be the same reason).

Also, as you can see in the code snippet you quoted, I do clear the second cell. The screen buffer should not contain any previous characters anymore. So I think there's a problem here, too. (I've seen this before but I can't reproduce it reliably.)

As for go-runewidth, I wonder if the original wcwidth or any of its descendants (e.g. the Javascript or Python versions) have the same problem as we do. If they don't, maybe it's worth looking at those implementations and making corresponding fixes to go-runewidth.

<!-- gh-comment-id:500244830 --> @rivo commented on GitHub (Jun 9, 2019): I understand what you're getting at and what you're describing is most likely an issue with `tview`'s dependence on `go-runewidth`. But from I can see in @SoMuchForSubtlety's screenshots, the problem is bigger than that. Look at this part: ![image](https://user-images.githubusercontent.com/480930/59164087-e933dc00-8b08-11e9-8119-b00a6346f203.png) The left border characters of the "Info" box don't line up. In some of the lines that contain the `™` symbol, they are shifted to the left by one character. When I draw the `Box` borders, I place the characters at specific screen positions, as you do in `tcell`. The fact that they don't end up where they should points to a problem in `tcell` as well (and it could be the same reason). Also, as you can see in the code snippet you quoted, I _do_ clear the second cell. The screen buffer should not contain any previous characters anymore. So I think there's a problem here, too. (I've seen this before but I can't reproduce it reliably.) As for `go-runewidth`, I wonder if the original `wcwidth` or any of its descendants (e.g. the Javascript or Python versions) have the same problem as we do. If they don't, maybe it's worth looking at those implementations and making corresponding fixes to `go-runewidth`.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/tview#215
No description provided.