diff --git a/misc/codepoint_width.c b/misc/codepoint_width.c index 39808631f1..0c500adff9 100644 --- a/misc/codepoint_width.c +++ b/misc/codepoint_width.c @@ -693,6 +693,12 @@ int term_disp_width(bstr str, int max_width, const unsigned char **cut_pos) goto next; } + if (cp == '\t') { + // Assume tabstop width is 8 + current_width = 8 - width % 8; + goto next; + } + if (cp < 0x20) goto next; @@ -736,8 +742,8 @@ int term_disp_width(bstr str, int max_width, const unsigned char **cut_pos) str = cluster_end; } -next: current_width = MPMIN(current_width, 2); +next: if (width + current_width > max_width) { assert(prev_pos < str.start + str.len); *cut_pos = prev_pos; diff --git a/test/codepoint_width.c b/test/codepoint_width.c index 8f9fcd45ab..f4358e5ae3 100644 --- a/test/codepoint_width.c +++ b/test/codepoint_width.c @@ -46,7 +46,7 @@ int main(void) { assert_int_equal(W("\U0001F1F5\U0001F1F1"), 2); assert_int_equal(W("\n"), 0); // Newline (should not take up any visual space) - assert_int_equal(W("\t"), 0); // Tab (no visual width itself) + assert_int_equal(W("\t"), 8); // Tab (tabstop assumend to be 8) assert_int_equal(W("\0"), 0); // Null character (non-visible) assert_int_equal(W("A\u3042"), 3); // ASCII 'A' + full-width Japanese Hiragana 'あ' (U+3042) @@ -56,7 +56,7 @@ int main(void) { assert_int_equal(W("\U0001F469\u200D\u2764\uFE0F\u200D\U0001F469A\u3042"), 5); assert_int_equal(W("A\nB"), 2); // ASCII characters with newline (newline should not affect width) - assert_int_equal(W("ABC\tDEF"), 6); // Tab inside a string (no visual width for '\t') + assert_int_equal(W("ABC\tDEF"), 11); // Tab inside a string // ASCII characters with color assert_int_equal(W("\033[31mABC\033[0m\033[32mDEF\033[0m"), 6);