From cb99fbd83ce057ccb564aeda3fedf9309e0d696f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 29 Mar 2023 20:41:05 +0530 Subject: [PATCH] Dont remove leading and trailing spaces when wrapping Without this we lose some spaces and also there was a case where the line could end up longer than the specified width. --- tools/utils/style/indent-and-wrap.go | 42 +++-------------------- tools/utils/style/indent-and-wrap_test.go | 35 ++++++++++++------- 2 files changed, 27 insertions(+), 50 deletions(-) diff --git a/tools/utils/style/indent-and-wrap.go b/tools/utils/style/indent-and-wrap.go index 8fd8c667b..cfb8a6d5d 100644 --- a/tools/utils/style/indent-and-wrap.go +++ b/tools/utils/style/indent-and-wrap.go @@ -261,24 +261,13 @@ func (self hyperlink_state) as_escape_codes(for_close bool) string { } type line_builder struct { - buf []byte - last_text_pos, cursor_pos int + buf []byte + cursor_pos int } func (self *line_builder) reset() string { ans := string(self.buf) - if len(ans) > self.last_text_pos { - prefix := ans[:self.last_text_pos] - suffix := ans[self.last_text_pos:] - prefix = strings.TrimRightFunc(prefix, unicode.IsSpace) - if len(prefix) != self.last_text_pos { - ans = prefix + suffix - } - } else { - ans = strings.TrimRightFunc(ans, unicode.IsSpace) - } self.buf = self.buf[:0] - self.last_text_pos = 0 self.cursor_pos = 0 return ans } @@ -289,13 +278,11 @@ func (self *line_builder) has_space_for_width(w, max_width int) bool { func (self *line_builder) add_char(ch rune) { self.buf = utf8.AppendRune(self.buf, ch) - self.last_text_pos = len(self.buf) self.cursor_pos += wcswidth.Runewidth(ch) } func (self *line_builder) add_word(word []byte, width int) { self.buf = append(self.buf, word...) - self.last_text_pos = len(self.buf) self.cursor_pos += width } @@ -351,27 +338,6 @@ func (self *word_builder) recalculate_width() { self.wcswidth.Parse(self.buf) } -func (self *word_builder) trim_leading_spaces() { - if self.is_empty() { - return - } - s := utils.UnsafeBytesToString(self.buf) - var before, after string - if self.text_start_position != 0 { - before, after = s[:self.text_start_position-1], s[self.text_start_position-1:] - } else { - after = s - } - q := strings.TrimLeftFunc(after, unicode.IsSpace) - if q != after { - self.buf = make([]byte, 0, len(s)) - self.buf = append(self.buf, before...) - self.buf = append(self.buf, q...) - self.text_start_position = len(before) + 1 - self.recalculate_width() - } -} - func (self *word_builder) add_rune(ch rune) (num_bytes_written int) { before := len(self.buf) self.buf = utf8.AppendRune(self.buf, ch) @@ -433,7 +399,6 @@ func (self *wrapper) print_word() { w := self.current_word.width() if !self.current_line.has_space_for_width(w, self.width) { self.end_current_line() - self.current_word.trim_leading_spaces() w = self.current_word.width() } for _, e := range self.current_word.escape_codes { @@ -454,6 +419,9 @@ func (self *wrapper) handle_rune(ch rune) error { self.end_current_line() } else if self.current_word.has_text() && ch != 0xa0 && unicode.IsSpace(ch) { self.print_word() + if self.current_line.cursor_pos >= self.width { + self.end_current_line() + } self.current_line.add_char(ch) } else { num_of_bytes_written := self.current_word.add_rune(ch) diff --git a/tools/utils/style/indent-and-wrap_test.go b/tools/utils/style/indent-and-wrap_test.go index 8cedc744a..6f94a922e 100644 --- a/tools/utils/style/indent-and-wrap_test.go +++ b/tools/utils/style/indent-and-wrap_test.go @@ -8,29 +8,38 @@ import ( ) func TestFormatWithIndent(t *testing.T) { - indent := "__" - screen_width := 11 + + screen_width, indent := 0, "" tx := func(text string, expected ...string) { q := indent + strings.Join(expected, "") actual := WrapText(text, indent, screen_width) if actual != q { - t.Fatalf("%#v\nexpected: %#v\nactual: %#v", text, q, actual) + t.Fatalf("\nFailed for: %#v\nexpected: %#v\nactual: %#v", text, q, actual) } } - tx("testing\n\ntwo", "testing\n\n__two") - tx("testing\n \ntwo", "testing\n\n__two") - a := strings.Repeat("a", screen_width-len(indent)-1) - tx(a+" b", a+"\n__b") + indent = "" + screen_width = 4 + tx("one two", "one \ntwo") + tx("a b", "a b") + screen_width = 3 + tx("one tw", "one\n tw") - tx("123456 \x1b[31m789a", "123456\n__\x1b[31m789a") - tx("12 \x1b[31m789 abcd", "12 \x1b[31m789\n\x1b[39m__\x1b[31mabcd") - tx("bb \x1b]8;;http://xyz.com\x1b\\text\x1b]8;;\x1b\\ two", "bb \x1b]8;;http://xyz.com\x1b\\text\x1b]8;;\x1b\\\n__two") - tx("\x1b[31maaaaaa \x1b[39mbbbbbb", "\x1b[31maaaaaa\n\x1b[39m__\x1b[31m\x1b[39mbbbbbb") + indent = "__" + screen_width = 11 + tx("testing\n\ntwo", "testing\n\n__two") + tx("testing\n \ntwo", "testing\n__ \n__two") + a := strings.Repeat("a", screen_width-len(indent)-1) + tx(a+" b", a+" \n__b") + + tx("123456 \x1b[31m789a", "123456 \n__\x1b[31m789a") + tx("12 \x1b[31m789 abcd", "12 \x1b[31m789 \n\x1b[39m__\x1b[31mabcd") + tx("bb \x1b]8;;http://xyz.com\x1b\\text\x1b]8;;\x1b\\ two", "bb \x1b]8;;http://xyz.com\x1b\\text\x1b]8;;\x1b\\ \n__two") + tx("\x1b[31maaaaaa \x1b[39mbbbbbb", "\x1b[31maaaaaa \n\x1b[39m__\x1b[31m\x1b[39mbbbbbb") tx( "\x1b[31;4:3m\x1b]8;;XXX\x1b\\combined using\x1b]8;;\x1b\\ operators", - "\x1b[31;4:3m\x1b]8;;XXX\x1b\\combined\n\x1b[4:0;39m\x1b]8;;\x1b\\__\x1b[4:3;31m\x1b]8;;XXX\x1b\\using\x1b]8;;\x1b\\\n\x1b[4:0;39m__\x1b[4:3;31moperators") + "\x1b[31;4:3m\x1b]8;;XXX\x1b\\combined \n\x1b[4:0;39m\x1b]8;;\x1b\\__\x1b[4:3;31m\x1b]8;;XXX\x1b\\using\x1b]8;;\x1b\\ \n\x1b[4:0;39m__\x1b[4:3;31moperators") indent = "" screen_width = 3 tx("one", "one") @@ -41,6 +50,6 @@ func TestFormatWithIndent(t *testing.T) { screen_width = 8 tx( "\x1b[1mbold\x1b[221m no more bold", - "\x1b[1mbold\x1b[221m no\nmore\nbold", + "\x1b[1mbold\x1b[221m no \nmore \nbold", ) }