git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] git-gui: apply color information from git diff output

From
Pat Thoyts <patthoyts@users.sourceforge.net>
Date
Oct 22, 2010, 10:10 UTC
Message-ID
<87pqv2ttjx.fsf_-_@fox.patthoyts.tk>
In-Reply-To
<FB63A238-C5FD-4A00-9EAD-E99512C9D38B@sb.org>

This patch extracts the ANSI color sequences from git diff output and applies these to the diff view window. This ensures that the gui view makes use of the current git configuration for whitespace display.

ANSI codes may include attributes, foreground and background in a single sequence. Handle this and support bold and reverse attributes. Ignore all other attributes.

Suggested-by: Tor Arvid Lund <torarvid@gmail.com>
Suggested-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
---
Kevin Ballard <kevin@sb.org> writes:
Show 7 quoted lines
>On Oct 21, 2010, at 8:22 AM, Pat Thoyts wrote:
>
>> +	while {[regexp -indices -start $start "\033\\\[(\\d+)?m" $line match code]} {
>
>Git currently doesn't emit combined escapes (e.g. \e[0;31m to reset and then turn on red text), but I can imagine it being enhanced to do this in the future. I would recommend handling it here if you can.
>
>-Kevin Ballard

It turns out that such sequences will be generated by git if the user configures the color.diff.whitespace (eg: bold cyan magenta). This patch handles these cases. I don't see any point trying to handle blink. I could add underline but I don't see that being so appropriate for a GUI. It seems more like something that is configured for a monochrome terminal.

 git-gui.sh   |   10 +++++++++-
 lib/diff.tcl |   34 +++++++++++++++++++++++++++++++++-
 2 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/git-gui.sh b/git-gui.sh
index 1ccaba1..1fb0254 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -3322,8 +3322,16 @@ pack $ui_diff -side left -fill both -expand 1
 pack .vpane.lower.diff.header -side top -fill x
 pack .vpane.lower.diff.body -side bottom -fill both -expand 1
 
+foreach {n c} {0 black 1 red4 2 green4 3 yellow4 4 blue4 5 magenta4 6 cyan4 7 grey60} {
+	$ui_diff tag configure clr4$n -background $c
+	$ui_diff tag configure clri4$n -foreground $c
+	$ui_diff tag configure clr3$n -foreground $c
+	$ui_diff tag configure clri3$n -background $c
+}
+$ui_diff tag configure clr1 -font font_diffbold
+
 $ui_diff tag conf d_cr -elide true
-$ui_diff tag conf d_@ -foreground blue -font font_diffbold
+$ui_diff tag conf d_@ -font font_diffbold
 $ui_diff tag conf d_+ -foreground {#00a000}
 $ui_diff tag conf d_- -foreground red
 
diff --git a/lib/diff.tcl b/lib/diff.tcl
index c628750..dcf0711 100644
--- a/lib/diff.tcl
+++ b/lib/diff.tcl
@@ -294,7 +294,7 @@ proc start_show_diff {cont_info {add_opts {}}} {
 	}
 
 	lappend cmd -p
-	lappend cmd --no-color
+	lappend cmd --color
 	if {$repo_config(gui.diffcontext) >= 1} {
 		lappend cmd "-U$repo_config(gui.diffcontext)"
 	}
@@ -332,6 +332,23 @@ proc start_show_diff {cont_info {add_opts {}}} {
 	fileevent $fd readable [list read_diff $fd $cont_info]
 }
 
+proc parse_color_line {line} {
+	set start 0
+	set result ""
+	set markup [list]
+	set regexp {\033\[((?:\d+;)*\d+)?m}
+	while {[regexp -indices -start $start $regexp $line match code]} {
+		foreach {begin end} $match break
+		append result [string range $line $start [expr {$begin - 1}]]
+		lappend markup [string length $result] \
+			[eval [linsert $code 0 string range $line]]
+		set start [incr end]
+	}
+	append result [string range $line $start end]
+	if {[llength $markup] < 4} {set markup {}}
+	return [list $result $markup]
+}
+
 proc read_diff {fd cont_info} {
 	global ui_diff diff_active is_submodule_diff
 	global is_3way_diff is_conflict_diff current_diff_header
@@ -340,6 +357,9 @@ proc read_diff {fd cont_info} {
 
 	$ui_diff conf -state normal
 	while {[gets $fd line] >= 0} {
+		foreach {line markup} [parse_color_line $line] break
+		set line [string map {\033 ^} $line]
+
 		# -- Cleanup uninteresting diff header lines.
 		#
 		if {$::current_diff_inheader} {
@@ -434,11 +454,23 @@ proc read_diff {fd cont_info} {
 			}
 			}
 		}
+		set mark [$ui_diff index "end - 1 line linestart"]
 		$ui_diff insert end $line $tags
 		if {[string index $line end] eq "\r"} {
 			$ui_diff tag add d_cr {end - 2c}
 		}
 		$ui_diff insert end "\n" $tags
+
+		foreach {posbegin colbegin posend colend} $markup {
+			set prefix clr
+			foreach style [split $colbegin ";"] {
+				if {$style eq "7"} {append prefix i; continue}
+				if {$style < 30 || $style > 47} {continue}
+				set a "$mark linestart + $posbegin chars"
+				set b "$mark linestart + $posend chars"
+				catch {$ui_diff tag add $prefix$style $a $b}
+			}
+		}
 	}
 	$ui_diff conf -state disabled
 
-- 
1.7.3.1.msysgit.0
Previous: Pat ThoytsNext: Tor Arvid Lund
Message 13 of 14 in “Colored whitespace in git gui”
  1. Tor Arvid LundOct 18, 2010
  2. git-gui: highlight trailing whitespace in diff viewPat Thoyts, Oct 19, 2010
  3. Tor Arvid LundOct 20, 2010
  4. git-gui: support core.whitespace rules in diff viewPat Thoyts, Oct 20, 2010
  5. Junio C HamanoOct 20, 2010
  6. Tor Arvid LundOct 21, 2010
  7. Pat ThoytsOct 21, 2010
  8. Tor Arvid LundOct 22, 2010
  9. Pat ThoytsOct 22, 2010
  10. git-gui: apply color information from git diffPat Thoyts, Oct 21, 2010
  11. Kevin BallardOct 21, 2010
  12. Pat ThoytsOct 21, 2010
  13. git-gui: apply color information from git diff outputPat Thoyts, Oct 22, 2010
  14. Tor Arvid LundOct 22, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.