diff --git a/tools/wcswidth/truncate.go b/tools/wcswidth/truncate.go index 00c00bd72..d61ceed0c 100644 --- a/tools/wcswidth/truncate.go +++ b/tools/wcswidth/truncate.go @@ -5,6 +5,8 @@ package wcswidth import ( "errors" "fmt" + "strconv" + "kitty/tools/utils" ) @@ -25,8 +27,21 @@ type truncate_iterator struct { limit_exceeded_at *truncate_error } -func (self *truncate_iterator) handle_csi(body []byte) error { - self.pos += len(body) + 2 +func (self *truncate_iterator) handle_csi(csi []byte) error { + if len(csi) > 1 && csi[len(csi)-1] == 'b' { // repeat previous char escape code + num_string := utils.UnsafeBytesToString(csi[:len(csi)-1]) + n, err := strconv.Atoi(num_string) + if err == nil && n > 0 { + width_before_repeat := self.w.current_width + for ; n > 0; n-- { + self.w.handle_rune(self.w.prev_ch) + if self.w.current_width > self.limit { + return &truncate_error{pos: self.pos, width: width_before_repeat} + } + } + } + } + self.pos += len(csi) + 2 return nil } diff --git a/tools/wcswidth/wcswidth_test.go b/tools/wcswidth/wcswidth_test.go index c21f00a2c..fd283b89a 100644 --- a/tools/wcswidth/wcswidth_test.go +++ b/tools/wcswidth/wcswidth_test.go @@ -61,6 +61,8 @@ func TestWCSWidth(t *testing.T) { truncate("a🌷\ufe0e", 2, "a🌷\ufe0e", 2) truncate("a🌷\ufe0eb", 3, "a🌷\ufe0eb", 3) truncate("a\x1b[31mb", 2, "a\x1b[31mb", 2) + truncate("a\x1b[7bb", 2, "a", 1) + truncate("a\x1b[3bbc", 5, "a\x1b[3bb", 5) } func TestCellIterator(t *testing.T) {