From ccf1dfabbcc26f1b2c04b7403d78aa6ec73d4b01 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 23 Mar 2023 15:52:43 +0530 Subject: [PATCH] Fix highlighting of center changes --- tools/cmd/diff/collect.go | 7 +++---- tools/cmd/diff/highlight.go | 7 +++---- tools/cmd/diff/patch.go | 15 +++++++------- tools/cmd/diff/render.go | 40 +++++++++++++------------------------ 4 files changed, 27 insertions(+), 42 deletions(-) diff --git a/tools/cmd/diff/collect.go b/tools/cmd/diff/collect.go index cf52ffc9e..740aa9e20 100644 --- a/tools/cmd/diff/collect.go +++ b/tools/cmd/diff/collect.go @@ -103,9 +103,9 @@ func hash_for_path(path string) (string, error) { } +// Remove all control codes except newlines func sanitize_control_codes(x string) string { - // exclude newlines, carriage returns and tabs - pat := utils.MustCompile("[\x00-\x08\x0b\x0c\x0e-\x1f\x7f\u0080-\u009f]") + pat := utils.MustCompile("[\x00-\x09\x0b-\x1f\x7f\u0080-\u009f]") return pat.ReplaceAllLiteralString(x, "░") } @@ -114,8 +114,7 @@ func sanitize_tabs_and_carriage_returns(x string) string { } func sanitize(x string) string { - x = sanitize_control_codes(x) - return sanitize_tabs_and_carriage_returns(x) + return sanitize_control_codes(sanitize_tabs_and_carriage_returns(x)) } func text_to_lines(text string) []string { diff --git a/tools/cmd/diff/highlight.go b/tools/cmd/diff/highlight.go index f689c701c..7ba20839c 100644 --- a/tools/cmd/diff/highlight.go +++ b/tools/cmd/diff/highlight.go @@ -123,7 +123,7 @@ func ansi_formatter(w io.Writer, style *chroma.Style, it chroma.Iterator) error } // independently format each line in a multiline token, needed for the diff kitten highlighting to work, also // pagers like less reset SGR formatting at line boundaries - text := token.Value + text := sanitize(token.Value) for text != "" { idx := strings.IndexByte(text, '\n') if idx < 0 { @@ -152,7 +152,6 @@ func highlight_file(path string) (highlighted string, err error) { if err != nil { return "", err } - text = sanitize_control_codes(text) lexer := lexers.Match(filename_for_detection) if lexer == nil { if err == nil { @@ -191,7 +190,7 @@ func highlight_file(path string) (highlighted string, err error) { w := strings.Builder{} w.Grow(len(text) * 2) err = formatter.Format(&w, style, iterator) - // os.WriteFile(path+".highlighted", []byte(w.String()), 0o600) + // os.WriteFile(filepath.Base(path+".highlighted"), []byte(w.String()), 0o600) return w.String(), err } @@ -202,7 +201,7 @@ func highlight_all(paths []string) { path := paths[i] raw, err := highlight_file(path) if err == nil { - highlighted_lines_cache.Set(path, text_to_lines(sanitize_tabs_and_carriage_returns(raw))) + highlighted_lines_cache.Set(path, text_to_lines(raw)) } } }) diff --git a/tools/cmd/diff/patch.go b/tools/cmd/diff/patch.go index 81286963b..ed8cdec36 100644 --- a/tools/cmd/diff/patch.go +++ b/tools/cmd/diff/patch.go @@ -60,7 +60,7 @@ func set_diff_command(q string) error { return nil } -type Center struct{ prefix_count, suffix_count int } +type Center struct{ offset, left_size, right_size int } type Chunk struct { is_context bool @@ -82,18 +82,17 @@ func (self *Chunk) context_line() { self.right_count++ } -func changed_center(left, right string) (ans struct{ prefix_count, suffix_count int }) { +func changed_center(left, right string) (ans Center) { if len(left) > 0 && len(right) > 0 { ll, rl := len(left), len(right) ml := utils.Min(ll, rl) - for ans.prefix_count < ml && left[ans.prefix_count] == right[ans.prefix_count] { - ans.prefix_count++ + for ; ans.offset < ml && left[ans.offset] == right[ans.offset]; ans.offset++ { } - if ans.prefix_count < ml { - for ans.suffix_count < ml-ans.prefix_count && left[ll-1-ans.suffix_count] == right[rl-1-ans.suffix_count] { - ans.suffix_count++ - } + suffix_count := 0 + for ; suffix_count < ml && left[ll-1-suffix_count] == right[rl-1-suffix_count]; suffix_count++ { } + ans.left_size = ll - suffix_count - ans.offset + ans.right_size = rl - suffix_count - ans.offset } return } diff --git a/tools/cmd/diff/render.go b/tools/cmd/diff/render.go index c1e6adb29..290027301 100644 --- a/tools/cmd/diff/render.go +++ b/tools/cmd/diff/render.go @@ -4,6 +4,7 @@ package diff import ( "fmt" + "kitty/tools/tui/sgr" "kitty/tools/utils" "kitty/tools/utils/style" "kitty/tools/wcswidth" @@ -71,7 +72,7 @@ func place_in(text string, sz int) string { return fill_in(fit_in(text, sz), sz) } -var title_format, text_format, margin_format, added_format, removed_format, added_margin_format, removed_margin_format, filler_format, margin_filler_format, hunk_margin_format, hunk_format, added_center, removed_center, statusline_format, added_count_format, removed_count_format, message_format func(...any) string +var title_format, text_format, margin_format, added_format, removed_format, added_margin_format, removed_margin_format, filler_format, margin_filler_format, hunk_margin_format, hunk_format, statusline_format, added_count_format, removed_count_format, message_format func(...any) string func create_formatters() { ctx := style.Context{AllowEscapeCodes: true} @@ -94,31 +95,17 @@ func create_formatters() { hunk_format = ctx.SprintFunc(fmt.Sprintf("fg=%s bg=%s", conf.Margin_fg.AsRGBSharp(), conf.Hunk_bg.AsRGBSharp())) hunk_margin_format = ctx.SprintFunc(fmt.Sprintf("fg=%s bg=%s", conf.Margin_fg.AsRGBSharp(), conf.Hunk_margin_bg.AsRGBSharp())) message_format = ctx.SprintFunc("bold") - make_bracketer := func(start, end string) func(...any) string { - s, e := ctx.SprintFunc(start), ctx.SprintFunc(end) - end = e(" ") - idx := strings.LastIndexByte(end, ' ') - end = end[:idx] - start = s(" ") - idx = strings.LastIndexByte(start, ' ') - start = start[:idx] - - return func(args ...any) string { - return start + fmt.Sprint(args) + end - } - } - added_center = make_bracketer("bg="+conf.Highlight_added_bg.AsRGBSharp(), "bg="+conf.Added_bg.AsRGBSharp()) - removed_center = make_bracketer("bg="+conf.Highlight_removed_bg.AsRGBSharp(), "bg="+conf.Removed_bg.AsRGBSharp()) } -func highlight_boundaries(ltype, text string) string { +func center_span(ltype string, offset, size int) *sgr.Span { + ans := sgr.NewSpan(offset, size) switch ltype { case "add": - return added_center(text) + ans.SetBackground(conf.Highlight_added_bg).SetClosingBackground(conf.Added_bg) case "remove": - return removed_center(text) + ans.SetBackground(conf.Highlight_removed_bg).SetClosingBackground(conf.Removed_bg) } - return text + return ans } func title_lines(left_path, right_path string, columns, margin_size int, ans []*LogicalLine) []*LogicalLine { @@ -333,12 +320,13 @@ func splitlines(text string, width int) []string { } func render_half_line(line_number int, line, ltype string, margin_size, available_cols int, center Center, ans []string) []string { - if center.prefix_count > 0 { - line_sz := len(line) - if center.prefix_count+center.suffix_count < line_sz { - end := len(line) - center.suffix_count - line = line[:center.prefix_count] + highlight_boundaries(ltype, line[center.prefix_count:end]) + line[end:] - } + size := center.left_size + if ltype != "remove" { + size = center.right_size + } + if size > 0 { + span := center_span(ltype, center.offset, size) + line = sgr.InsertFormatting(line, span) } lnum := strconv.Itoa(line_number + 1) for _, sc := range splitlines(line, available_cols) {