From 908c35850a9aed6efd1a6a616e594a28467230fa Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 20 May 2006 09:38:11 +1000 Subject: gitk: Make a row of controls for controlling highlighting Now there is a bar across the middle (just below the bar containing the sha1 ID, find string etc.) which controls highlighting. There are three ways to highlight: the user can highlight commits affecting a list of paths, commits in a view, or commits where the author or committer matches any of a list of strings (case-insensitive). The elements of the list of paths and list of names are delimited by whitespace with shell quoting rules. Signed-off-by: Paul Mackerras --- gitk | 365 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 298 insertions(+), 67 deletions(-) diff --git a/gitk b/gitk index d59debf2f5..584a95e062 100755 --- a/gitk +++ b/gitk @@ -187,7 +187,7 @@ proc getcommitlines {fd view} { if {$view == $curview} { layoutmore } elseif {[info exists hlview] && $view == $hlview} { - highlightmore + vhighlightmore } } if {[clock clicks -milliseconds] >= $nextupdate} { @@ -223,7 +223,7 @@ proc readcommit {id} { proc updatecommits {} { global viewdata curview phase displayorder - global children commitrow + global children commitrow selectedline thickerline if {$phase ne {}} { stop_rev_list @@ -235,6 +235,8 @@ proc updatecommits {} { catch {unset commitrow($n,$id)} } set curview -1 + catch {unset selectedline} + catch {unset thickerline} catch {unset viewdata($n)} readrefs showview $n @@ -381,6 +383,7 @@ proc makewindow {} { global entries sha1entry sha1string sha1but global maincursor textcursor curtextcursor global rowctxmenu mergemax + global highlight_files highlight_names menu .bar .bar add cascade -label "File" -menu .bar.file @@ -396,20 +399,14 @@ proc makewindow {} { .bar.edit configure -font $uifont menu .bar.view -font $uifont - menu .bar.view.hl -font $uifont -tearoff 0 .bar add cascade -label "View" -menu .bar.view .bar.view add command -label "New view..." -command {newview 0} .bar.view add command -label "Edit view..." -command editview \ -state disabled .bar.view add command -label "Delete view" -command delview -state disabled - .bar.view add cascade -label "Highlight" -menu .bar.view.hl .bar.view add separator .bar.view add radiobutton -label "All files" -command {showview 0} \ -variable selectedview -value 0 - .bar.view.hl add command -label "New view..." -command {newview 1} - .bar.view.hl add command -label "Remove" -command delhighlight \ - -state disabled - .bar.view.hl add separator menu .bar.help .bar add cascade -label "Help" -menu .bar.help @@ -436,6 +433,8 @@ proc makewindow {} { } frame .ctop.top frame .ctop.top.bar + frame .ctop.top.lbar + pack .ctop.top.lbar -side bottom -fill x pack .ctop.top.bar -side bottom -fill x set cscroll .ctop.top.csb scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0 @@ -497,7 +496,7 @@ proc makewindow {} { set findstring {} set fstring .ctop.top.bar.findstring lappend entries $fstring - entry $fstring -width 30 -font $textfont -textvariable findstring -font $textfont + entry $fstring -width 30 -font $textfont -textvariable findstring pack $fstring -side left -expand 1 -fill x set findtype Exact set findtypemenu [tk_optionMenu .ctop.top.bar.findtype \ @@ -515,6 +514,29 @@ proc makewindow {} { # for making sure type==Exact whenever loc==Pickaxe trace add variable findloc write findlocchange + label .ctop.top.lbar.flabel -text "Highlight: Commits touching paths:" \ + -font $uifont + pack .ctop.top.lbar.flabel -side left -fill y + entry .ctop.top.lbar.fent -width 25 -font $textfont \ + -textvariable highlight_files + trace add variable highlight_files write hfiles_change + lappend entries .ctop.top.lbar.fent + pack .ctop.top.lbar.fent -side left -fill x -expand 1 + label .ctop.top.lbar.vlabel -text " OR in view" -font $uifont + pack .ctop.top.lbar.vlabel -side left -fill y + global viewhlmenu selectedhlview + set viewhlmenu [tk_optionMenu .ctop.top.lbar.vhl selectedhlview None] + $viewhlmenu entryconf 0 -command delvhighlight + pack .ctop.top.lbar.vhl -side left -fill y + label .ctop.top.lbar.alabel -text " OR author/committer:" \ + -font $uifont + pack .ctop.top.lbar.alabel -side left -fill y + entry .ctop.top.lbar.aent -width 20 -font $textfont \ + -textvariable highlight_names + trace add variable highlight_names write hnames_change + lappend entries .ctop.top.lbar.aent + pack .ctop.top.lbar.aent -side right -fill x -expand 1 + panedwindow .ctop.cdet -orient horizontal .ctop add .ctop.cdet frame .ctop.cdet.left @@ -664,6 +686,7 @@ proc canvscan {op w x y} { proc scrollcanv {cscroll f0 f1} { $cscroll set $f0 $f1 drawfrac $f0 $f1 + flushhighlights } # when we make a key binding for the toplevel, make sure @@ -1313,25 +1336,27 @@ proc vieweditor {top n title} { focus $top.t } -proc doviewmenu {m first cmd op args} { +proc doviewmenu {m first cmd op argv} { set nmenu [$m index end] for {set i $first} {$i <= $nmenu} {incr i} { if {[$m entrycget $i -command] eq $cmd} { - eval $m $op $i $args + eval $m $op $i $argv break } } } proc allviewmenus {n op args} { + global viewhlmenu + doviewmenu .bar.view 7 [list showview $n] $op $args - doviewmenu .bar.view.hl 3 [list addhighlight $n] $op $args + doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args } proc newviewok {top n} { global nextviewnum newviewperm newviewname newishighlight global viewname viewfiles viewperm selectedview curview - global viewargs newviewargs + global viewargs newviewargs viewhlmenu if {[catch { set newargs [shellsplit $newviewargs($n)] @@ -1359,14 +1384,17 @@ proc newviewok {top n} { if {!$newishighlight} { after idle showview $n } else { - after idle addhighlight $n + after idle addvhighlight $n } } else { # editing an existing view set viewperm($n) $newviewperm($n) if {$newviewname($n) ne $viewname($n)} { set viewname($n) $newviewname($n) - allviewmenus $n entryconf -label $viewname($n) + doviewmenu .bar.view 7 [list showview $n] \ + entryconf [list -label $viewname($n)] + doviewmenu $viewhlmenu 1 [list addvhighlight $n] \ + entryconf [list -label $viewname($n) -value $viewname($n)] } if {$files ne $viewfiles($n) || $newargs ne $viewargs($n)} { set viewfiles($n) $files @@ -1380,9 +1408,13 @@ proc newviewok {top n} { } proc delview {} { - global curview viewdata viewperm + global curview viewdata viewperm hlview selectedhlview if {$curview == 0} return + if {[info exists hlview] && $hlview == $curview} { + set selectedhlview None + unset hlview + } allviewmenus $curview delete set viewdata($curview) {} set viewperm($curview) 0 @@ -1390,12 +1422,12 @@ proc delview {} { } proc addviewmenu {n} { - global viewname + global viewname viewhlmenu .bar.view add radiobutton -label $viewname($n) \ -command [list showview $n] -variable selectedview -value $n - .bar.view.hl add radiobutton -label $viewname($n) \ - -command [list addhighlight $n] -variable selectedhlview -value $n + $viewhlmenu add radiobutton -label $viewname($n) \ + -command [list addvhighlight $n] -variable selectedhlview } proc flatten {var} { @@ -1427,8 +1459,9 @@ proc showview {n} { global pending_select phase global commitidx rowlaidout rowoptim linesegends global commfd nextupdate - global selectedview hlview selectedhlview + global selectedview global vparentlist vchildlist vdisporder vcmitlisted + global hlview selectedhlview if {$n == $curview} return set selid {} @@ -1467,14 +1500,15 @@ proc showview {n} { catch {unset matchinglines} catch {unset treediffs} clear_display + if {[info exists hlview] && $hlview == $n} { + unset hlview + set selectedhlview None + } set curview $n set selectedview $n - set selectedhlview -1 .bar.view entryconf 2 -state [expr {$n == 0? "disabled": "normal"}] .bar.view entryconf 3 -state [expr {$n == 0? "disabled": "normal"}] - catch {unset hlview} - .bar.view.hl entryconf 1 -state disabled if {![info exists viewdata($n)]} { set pending_select $selid @@ -1539,18 +1573,66 @@ proc showview {n} { } } -proc addhighlight {n} { - global hlview curview viewdata highlighted highlightedrows - global selectedhlview +# Stuff relating to the highlighting facility + +proc ishighlighted {row} { + global vhighlights fhighlights nhighlights + + if {[info exists nhighlights($row)] && $nhighlights($row) > 0} { + return $nhighlights($row) + } + if {[info exists vhighlights($row)] && $vhighlights($row) > 0} { + return $vhighlights($row) + } + if {[info exists fhighlights($row)] && $fhighlights($row) > 0} { + return $fhighlights($row) + } + return 0 +} + +proc bolden {row font} { + global canv linehtag selectedline + + $canv itemconf $linehtag($row) -font $font + if {$row == $selectedline} { + $canv delete secsel + set t [eval $canv create rect [$canv bbox $linehtag($row)] \ + -outline {{}} -tags secsel \ + -fill [$canv cget -selectbackground]] + $canv lower $t + } +} + +proc bolden_name {row font} { + global canv2 linentag selectedline + + $canv2 itemconf $linentag($row) -font $font + if {$row == $selectedline} { + $canv2 delete secsel + set t [eval $canv2 create rect [$canv2 bbox $linentag($row)] \ + -outline {{}} -tags secsel \ + -fill [$canv2 cget -selectbackground]] + $canv2 lower $t + } +} + +proc unbolden {rows} { + global mainfont + + foreach row $rows { + if {![ishighlighted $row]} { + bolden $row $mainfont + } + } +} + +proc addvhighlight {n} { + global hlview curview viewdata vhl_done vhighlights commitidx if {[info exists hlview]} { - delhighlight + delvhighlight } set hlview $n - set selectedhlview $n - .bar.view.hl entryconf 1 -state normal - set highlighted($n) 0 - set highlightedrows {} if {$n != $curview && ![info exists viewdata($n)]} { set viewdata($n) [list getcommits {{}} {{}} {} {} {} 0 0 0 {}] set vparentlist($n) {} @@ -1558,34 +1640,29 @@ proc addhighlight {n} { set vdisporder($n) {} set vcmitlisted($n) {} start_rev_list $n - } else { - highlightmore + } + set vhl_done $commitidx($hlview) + if {$vhl_done > 0} { + drawvisible } } -proc delhighlight {} { - global hlview highlightedrows canv linehtag mainfont - global selectedhlview selectedline +proc delvhighlight {} { + global hlview vhighlights + global selectedline if {![info exists hlview]} return unset hlview - set selectedhlview {} - .bar.view.hl entryconf 1 -state disabled - foreach l $highlightedrows { - $canv itemconf $linehtag($l) -font $mainfont - if {$l == $selectedline} { - $canv delete secsel - set t [eval $canv create rect [$canv bbox $linehtag($l)] \ - -outline {{}} -tags secsel \ - -fill [$canv cget -selectbackground]] - $canv lower $t - } + set rows [array names vhighlights] + if {$rows ne {}} { + unset vhighlights + unbolden $rows } } -proc highlightmore {} { - global hlview highlighted commitidx highlightedrows linehtag mainfont - global displayorder vdisporder curview canv commitrow selectedline +proc vhighlightmore {} { + global hlview vhl_done commitidx vhighlights + global displayorder vdisporder curview mainfont set font [concat $mainfont bold] set max $commitidx($hlview) @@ -1594,25 +1671,158 @@ proc highlightmore {} { } else { set disp $vdisporder($hlview) } - for {set i $highlighted($hlview)} {$i < $max} {incr i} { + set vr [visiblerows] + set r0 [lindex $vr 0] + set r1 [lindex $vr 1] + for {set i $vhl_done} {$i < $max} {incr i} { set id [lindex $disp $i] if {[info exists commitrow($curview,$id)]} { set row $commitrow($curview,$id) - if {[info exists linehtag($row)]} { - $canv itemconf $linehtag($row) -font $font - lappend highlightedrows $row - if {$row == $selectedline} { - $canv delete secsel - set t [eval $canv create rect \ - [$canv bbox $linehtag($row)] \ - -outline {{}} -tags secsel \ - -fill [$canv cget -selectbackground]] - $canv lower $t + if {$r0 <= $row && $row <= $r1} { + if {![highlighted $row]} { + bolden $row $font } + set vhighlights($row) 1 } } } - set highlighted($hlview) $max + set vhl_done $max +} + +proc askvhighlight {row id} { + global hlview vhighlights commitrow iddrawn mainfont + + if {[info exists commitrow($hlview,$id)]} { + if {[info exists iddrawn($id)] && ![ishighlighted $row]} { + bolden $row [concat $mainfont bold] + } + set vhighlights($row) 1 + } else { + set vhighlights($row) 0 + } +} + +proc hfiles_change {name ix op} { + global highlight_files filehighlight fhighlights fh_serial + global mainfont + + if {[info exists filehighlight]} { + # delete previous highlights + catch {close $filehighlight} + unset filehighlight + set rows [array names fhighlights] + if {$rows ne {}} { + unset fhighlights + unbolden $rows + } + } + after cancel do_file_hl $fh_serial + incr fh_serial + if {$highlight_files ne {}} { + after 300 do_file_hl $fh_serial + } +} + +proc do_file_hl {serial} { + global highlight_files filehighlight + + if {[catch {set paths [shellsplit $highlight_files]}]} return + set cmd [concat | git-diff-tree -r -s --stdin -- $paths] + set filehighlight [open $cmd r+] + fconfigure $filehighlight -blocking 0 + fileevent $filehighlight readable readfhighlight + drawvisible + flushhighlights +} + +proc flushhighlights {} { + global filehighlight + + if {[info exists filehighlight]} { + puts $filehighlight "" + flush $filehighlight + } +} + +proc askfilehighlight {row id} { + global filehighlight fhighlights + + set fhighlights($row) 0 + puts $filehighlight $id +} + +proc readfhighlight {} { + global filehighlight fhighlights commitrow curview mainfont iddrawn + + set n [gets $filehighlight line] + if {$n < 0} { + if {[eof $filehighlight]} { + # strange... + puts "oops, git-diff-tree died" + catch {close $filehighlight} + unset filehighlight + } + return + } + set line [string trim $line] + if {$line eq {}} return + if {![info exists commitrow($curview,$line)]} return + set row $commitrow($curview,$line) + if {[info exists iddrawn($line)] && ![ishighlighted $row]} { + bolden $row [concat $mainfont bold] + } + set fhighlights($row) 1 +} + +proc hnames_change {name ix op} { + global highlight_names nhighlights nhl_names mainfont + + # delete previous highlights, if any + set rows [array names nhighlights] + if {$rows ne {}} { + foreach row $rows { + if {$nhighlights($row) >= 2} { + bolden_name $row $mainfont + } + } + unset nhighlights + unbolden $rows + } + if {[catch {set nhl_names [shellsplit $highlight_names]}]} { + set nhl_names {} + return + } + drawvisible +} + +proc asknamehighlight {row id} { + global nhl_names nhighlights commitinfo iddrawn mainfont + + if {![info exists commitinfo($id)]} { + getcommit $id + } + set isbold 0 + set author [lindex $commitinfo($id) 1] + set committer [lindex $commitinfo($id) 3] + foreach name $nhl_names { + set pattern "*$name*" + if {[string match -nocase $pattern $author]} { + set isbold 2 + break + } + if {!$isbold && [string match -nocase $pattern $committer]} { + set isbold 1 + } + } + if {[info exists iddrawn($id)]} { + if {$isbold && ![ishighlighted $row]} { + bolden $row [concat $mainfont bold] + } + if {$isbold >= 2} { + bolden_name $row [concat $mainfont bold] + } + } + set nhighlights($row) $isbold } # Graph layout functions @@ -2335,7 +2545,6 @@ proc drawcmittext {id row col rmx} { global rowtextx idpos idtags idheads idotherrefs global linehtag linentag linedtag global mainfont canvxmax - global hlview commitrow highlightedrows set ofill [expr {[lindex $commitlisted $row]? "blue": "white"}] set x [xc $row $col] @@ -2361,15 +2570,19 @@ proc drawcmittext {id row col rmx} { set date [lindex $commitinfo($id) 2] set date [formatdate $date] set font $mainfont - if {[info exists hlview] && [info exists commitrow($hlview,$id)]} { + set nfont $mainfont + set isbold [ishighlighted $row] + if {$isbold > 0} { lappend font bold - lappend highlightedrows $row + if {$isbold > 1} { + lappend nfont bold + } } set linehtag($row) [$canv create text $xt $y -anchor w \ -text $headline -font $font] $canv bind $linehtag($row) "rowmenu %X %Y $id" set linentag($row) [$canv2 create text 3 $y -anchor w \ - -text $name -font $mainfont] + -text $name -font $nfont] set linedtag($row) [$canv3 create text 3 $y -anchor w \ -text $date -font $mainfont] set xr [expr {$xt + [font measure $mainfont $headline]}] @@ -2383,6 +2596,8 @@ proc drawcmitrow {row} { global displayorder rowidlist global idrangedrawn iddrawn global commitinfo parentlist numcommits + global filehighlight fhighlights nhl_names nhighlights + global hlview vhighlights if {$row >= $numcommits} return foreach id [lindex $rowidlist $row] { @@ -2403,6 +2618,15 @@ proc drawcmitrow {row} { } set id [lindex $displayorder $row] + if {[info exists hlview] && ![info exists vhighlights($row)]} { + askvhighlight $row $id + } + if {[info exists filehighlight] && ![info exists fhighlights($row)]} { + askfilehighlight $row $id + } + if {$nhl_names ne {} && ![info exists nhighlights($row)]} { + asknamehighlight $row $id + } if {[info exists iddrawn($id)]} return set col [lsearch -exact [lindex $rowidlist $row] $id] if {$col < 0} { @@ -2451,10 +2675,14 @@ proc drawvisible {} { proc clear_display {} { global iddrawn idrangedrawn + global vhighlights fhighlights nhighlights allcanvs delete all catch {unset iddrawn} catch {unset idrangedrawn} + catch {unset vhighlights} + catch {unset fhighlights} + catch {unset nhighlights} } proc findcrossings {id} { @@ -4943,13 +5171,16 @@ if {$i >= 0} { set history {} set historyindex 0 +set fh_serial 0 +set highlight_names {} +set nhl_names {} set optim_delay 16 set nextviewnum 1 set curview 0 set selectedview 0 -set selectedhlview {} +set selectedhlview None set viewfiles(0) {} set viewperm(0) 0 set viewargs(0) {} -- cgit v1.2.3 From 63b791912112a0f8cbd793a943bc40c88cad6e51 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 20 May 2006 21:31:52 +1000 Subject: gitk: Highlight entries in the file list as well This applies a bold highlight to entries in the file list pane in the bottom right corner when it is displaying the list of changed files. This doesn't yet highlight file list entries when it is in tree view mode. Signed-off-by: Paul Mackerras --- gitk | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 5 deletions(-) diff --git a/gitk b/gitk index f007af47aa..52013323ee 100755 --- a/gitk +++ b/gitk @@ -527,6 +527,8 @@ proc makewindow {} { global viewhlmenu selectedhlview set viewhlmenu [tk_optionMenu .ctop.top.lbar.vhl selectedhlview None] $viewhlmenu entryconf 0 -command delvhighlight + $viewhlmenu conf -font $uifont + .ctop.top.lbar.vhl conf -font $uifont pack .ctop.top.lbar.vhl -side left -fill y label .ctop.top.lbar.alabel -text " OR author/committer:" \ -font $uifont @@ -595,6 +597,7 @@ proc makewindow {} { pack $cflist -side left -fill both -expand 1 $cflist tag configure highlight \ -background [$cflist cget -selectbackground] + $cflist tag configure bold -font [concat $mainfont bold] .ctop.cdet add .ctop.cdet.right bind .ctop.cdet {resizecdetpanes %W %w} @@ -1140,16 +1143,55 @@ proc init_flist {first} { set difffilestart {} } +proc highlight_tag {f} { + global highlight_paths + + foreach p $highlight_paths { + if {[string match $p $f]} { + return "bold" + } + } + return {} +} + +proc highlight_filelist {} { + global flistmode cflist + + global highlight_paths + if {$flistmode eq "flat"} { + $cflist conf -state normal + set end [lindex [split [$cflist index end] .] 0] + for {set l 2} {$l < $end} {incr l} { + set line [$cflist get $l.0 "$l.0 lineend"] + if {[highlight_tag $line] ne {}} { + $cflist tag add bold $l.0 "$l.0 lineend" + } + } + $cflist conf -state disabled + } +} + +proc unhighlight_filelist {} { + global flistmode cflist + + if {$flistmode eq "flat"} { + $cflist conf -state normal + $cflist tag remove bold 1.0 end + $cflist conf -state disabled + } +} + proc add_flist {fl} { global flistmode cflist - $cflist conf -state normal if {$flistmode eq "flat"} { + $cflist conf -state normal foreach f $fl { - $cflist insert end "\n$f" + $cflist insert end "\n" + $cflist insert end $f [highlight_tag $f] } + $cflist conf -state disabled } - $cflist conf -state disabled } proc sel_flist {w x y} { @@ -1704,7 +1746,7 @@ proc askvhighlight {row id} { proc hfiles_change {name ix op} { global highlight_files filehighlight fhighlights fh_serial - global mainfont + global mainfont highlight_paths if {[info exists filehighlight]} { # delete previous highlights @@ -1715,7 +1757,9 @@ proc hfiles_change {name ix op} { unset fhighlights unbolden $rows } + unhighlight_filelist } + set highlight_paths {} after cancel do_file_hl $fh_serial incr fh_serial if {$highlight_files ne {}} { @@ -1723,10 +1767,26 @@ proc hfiles_change {name ix op} { } } +proc makepatterns {l} { + set ret {} + foreach e $l { + set ee [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} $e] + if {[string index $ee end] eq "/"} { + lappend ret "$ee*" + } else { + lappend ret $ee + lappend ret "$ee/*" + } + } + return $ret +} + proc do_file_hl {serial} { - global highlight_files filehighlight + global highlight_files filehighlight highlight_paths if {[catch {set paths [shellsplit $highlight_files]}]} return + set highlight_paths [makepatterns $paths] + highlight_filelist set cmd [concat | git-diff-tree -r -s --stdin -- $paths] set filehighlight [open $cmd r+] fconfigure $filehighlight -blocking 0 @@ -5175,6 +5235,7 @@ set historyindex 0 set fh_serial 0 set highlight_names {} set nhl_names {} +set highlight_paths {} set optim_delay 16 -- cgit v1.2.3 From 45a9d5054d69f0c662b6a28e60934f63fa4ee9ef Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 20 May 2006 22:56:27 +1000 Subject: gitk: Highlight paths of interest in tree view as well With this, when the file list window is in tree view mode, we highlight the paths of interest. Signed-off-by: Paul Mackerras --- gitk | 64 ++++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/gitk b/gitk index 52013323ee..2e0450437f 100755 --- a/gitk +++ b/gitk @@ -950,7 +950,7 @@ proc treeview {w l openlevs} { $w insert end $str $w image create end -align center -image $bm -padx 1 \ -name a:$ix - $w insert end $d + $w insert end $d [highlight_tag $prefix] $w mark set s:$ix "end -1c" $w mark gravity s:$ix left } @@ -962,7 +962,7 @@ proc treeview {w l openlevs} { set str "\n" for {set i 0} {$i < $lev} {incr i} {append str "\t"} $w insert end $str - $w insert end $tail + $w insert end $tail [highlight_tag $f] } lappend treecontents($prefix) $tail } @@ -999,6 +999,22 @@ proc linetoelt {l} { } } +proc highlight_tree {y prefix} { + global treeheight treecontents cflist + + foreach e $treecontents($prefix) { + set path $prefix$e + if {[highlight_tag $path] ne {}} { + $cflist tag add bold $y.0 "$y.0 lineend" + } + incr y + if {[string index $e end] eq "/" && $treeheight($path) > 1} { + set y [highlight_tree $y $path] + } + } + return $y +} + proc treeclosedir {w dir} { global treediropen treeheight treeparent treeindex @@ -1032,8 +1048,8 @@ proc treeopendir {w dir} { incr treeheight($x) $n } foreach e $treecontents($dir) { + set de $dir$e if {[string index $e end] eq "/"} { - set de $dir$e set iy $treeindex($de) $w mark set d:$iy e:$ix $w mark gravity d:$iy left @@ -1041,13 +1057,13 @@ proc treeopendir {w dir} { set treediropen($de) 0 $w image create e:$ix -align center -image tri-rt -padx 1 \ -name a:$iy - $w insert e:$ix $e + $w insert e:$ix $e [highlight_tag $de] $w mark set s:$iy e:$ix $w mark gravity s:$iy left set treeheight($de) 1 } else { $w insert e:$ix $str - $w insert e:$ix $e + $w insert e:$ix $e [highlight_tag $de] } } $w mark gravity e:$ix left @@ -1155,11 +1171,10 @@ proc highlight_tag {f} { } proc highlight_filelist {} { - global flistmode cflist + global cmitmode cflist - global highlight_paths - if {$flistmode eq "flat"} { - $cflist conf -state normal + $cflist conf -state normal + if {$cmitmode ne "tree"} { set end [lindex [split [$cflist index end] .] 0] for {set l 2} {$l < $end} {incr l} { set line [$cflist get $l.0 "$l.0 lineend"] @@ -1167,35 +1182,33 @@ proc highlight_filelist {} { $cflist tag add bold $l.0 "$l.0 lineend" } } - $cflist conf -state disabled + } else { + highlight_tree 2 {} } + $cflist conf -state disabled } proc unhighlight_filelist {} { - global flistmode cflist + global cflist - if {$flistmode eq "flat"} { - $cflist conf -state normal - $cflist tag remove bold 1.0 end - $cflist conf -state disabled - } + $cflist conf -state normal + $cflist tag remove bold 1.0 end + $cflist conf -state disabled } proc add_flist {fl} { - global flistmode cflist + global cflist - if {$flistmode eq "flat"} { - $cflist conf -state normal - foreach f $fl { - $cflist insert end "\n" - $cflist insert end $f [highlight_tag $f] - } - $cflist conf -state disabled + $cflist conf -state normal + foreach f $fl { + $cflist insert end "\n" + $cflist insert end $f [highlight_tag $f] } + $cflist conf -state disabled } proc sel_flist {w x y} { - global flistmode ctext difffilestart cflist cflist_top cmitmode + global ctext difffilestart cflist cflist_top cmitmode if {$cmitmode eq "tree"} return if {![info exists cflist_top]} return @@ -5180,7 +5193,6 @@ set fastdate 0 set uparrowlen 7 set downarrowlen 7 set mingaplen 30 -set flistmode "flat" set cmitmode "patch" set colors {green red blue magenta darkgrey brown orange} -- cgit v1.2.3 From 3ea06f9f7e10463ee52b7ed8cbe3b2728c9e662e Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 24 May 2006 10:16:03 +1000 Subject: gitk: First cut at a search function in the patch/file display window This does incremental highlighting of matches to the search string but doesn't do true incremental search a la emacs. Signed-off-by: Paul Mackerras --- gitk | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 101 insertions(+), 6 deletions(-) diff --git a/gitk b/gitk index 2e0450437f..ff210494ce 100755 --- a/gitk +++ b/gitk @@ -384,6 +384,7 @@ proc makewindow {} { global maincursor textcursor curtextcursor global rowctxmenu mergemax global highlight_files highlight_names + global searchstring sstring menu .bar .bar add cascade -label "File" -menu .bar.file @@ -542,10 +543,20 @@ proc makewindow {} { panedwindow .ctop.cdet -orient horizontal .ctop add .ctop.cdet frame .ctop.cdet.left + frame .ctop.cdet.left.bot + pack .ctop.cdet.left.bot -side bottom -fill x + button .ctop.cdet.left.bot.search -text "Search" -command dosearch \ + -font $uifont + pack .ctop.cdet.left.bot.search -side left -padx 5 + set sstring .ctop.cdet.left.bot.sstring + entry $sstring -width 20 -font $textfont -textvariable searchstring + lappend entries $sstring + trace add variable searchstring write incrsearch + pack $sstring -side left -expand 1 -fill x set ctext .ctop.cdet.left.ctext text $ctext -bg white -state disabled -font $textfont \ -width $geometry(ctextw) -height $geometry(ctexth) \ - -yscrollcommand {.ctop.cdet.left.sb set} -wrap none + -yscrollcommand scrolltext -wrap none scrollbar .ctop.cdet.left.sb -command "$ctext yview" pack .ctop.cdet.left.sb -side right -fill y pack $ctext -side left -fill both -expand 1 @@ -645,6 +656,7 @@ proc makewindow {} { bind . dofind bind . {findnext 0} bind . findprev + bind . dosearch bind . {incrfont 1} bind . {incrfont 1} bind . {incrfont -1} @@ -3643,7 +3655,7 @@ proc selectline {l isnew} { $sha1entry selection to end $ctext conf -state normal - $ctext delete 0.0 end + clear_ctext set linknum 0 set info $commitinfo($id) set date [formatdate [lindex $info 2]] @@ -3881,7 +3893,7 @@ proc showfile {f} { fconfigure $bf -blocking 0 fileevent $bf readable [list getblobline $bf $diffids] $ctext config -state normal - $ctext delete $commentend end + clear_ctext $commentend $ctext insert end "\n" $ctext insert end "$f\n" filesep $ctext config -state disabled @@ -4181,6 +4193,89 @@ proc nextfile {} { } } +proc clear_ctext {{first 1.0}} { + global ctext smarktop smarkbot + + if {![info exists smarktop] || [$ctext compare $first < $smarktop]} { + set smarktop $first + } + if {![info exists smarkbot] || [$ctext compare $first < $smarkbot]} { + set smarkbot $first + } + $ctext delete $first end +} + +proc incrsearch {name ix op} { + global ctext searchstring + + $ctext tag remove found 1.0 end + if {$searchstring ne {}} { + searchmarkvisible 1 + } +} + +proc dosearch {} { + global sstring ctext searchstring + + focus $sstring + $sstring icursor end + $ctext tag remove sel 1.0 end + if {$searchstring eq {}} return + set here [$ctext index insert] + set match [$ctext search -count mlen -- $searchstring $here] + if {$match eq {}} { + bell + return + } + $ctext see $match + set mend "$match + $mlen c" + $ctext tag add sel $match $mend + $ctext mark set insert $mend +} + +proc searchmark {first last} { + global ctext searchstring + + set mend $first.0 + while {1} { + set match [$ctext search -count mlen -- $searchstring $mend $last.end] + if {$match eq {}} break + set mend "$match + $mlen c" + $ctext tag add found $match $mend + } +} + +proc searchmarkvisible {doall} { + global ctext smarktop smarkbot + + set topline [lindex [split [$ctext index @0,0] .] 0] + set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0] + if {$doall || $botline < $smarktop || $topline > $smarkbot} { + # no overlap with previous + searchmark $topline $botline + set smarktop $topline + set smarkbot $botline + } else { + if {$topline < $smarktop} { + searchmark $topline [expr {$smarktop-1}] + set smarktop $topline + } + if {$botline > $smarkbot} { + searchmark [expr {$smarkbot+1}] $botline + set smarkbot $botline + } + } +} + +proc scrolltext {f0 f1} { + global ctext smarktop smarkbot searchstring + + .ctop.cdet.left.sb set $f0 $f1 + if {$searchstring ne {}} { + searchmarkvisible 0 + } +} + proc setcoords {} { global linespc charspc canvx0 canvy0 mainfont global xspc1 xspc2 lthickness @@ -4415,7 +4510,7 @@ proc lineclick {x y id isnew} { } # fill the details pane with info about this line $ctext conf -state normal - $ctext delete 0.0 end + clear_ctext $ctext tag conf link -foreground blue -underline 1 $ctext tag bind link { %W configure -cursor hand2 } $ctext tag bind link { %W configure -cursor $curtextcursor } @@ -4508,7 +4603,7 @@ proc doseldiff {oldid newid} { global commitinfo $ctext conf -state normal - $ctext delete 0.0 end + clear_ctext init_flist "Top" $ctext insert end "From " $ctext tag conf link -foreground blue -underline 1 @@ -4802,7 +4897,7 @@ proc showtag {tag isnew} { addtohistory [list showtag $tag 0] } $ctext conf -state normal - $ctext delete 0.0 end + clear_ctext set linknum 0 if {[info exists tagcontents($tag)]} { set text $tagcontents($tag) -- cgit v1.2.3 From 1902c2705e41da499fd7ed964e747cf48a0745dd Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 25 May 2006 21:25:13 +1000 Subject: gitk: Improve the text window search function This makes it work a bit more smoothly, and adds a reverse-search function, for which I stole the ^R binding from the find function. Signed-off-by: Paul Mackerras --- gitk | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 69 insertions(+), 19 deletions(-) diff --git a/gitk b/gitk index ff210494ce..52ba8dd176 100755 --- a/gitk +++ b/gitk @@ -655,7 +655,7 @@ proc makewindow {} { bind . doquit bind . dofind bind . {findnext 0} - bind . findprev + bind . dosearchback bind . dosearch bind . {incrfont 1} bind . {incrfont 1} @@ -4196,41 +4196,90 @@ proc nextfile {} { proc clear_ctext {{first 1.0}} { global ctext smarktop smarkbot - if {![info exists smarktop] || [$ctext compare $first < $smarktop]} { - set smarktop $first + set l [lindex [split $first .] 0] + if {![info exists smarktop] || [$ctext compare $first < $smarktop.0]} { + set smarktop $l } - if {![info exists smarkbot] || [$ctext compare $first < $smarkbot]} { - set smarkbot $first + if {![info exists smarkbot] || [$ctext compare $first < $smarkbot.0]} { + set smarkbot $l } $ctext delete $first end } proc incrsearch {name ix op} { - global ctext searchstring + global ctext searchstring searchdirn $ctext tag remove found 1.0 end + if {[catch {$ctext index anchor}]} { + # no anchor set, use start of selection, or of visible area + set sel [$ctext tag ranges sel] + if {$sel ne {}} { + $ctext mark set anchor [lindex $sel 0] + } elseif {$searchdirn eq "-forwards"} { + $ctext mark set anchor @0,0 + } else { + $ctext mark set anchor @0,[winfo height $ctext] + } + } if {$searchstring ne {}} { + set here [$ctext search $searchdirn -- $searchstring anchor] + if {$here ne {}} { + $ctext see $here + } searchmarkvisible 1 } } proc dosearch {} { - global sstring ctext searchstring + global sstring ctext searchstring searchdirn focus $sstring $sstring icursor end - $ctext tag remove sel 1.0 end - if {$searchstring eq {}} return - set here [$ctext index insert] - set match [$ctext search -count mlen -- $searchstring $here] - if {$match eq {}} { - bell - return + set searchdirn -forwards + if {$searchstring ne {}} { + set sel [$ctext tag ranges sel] + if {$sel ne {}} { + set start "[lindex $sel 0] + 1c" + } elseif {[catch {set start [$ctext index anchor]}]} { + set start "@0,0" + } + set match [$ctext search -count mlen -- $searchstring $start] + $ctext tag remove sel 1.0 end + if {$match eq {}} { + bell + return + } + $ctext see $match + set mend "$match + $mlen c" + $ctext tag add sel $match $mend + $ctext mark unset anchor + } +} + +proc dosearchback {} { + global sstring ctext searchstring searchdirn + + focus $sstring + $sstring icursor end + set searchdirn -backwards + if {$searchstring ne {}} { + set sel [$ctext tag ranges sel] + if {$sel ne {}} { + set start [lindex $sel 0] + } elseif {[catch {set start [$ctext index anchor]}]} { + set start @0,[winfo height $ctext] + } + set match [$ctext search -backwards -count ml -- $searchstring $start] + $ctext tag remove sel 1.0 end + if {$match eq {}} { + bell + return + } + $ctext see $match + set mend "$match + $ml c" + $ctext tag add sel $match $mend + $ctext mark unset anchor } - $ctext see $match - set mend "$match + $mlen c" - $ctext tag add sel $match $mend - $ctext mark set insert $mend } proc searchmark {first last} { @@ -4268,7 +4317,7 @@ proc searchmarkvisible {doall} { } proc scrolltext {f0 f1} { - global ctext smarktop smarkbot searchstring + global searchstring .ctop.cdet.left.sb set $f0 $f1 if {$searchstring ne {}} { @@ -5343,6 +5392,7 @@ set fh_serial 0 set highlight_names {} set nhl_names {} set highlight_paths {} +set searchdirn -forwards set optim_delay 16 -- cgit v1.2.3 From 60f7a7dc4904ba4baab44b70e2675a01e6172f54 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 26 May 2006 10:43:47 +1000 Subject: gitk: Move "pickaxe" find function to highlight facility This removes the "Files" and "Pickaxe" parts of the "Find" function, so Find is now just about searching the commit data. We now highlight the commits that match the Find string (without having to press Find), and have a drop-down menu for selecting whether the git-diff-tree based highlighting is done on paths or on adding/removing a given string. Signed-off-by: Paul Mackerras --- gitk | 368 +++++++++++-------------------------------------------------------- 1 file changed, 59 insertions(+), 309 deletions(-) diff --git a/gitk b/gitk index 52ba8dd176..c90ef993c5 100755 --- a/gitk +++ b/gitk @@ -383,7 +383,7 @@ proc makewindow {} { global entries sha1entry sha1string sha1but global maincursor textcursor curtextcursor global rowctxmenu mergemax - global highlight_files highlight_names + global highlight_files gdttype global searchstring sstring menu .bar @@ -498,26 +498,33 @@ proc makewindow {} { set fstring .ctop.top.bar.findstring lappend entries $fstring entry $fstring -width 30 -font $textfont -textvariable findstring + trace add variable findstring write find_change pack $fstring -side left -expand 1 -fill x set findtype Exact set findtypemenu [tk_optionMenu .ctop.top.bar.findtype \ findtype Exact IgnCase Regexp] + trace add variable findtype write find_change .ctop.top.bar.findtype configure -font $uifont .ctop.top.bar.findtype.menu configure -font $uifont set findloc "All fields" tk_optionMenu .ctop.top.bar.findloc findloc "All fields" Headline \ - Comments Author Committer Files Pickaxe + Comments Author Committer + trace add variable findloc write find_change .ctop.top.bar.findloc configure -font $uifont .ctop.top.bar.findloc.menu configure -font $uifont - pack .ctop.top.bar.findloc -side right pack .ctop.top.bar.findtype -side right - # for making sure type==Exact whenever loc==Pickaxe - trace add variable findloc write findlocchange - label .ctop.top.lbar.flabel -text "Highlight: Commits touching paths:" \ + label .ctop.top.lbar.flabel -text "Highlight: Commits " \ -font $uifont pack .ctop.top.lbar.flabel -side left -fill y + set gdttype "touching paths:" + set gm [tk_optionMenu .ctop.top.lbar.gdttype gdttype "touching paths:" \ + "adding/removing string:"] + trace add variable gdttype write hfiles_change + $gm conf -font $uifont + .ctop.top.lbar.gdttype conf -font $uifont + pack .ctop.top.lbar.gdttype -side left -fill y entry .ctop.top.lbar.fent -width 25 -font $textfont \ -textvariable highlight_files trace add variable highlight_files write hfiles_change @@ -531,14 +538,6 @@ proc makewindow {} { $viewhlmenu conf -font $uifont .ctop.top.lbar.vhl conf -font $uifont pack .ctop.top.lbar.vhl -side left -fill y - label .ctop.top.lbar.alabel -text " OR author/committer:" \ - -font $uifont - pack .ctop.top.lbar.alabel -side left -fill y - entry .ctop.top.lbar.aent -width 20 -font $textfont \ - -textvariable highlight_names - trace add variable highlight_names write hnames_change - lappend entries .ctop.top.lbar.aent - pack .ctop.top.lbar.aent -side right -fill x -expand 1 panedwindow .ctop.cdet -orient horizontal .ctop add .ctop.cdet @@ -1807,12 +1806,17 @@ proc makepatterns {l} { } proc do_file_hl {serial} { - global highlight_files filehighlight highlight_paths + global highlight_files filehighlight highlight_paths gdttype - if {[catch {set paths [shellsplit $highlight_files]}]} return - set highlight_paths [makepatterns $paths] - highlight_filelist - set cmd [concat | git-diff-tree -r -s --stdin -- $paths] + if {$gdttype eq "touching paths:"} { + if {[catch {set paths [shellsplit $highlight_files]}]} return + set highlight_paths [makepatterns $paths] + highlight_filelist + set gdtargs [concat -- $paths] + } else { + set gdtargs [list "-S$highlight_files"] + } + set cmd [concat | git-diff-tree -r -s --stdin $gdtargs] set filehighlight [open $cmd r+] fconfigure $filehighlight -blocking 0 fileevent $filehighlight readable readfhighlight @@ -1859,8 +1863,9 @@ proc readfhighlight {} { set fhighlights($row) 1 } -proc hnames_change {name ix op} { - global highlight_names nhighlights nhl_names mainfont +proc find_change {name ix op} { + global nhighlights mainfont + global findstring findpattern findtype # delete previous highlights, if any set rows [array names nhighlights] @@ -1873,30 +1878,41 @@ proc hnames_change {name ix op} { unset nhighlights unbolden $rows } - if {[catch {set nhl_names [shellsplit $highlight_names]}]} { - set nhl_names {} - return + if {$findtype ne "Regexp"} { + set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \ + $findstring] + set findpattern "*$e*" } drawvisible } -proc asknamehighlight {row id} { - global nhl_names nhighlights commitinfo iddrawn mainfont +proc askfindhighlight {row id} { + global nhighlights commitinfo iddrawn mainfont + global findstring findtype findloc findpattern if {![info exists commitinfo($id)]} { getcommit $id } + set info $commitinfo($id) set isbold 0 - set author [lindex $commitinfo($id) 1] - set committer [lindex $commitinfo($id) 3] - foreach name $nhl_names { - set pattern "*$name*" - if {[string match -nocase $pattern $author]} { - set isbold 2 - break + set fldtypes {Headline Author Date Committer CDate Comments} + foreach f $info ty $fldtypes { + if {$findloc ne "All fields" && $findloc ne $ty} { + continue } - if {!$isbold && [string match -nocase $pattern $committer]} { - set isbold 1 + if {$findtype eq "Regexp"} { + set doesmatch [regexp $findstring $f] + } elseif {$findtype eq "IgnCase"} { + set doesmatch [string match -nocase $findpattern $f] + } else { + set doesmatch [string match $findpattern $f] + } + if {$doesmatch} { + if {$ty eq "Author"} { + set isbold 2 + } else { + set isbold 1 + } } } if {[info exists iddrawn($id)]} { @@ -2681,7 +2697,7 @@ proc drawcmitrow {row} { global displayorder rowidlist global idrangedrawn iddrawn global commitinfo parentlist numcommits - global filehighlight fhighlights nhl_names nhighlights + global filehighlight fhighlights findstring nhighlights global hlview vhighlights if {$row >= $numcommits} return @@ -2709,8 +2725,8 @@ proc drawcmitrow {row} { if {[info exists filehighlight] && ![info exists fhighlights($row)]} { askfilehighlight $row $id } - if {$nhl_names ne {} && ![info exists nhighlights($row)]} { - asknamehighlight $row $id + if {$findstring ne {} && ![info exists nhighlights($row)]} { + askfindhighlight $row $id } if {[info exists iddrawn($id)]} return set col [lsearch -exact [lindex $rowidlist $row] $id] @@ -3073,10 +3089,6 @@ proc dofind {} { unmarkmatches focus . set matchinglines {} - if {$findloc == "Pickaxe"} { - findpatches - return - } if {$findtype == "IgnCase"} { set foundstring [string tolower $findstring] } else { @@ -3086,17 +3098,13 @@ proc dofind {} { if {$foundstrlen == 0} return regsub -all {[*?\[\\]} $foundstring {\\&} matchstring set matchstring "*$matchstring*" - if {$findloc == "Files"} { - findfiles - return - } if {![info exists selectedline]} { set oldsel -1 } else { set oldsel $selectedline } set didsel 0 - set fldtypes {Headline Author Date Committer CDate Comment} + set fldtypes {Headline Author Date Committer CDate Comments} set l -1 foreach id $displayorder { set d $commitdata($id) @@ -3199,18 +3207,6 @@ proc findprev {} { } } -proc findlocchange {name ix op} { - global findloc findtype findtypemenu - if {$findloc == "Pickaxe"} { - set findtype Exact - set state disabled - } else { - set state normal - } - $findtypemenu entryconf 1 -state $state - $findtypemenu entryconf 2 -state $state -} - proc stopfindproc {{done 0}} { global findprocpid findprocfile findids global ctext findoldcursor phase maincursor textcursor @@ -3228,247 +3224,6 @@ proc stopfindproc {{done 0}} { notbusy find } -proc findpatches {} { - global findstring selectedline numcommits - global findprocpid findprocfile - global finddidsel ctext displayorder findinprogress - global findinsertpos - - if {$numcommits == 0} return - - # make a list of all the ids to search, starting at the one - # after the selected line (if any) - if {[info exists selectedline]} { - set l $selectedline - } else { - set l -1 - } - set inputids {} - for {set i 0} {$i < $numcommits} {incr i} { - if {[incr l] >= $numcommits} { - set l 0 - } - append inputids [lindex $displayorder $l] "\n" - } - - if {[catch { - set f [open [list | git-diff-tree --stdin -s -r -S$findstring \ - << $inputids] r] - } err]} { - error_popup "Error starting search process: $err" - return - } - - set findinsertpos end - set findprocfile $f - set findprocpid [pid $f] - fconfigure $f -blocking 0 - fileevent $f readable readfindproc - set finddidsel 0 - nowbusy find - set findinprogress 1 -} - -proc readfindproc {} { - global findprocfile finddidsel - global commitrow matchinglines findinsertpos curview - - set n [gets $findprocfile line] - if {$n < 0} { - if {[eof $findprocfile]} { - stopfindproc 1 - if {!$finddidsel} { - bell - } - } - return - } - if {![regexp {^[0-9a-f]{40}} $line id]} { - error_popup "Can't parse git-diff-tree output: $line" - stopfindproc - return - } - if {![info exists commitrow($curview,$id)]} { - puts stderr "spurious id: $id" - return - } - set l $commitrow($curview,$id) - insertmatch $l $id -} - -proc insertmatch {l id} { - global matchinglines findinsertpos finddidsel - - if {$findinsertpos == "end"} { - if {$matchinglines != {} && $l < [lindex $matchinglines 0]} { - set matchinglines [linsert $matchinglines 0 $l] - set findinsertpos 1 - } else { - lappend matchinglines $l - } - } else { - set matchinglines [linsert $matchinglines $findinsertpos $l] - incr findinsertpos - } - markheadline $l $id - if {!$finddidsel} { - findselectline $l - set finddidsel 1 - } -} - -proc findfiles {} { - global selectedline numcommits displayorder ctext - global ffileline finddidsel parentlist - global findinprogress findstartline findinsertpos - global treediffs fdiffid fdiffsneeded fdiffpos - global findmergefiles - - if {$numcommits == 0} return - - if {[info exists selectedline]} { - set l [expr {$selectedline + 1}] - } else { - set l 0 - } - set ffileline $l - set findstartline $l - set diffsneeded {} - set fdiffsneeded {} - while 1 { - set id [lindex $displayorder $l] - if {$findmergefiles || [llength [lindex $parentlist $l]] == 1} { - if {![info exists treediffs($id)]} { - append diffsneeded "$id\n" - lappend fdiffsneeded $id - } - } - if {[incr l] >= $numcommits} { - set l 0 - } - if {$l == $findstartline} break - } - - # start off a git-diff-tree process if needed - if {$diffsneeded ne {}} { - if {[catch { - set df [open [list | git-diff-tree -r --stdin << $diffsneeded] r] - } err ]} { - error_popup "Error starting search process: $err" - return - } - catch {unset fdiffid} - set fdiffpos 0 - fconfigure $df -blocking 0 - fileevent $df readable [list readfilediffs $df] - } - - set finddidsel 0 - set findinsertpos end - set id [lindex $displayorder $l] - nowbusy find - set findinprogress 1 - findcont - update -} - -proc readfilediffs {df} { - global findid fdiffid fdiffs - - set n [gets $df line] - if {$n < 0} { - if {[eof $df]} { - donefilediff - if {[catch {close $df} err]} { - stopfindproc - bell - error_popup "Error in git-diff-tree: $err" - } elseif {[info exists findid]} { - set id $findid - stopfindproc - bell - error_popup "Couldn't find diffs for $id" - } - } - return - } - if {[regexp {^([0-9a-f]{40})$} $line match id]} { - # start of a new string of diffs - donefilediff - set fdiffid $id - set fdiffs {} - } elseif {[string match ":*" $line]} { - lappend fdiffs [lindex $line 5] - } -} - -proc donefilediff {} { - global fdiffid fdiffs treediffs findid - global fdiffsneeded fdiffpos - - if {[info exists fdiffid]} { - while {[lindex $fdiffsneeded $fdiffpos] ne $fdiffid - && $fdiffpos < [llength $fdiffsneeded]} { - # git-diff-tree doesn't output anything for a commit - # which doesn't change anything - set nullid [lindex $fdiffsneeded $fdiffpos] - set treediffs($nullid) {} - if {[info exists findid] && $nullid eq $findid} { - unset findid - findcont - } - incr fdiffpos - } - incr fdiffpos - - if {![info exists treediffs($fdiffid)]} { - set treediffs($fdiffid) $fdiffs - } - if {[info exists findid] && $fdiffid eq $findid} { - unset findid - findcont - } - } -} - -proc findcont {} { - global findid treediffs parentlist - global ffileline findstartline finddidsel - global displayorder numcommits matchinglines findinprogress - global findmergefiles - - set l $ffileline - while {1} { - set id [lindex $displayorder $l] - if {$findmergefiles || [llength [lindex $parentlist $l]] == 1} { - if {![info exists treediffs($id)]} { - set findid $id - set ffileline $l - return - } - set doesmatch 0 - foreach f $treediffs($id) { - set x [findmatches $f] - if {$x != {}} { - set doesmatch 1 - break - } - } - if {$doesmatch} { - insertmatch $l $id - } - } - if {[incr l] >= $numcommits} { - set l 0 - } - if {$l == $findstartline} break - } - stopfindproc - if {!$finddidsel} { - bell - } -} - # mark a commit as matching by putting a yellow background # behind the headline proc markheadline {l id} { @@ -4965,7 +4720,7 @@ proc doquit {} { } proc doprefs {} { - global maxwidth maxgraphpct diffopts findmergefiles + global maxwidth maxgraphpct diffopts global oldprefs prefstop set top .gitkprefs @@ -4974,7 +4729,7 @@ proc doprefs {} { raise $top return } - foreach v {maxwidth maxgraphpct diffopts findmergefiles} { + foreach v {maxwidth maxgraphpct diffopts} { set oldprefs($v) [set $v] } toplevel $top @@ -4990,10 +4745,6 @@ proc doprefs {} { -font optionfont spinbox $top.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct grid x $top.maxpctl $top.maxpct -sticky w - checkbutton $top.findm -variable findmergefiles - label $top.findml -text "Include merges for \"Find\" in \"Files\"" \ - -font optionfont - grid $top.findm $top.findml - -sticky w label $top.ddisp -text "Diff display options" grid $top.ddisp - -sticky w -pady 10 label $top.diffoptl -text "Options for diff program" \ @@ -5010,10 +4761,10 @@ proc doprefs {} { } proc prefscan {} { - global maxwidth maxgraphpct diffopts findmergefiles + global maxwidth maxgraphpct diffopts global oldprefs prefstop - foreach v {maxwidth maxgraphpct diffopts findmergefiles} { + foreach v {maxwidth maxgraphpct diffopts} { set $v $oldprefs($v) } catch {destroy $prefstop} @@ -5389,7 +5140,6 @@ if {$i >= 0} { set history {} set historyindex 0 set fh_serial 0 -set highlight_names {} set nhl_names {} set highlight_paths {} set searchdirn -forwards -- cgit v1.2.3 From 5864c08f897425ff186fcab00ecc81166e783bd5 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 26 May 2006 22:22:48 +1000 Subject: gitk: Fix bug in highlight stuff when no line is selected Signed-off-by: Paul Mackerras --- gitk | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/gitk b/gitk index c90ef993c5..317d90d954 100755 --- a/gitk +++ b/gitk @@ -1660,7 +1660,7 @@ proc bolden {row font} { global canv linehtag selectedline $canv itemconf $linehtag($row) -font $font - if {$row == $selectedline} { + if {[info exists selectedline] && $row == $selectedline} { $canv delete secsel set t [eval $canv create rect [$canv bbox $linehtag($row)] \ -outline {{}} -tags secsel \ @@ -1673,7 +1673,7 @@ proc bolden_name {row font} { global canv2 linentag selectedline $canv2 itemconf $linentag($row) -font $font - if {$row == $selectedline} { + if {[info exists selectedline] && $row == $selectedline} { $canv2 delete secsel set t [eval $canv2 create rect [$canv2 bbox $linentag($row)] \ -outline {{}} -tags secsel \ @@ -1715,7 +1715,6 @@ proc addvhighlight {n} { proc delvhighlight {} { global hlview vhighlights - global selectedline if {![info exists hlview]} return unset hlview -- cgit v1.2.3 From 164ff275adf2e212ef21632c21eef191a1c7420d Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 29 May 2006 19:50:02 +1000 Subject: gitk: Provide ability to highlight based on relationship to selected commit This provides a way to highlight commits that are, or are not, descendents or ancestors of the currently selected commit. It's still rough around the edges but seems to be useful even so. Signed-off-by: Paul Mackerras --- gitk | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 150 insertions(+), 2 deletions(-) diff --git a/gitk b/gitk index 317d90d954..b0a62c0295 100755 --- a/gitk +++ b/gitk @@ -538,6 +538,15 @@ proc makewindow {} { $viewhlmenu conf -font $uifont .ctop.top.lbar.vhl conf -font $uifont pack .ctop.top.lbar.vhl -side left -fill y + label .ctop.top.lbar.rlabel -text " OR " -font $uifont + pack .ctop.top.lbar.rlabel -side left -fill y + global highlight_related + set m [tk_optionMenu .ctop.top.lbar.relm highlight_related None \ + "Descendent" "Not descendent" "Ancestor" "Not ancestor"] + $m conf -font $uifont + .ctop.top.lbar.relm conf -font $uifont + trace add variable highlight_related write vrel_change + pack .ctop.top.lbar.relm -side left -fill y panedwindow .ctop.cdet -orient horizontal .ctop add .ctop.cdet @@ -1642,7 +1651,7 @@ proc showview {n} { # Stuff relating to the highlighting facility proc ishighlighted {row} { - global vhighlights fhighlights nhighlights + global vhighlights fhighlights nhighlights rhighlights if {[info exists nhighlights($row)] && $nhighlights($row) > 0} { return $nhighlights($row) @@ -1653,6 +1662,9 @@ proc ishighlighted {row} { if {[info exists fhighlights($row)] && $fhighlights($row) > 0} { return $fhighlights($row) } + if {[info exists rhighlights($row)] && $rhighlights($row) > 0} { + return $rhighlights($row) + } return 0 } @@ -1925,6 +1937,135 @@ proc askfindhighlight {row id} { set nhighlights($row) $isbold } +proc vrel_change {name ix op} { + global highlight_related + + rhighlight_none + if {$highlight_related ne "None"} { + after idle drawvisible + } +} + +# prepare for testing whether commits are descendents or ancestors of a +proc rhighlight_sel {a} { + global descendent desc_todo ancestor anc_todo + global highlight_related rhighlights + + catch {unset descendent} + set desc_todo [list $a] + catch {unset ancestor} + set anc_todo [list $a] + if {$highlight_related ne "None"} { + rhighlight_none + after idle drawvisible + } +} + +proc rhighlight_none {} { + global rhighlights + + set rows [array names rhighlights] + if {$rows ne {}} { + unset rhighlights + unbolden $rows + } +} + +proc is_descendent {a} { + global curview children commitrow descendent desc_todo + + set v $curview + set la $commitrow($v,$a) + set todo $desc_todo + set leftover {} + set done 0 + for {set i 0} {$i < [llength $todo]} {incr i} { + set do [lindex $todo $i] + if {$commitrow($v,$do) < $la} { + lappend leftover $do + continue + } + foreach nk $children($v,$do) { + if {![info exists descendent($nk)]} { + set descendent($nk) 1 + lappend todo $nk + if {$nk eq $a} { + set done 1 + } + } + } + if {$done} { + set desc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]] + return + } + } + set descendent($a) 0 + set desc_todo $leftover +} + +proc is_ancestor {a} { + global curview parentlist commitrow ancestor anc_todo + + set v $curview + set la $commitrow($v,$a) + set todo $anc_todo + set leftover {} + set done 0 + for {set i 0} {$i < [llength $todo]} {incr i} { + set do [lindex $todo $i] + if {![info exists commitrow($v,$do)] || $commitrow($v,$do) > $la} { + lappend leftover $do + continue + } + foreach np [lindex $parentlist $commitrow($v,$do)] { + if {![info exists ancestor($np)]} { + set ancestor($np) 1 + lappend todo $np + if {$np eq $a} { + set done 1 + } + } + } + if {$done} { + set anc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]] + return + } + } + set ancestor($a) 0 + set anc_todo $leftover +} + +proc askrelhighlight {row id} { + global descendent highlight_related iddrawn mainfont rhighlights + global selectedline ancestor + + if {![info exists selectedline]} return + set isbold 0 + if {$highlight_related eq "Descendent" || + $highlight_related eq "Not descendent"} { + if {![info exists descendent($id)]} { + is_descendent $id + } + if {$descendent($id) == ($highlight_related eq "Descendent")} { + set isbold 1 + } + } elseif {$highlight_related eq "Ancestor" || + $highlight_related eq "Not ancestor"} { + if {![info exists ancestor($id)]} { + is_ancestor $id + } + if {$ancestor($id) == ($highlight_related eq "Ancestor")} { + set isbold 1 + } + } + if {[info exists iddrawn($id)]} { + if {$isbold && ![ishighlighted $row]} { + bolden $row [concat $mainfont bold] + } + } + set rhighlights($row) $isbold +} + # Graph layout functions proc shortids {ids} { @@ -2698,6 +2839,7 @@ proc drawcmitrow {row} { global commitinfo parentlist numcommits global filehighlight fhighlights findstring nhighlights global hlview vhighlights + global highlight_related rhighlights if {$row >= $numcommits} return foreach id [lindex $rowidlist $row] { @@ -2727,6 +2869,9 @@ proc drawcmitrow {row} { if {$findstring ne {} && ![info exists nhighlights($row)]} { askfindhighlight $row $id } + if {$highlight_related ne "None" && ![info exists rhighlights($row)]} { + askrelhighlight $row $id + } if {[info exists iddrawn($id)]} return set col [lsearch -exact [lindex $rowidlist $row] $id] if {$col < 0} { @@ -2775,7 +2920,7 @@ proc drawvisible {} { proc clear_display {} { global iddrawn idrangedrawn - global vhighlights fhighlights nhighlights + global vhighlights fhighlights nhighlights rhighlights allcanvs delete all catch {unset iddrawn} @@ -2783,6 +2928,7 @@ proc clear_display {} { catch {unset vhighlights} catch {unset fhighlights} catch {unset nhighlights} + catch {unset rhighlights} } proc findcrossings {id} { @@ -3407,6 +3553,7 @@ proc selectline {l isnew} { $sha1entry insert 0 $id $sha1entry selection from 0 $sha1entry selection to end + rhighlight_sel $id $ctext conf -state normal clear_ctext @@ -3514,6 +3661,7 @@ proc unselectline {} { catch {unset selectedline} catch {unset currentid} allcanvs delete secsel + rhighlight_none } proc reselectline {} { -- cgit v1.2.3 From 4e7d677949e8ee7617e42f10c1ddf5cd2adee3a1 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 30 May 2006 21:33:07 +1000 Subject: gitk: Add a goto next/previous highlighted commit function This is invoked by shift-down/shift-up. It relies on a patch to git-diff-tree that has recently gone into the git repository, commit ID e0c97ca6 (without this it may just sit there doing waiting for git-diff-tree when looking for the next/previous highlight). Signed-off-by: Paul Mackerras --- gitk | 196 +++++++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 144 insertions(+), 52 deletions(-) diff --git a/gitk b/gitk index b0a62c0295..7c8ad595c0 100755 --- a/gitk +++ b/gitk @@ -632,6 +632,8 @@ proc makewindow {} { bindkey sellastline bind . "selnextline -1" bind . "selnextline 1" + bind . "next_highlight -1" + bind . "next_highlight 1" bindkey "goforw" bindkey "goback" bind . "selnextpage -1" @@ -892,6 +894,8 @@ Gitk key bindings: Scroll commit list down one line Scroll commit list up one page Scroll commit list down one page + Move to previous highlighted line + Move to next highlighted line , b Scroll diff view up one page Scroll diff view up one page Scroll diff view down one page @@ -899,11 +903,12 @@ u Scroll diff view up 18 lines d Scroll diff view down 18 lines Find Move to next find hit - Move to previous find hit Move to next find hit / Move to next find hit, or redo find ? Move to previous find hit f Scroll diff view to next file + Search for next hit in diff view + Search for previous hit in diff view Increase font size Increase font size Decrease font size @@ -1669,8 +1674,9 @@ proc ishighlighted {row} { } proc bolden {row font} { - global canv linehtag selectedline + global canv linehtag selectedline boldrows + lappend boldrows $row $canv itemconf $linehtag($row) -font $font if {[info exists selectedline] && $row == $selectedline} { $canv delete secsel @@ -1682,8 +1688,9 @@ proc bolden {row font} { } proc bolden_name {row font} { - global canv2 linentag selectedline + global canv2 linentag selectedline boldnamerows + lappend boldnamerows $row $canv2 itemconf $linentag($row) -font $font if {[info exists selectedline] && $row == $selectedline} { $canv2 delete secsel @@ -1694,14 +1701,18 @@ proc bolden_name {row font} { } } -proc unbolden {rows} { - global mainfont +proc unbolden {} { + global mainfont boldrows - foreach row $rows { + set stillbold {} + foreach row $boldrows { if {![ishighlighted $row]} { bolden $row $mainfont + } else { + lappend stillbold $row } } + set boldrows $stillbold } proc addvhighlight {n} { @@ -1730,11 +1741,8 @@ proc delvhighlight {} { if {![info exists hlview]} return unset hlview - set rows [array names vhighlights] - if {$rows ne {}} { - unset vhighlights - unbolden $rows - } + catch {unset vhighlights} + unbolden } proc vhighlightmore {} { @@ -1787,11 +1795,8 @@ proc hfiles_change {name ix op} { # delete previous highlights catch {close $filehighlight} unset filehighlight - set rows [array names fhighlights] - if {$rows ne {}} { - unset fhighlights - unbolden $rows - } + catch {unset fhighlights} + unbolden unhighlight_filelist } set highlight_paths {} @@ -1817,7 +1822,7 @@ proc makepatterns {l} { } proc do_file_hl {serial} { - global highlight_files filehighlight highlight_paths gdttype + global highlight_files filehighlight highlight_paths gdttype fhl_list if {$gdttype eq "touching paths:"} { if {[catch {set paths [shellsplit $highlight_files]}]} return @@ -1831,64 +1836,72 @@ proc do_file_hl {serial} { set filehighlight [open $cmd r+] fconfigure $filehighlight -blocking 0 fileevent $filehighlight readable readfhighlight + set fhl_list {} drawvisible flushhighlights } proc flushhighlights {} { - global filehighlight + global filehighlight fhl_list if {[info exists filehighlight]} { + lappend fhl_list {} puts $filehighlight "" flush $filehighlight } } proc askfilehighlight {row id} { - global filehighlight fhighlights + global filehighlight fhighlights fhl_list - set fhighlights($row) 0 + lappend fhl_list $id + set fhighlights($row) -1 puts $filehighlight $id } proc readfhighlight {} { global filehighlight fhighlights commitrow curview mainfont iddrawn - - set n [gets $filehighlight line] - if {$n < 0} { - if {[eof $filehighlight]} { - # strange... - puts "oops, git-diff-tree died" - catch {close $filehighlight} - unset filehighlight + global fhl_list + + while {[gets $filehighlight line] >= 0} { + set line [string trim $line] + set i [lsearch -exact $fhl_list $line] + if {$i < 0} continue + for {set j 0} {$j < $i} {incr j} { + set id [lindex $fhl_list $j] + if {[info exists commitrow($curview,$id)]} { + set fhighlights($commitrow($curview,$id)) 0 + } } - return + set fhl_list [lrange $fhl_list [expr {$i+1}] end] + if {$line eq {}} continue + if {![info exists commitrow($curview,$line)]} continue + set row $commitrow($curview,$line) + if {[info exists iddrawn($line)] && ![ishighlighted $row]} { + bolden $row [concat $mainfont bold] + } + set fhighlights($row) 1 } - set line [string trim $line] - if {$line eq {}} return - if {![info exists commitrow($curview,$line)]} return - set row $commitrow($curview,$line) - if {[info exists iddrawn($line)] && ![ishighlighted $row]} { - bolden $row [concat $mainfont bold] + if {[eof $filehighlight]} { + # strange... + puts "oops, git-diff-tree died" + catch {close $filehighlight} + unset filehighlight } - set fhighlights($row) 1 + next_hlcont } proc find_change {name ix op} { - global nhighlights mainfont + global nhighlights mainfont boldnamerows global findstring findpattern findtype # delete previous highlights, if any - set rows [array names nhighlights] - if {$rows ne {}} { - foreach row $rows { - if {$nhighlights($row) >= 2} { - bolden_name $row $mainfont - } - } - unset nhighlights - unbolden $rows + foreach row $boldnamerows { + bolden_name $row $mainfont } + set boldnamerows {} + catch {unset nhighlights} + unbolden if {$findtype ne "Regexp"} { set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \ $findstring] @@ -1964,11 +1977,8 @@ proc rhighlight_sel {a} { proc rhighlight_none {} { global rhighlights - set rows [array names rhighlights] - if {$rows ne {}} { - unset rhighlights - unbolden $rows - } + catch {unset rhighlights} + unbolden } proc is_descendent {a} { @@ -2066,6 +2076,81 @@ proc askrelhighlight {row id} { set rhighlights($row) $isbold } +proc next_hlcont {} { + global fhl_row fhl_dirn displayorder numcommits + global vhighlights fhighlights nhighlights rhighlights + global hlview filehighlight findstring highlight_related + + if {![info exists fhl_dirn] || $fhl_dirn == 0} return + set row $fhl_row + while {1} { + if {$row < 0 || $row >= $numcommits} { + bell + set fhl_dirn 0 + return + } + set id [lindex $displayorder $row] + if {[info exists hlview]} { + if {![info exists vhighlights($row)]} { + askvhighlight $row $id + } + if {$vhighlights($row) > 0} break + } + if {$findstring ne {}} { + if {![info exists nhighlights($row)]} { + askfindhighlight $row $id + } + if {$nhighlights($row) > 0} break + } + if {$highlight_related ne "None"} { + if {![info exists rhighlights($row)]} { + askrelhighlight $row $id + } + if {$rhighlights($row) > 0} break + } + if {[info exists filehighlight]} { + if {![info exists fhighlights($row)]} { + # ask for a few more while we're at it... + set r $row + for {set n 0} {$n < 100} {incr n} { + if {![info exists fhighlights($r)]} { + askfilehighlight $r [lindex $displayorder $r] + } + incr r $fhl_dirn + if {$r < 0 || $r >= $numcommits} break + } + flushhighlights + } + if {$fhighlights($row) < 0} { + set fhl_row $row + return + } + if {$fhighlights($row) > 0} break + } + incr row $fhl_dirn + } + set fhl_dirn 0 + selectline $row 1 +} + +proc next_highlight {dirn} { + global selectedline fhl_row fhl_dirn + global hlview filehighlight findstring highlight_related + + if {![info exists selectedline]} return + if {!([info exists hlview] || $findstring ne {} || + $highlight_related ne "None" || [info exists filehighlight])} return + set fhl_row [expr {$selectedline + $dirn}] + set fhl_dirn $dirn + next_hlcont +} + +proc cancel_next_highlight {} { + global fhl_dirn + + set fhl_dirn 0 +} + # Graph layout functions proc shortids {ids} { @@ -2785,7 +2870,7 @@ proc drawcmittext {id row col rmx} { global commitlisted commitinfo rowidlist global rowtextx idpos idtags idheads idotherrefs global linehtag linentag linedtag - global mainfont canvxmax + global mainfont canvxmax boldrows boldnamerows set ofill [expr {[lindex $commitlisted $row]? "blue": "white"}] set x [xc $row $col] @@ -2814,8 +2899,10 @@ proc drawcmittext {id row col rmx} { set nfont $mainfont set isbold [ishighlighted $row] if {$isbold > 0} { + lappend boldrows $row lappend font bold if {$isbold > 1} { + lappend boldnamerows $row lappend nfont bold } } @@ -3232,6 +3319,7 @@ proc dofind {} { stopfindproc unmarkmatches + cancel_next_highlight focus . set matchinglines {} if {$findtype == "IgnCase"} { @@ -3490,6 +3578,7 @@ proc selectline {l isnew} { catch {unset pending_select} $canv delete hover normalline + cancel_next_highlight if {$l < 0 || $l >= $numcommits} return set y [expr {$canvy0 + $l * $linespc}] set ymax [lindex [$canv cget -scrollregion] 3] @@ -3662,6 +3751,7 @@ proc unselectline {} { catch {unset currentid} allcanvs delete secsel rhighlight_none + cancel_next_highlight } proc reselectline {} { @@ -5290,6 +5380,8 @@ set fh_serial 0 set nhl_names {} set highlight_paths {} set searchdirn -forwards +set boldrows {} +set boldnamerows {} set optim_delay 16 -- cgit v1.2.3 From b8ab2e177a7dacc37af933ec382ef9ea929127ee Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 3 Jun 2006 19:11:13 +1000 Subject: gitk: Show nearby tags This adds a feature to the diff display window where it will show the tags that this commit follows (is a descendent of) and precedes (is an ancestor of). Specifically, it will show the tags for all tagged descendents that are not a descendent of another tagged descendent of this commit, and the tags for all tagged ancestors that are not ancestors of another tagged ancestor of this commit. To do this, gitk reads the complete commit graph using git rev-list and performs a couple of traversals of the tree. This is done in the background, but since it can be time-consuming, there is an option to turn it off in the `edit preferences' window. Signed-off-by: Paul Mackerras --- gitk | 270 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 247 insertions(+), 23 deletions(-) diff --git a/gitk b/gitk index 25c86b70af..3db662577b 100755 --- a/gitk +++ b/gitk @@ -743,7 +743,7 @@ proc click {w} { proc savestuff {w} { global canv canv2 canv3 ctext cflist mainfont textfont uifont global stuffsaved findmergefiles maxgraphpct - global maxwidth + global maxwidth showneartags global viewname viewfiles viewargs viewperm nextviewnum global cmitmode wrapcomment @@ -759,6 +759,7 @@ proc savestuff {w} { puts $f [list set maxwidth $maxwidth] puts $f [list set cmitmode $cmitmode] puts $f [list set wrapcomment $wrapcomment] + puts $f [list set showneartags $showneartags] puts $f "set geometry(width) [winfo width .ctop]" puts $f "set geometry(height) [winfo height .ctop]" puts $f "set geometry(canv1) [expr {[winfo width $canv]-2}]" @@ -3523,7 +3524,7 @@ proc commit_descriptor {p} { if {[llength $commitinfo($p)] > 1} { set l [lindex $commitinfo($p) 0] } - return "$p ($l)" + return "$p ($l)\n" } # append some text to the ctext widget, and make any SHA1 ID @@ -3533,7 +3534,6 @@ proc appendwithlinks {text tags} { set start [$ctext index "end - 1c"] $ctext insert end $text $tags - $ctext insert end "\n" set links [regexp -indices -all -inline {[0-9a-f]{40}} $text] foreach l $links { set s [lindex $l 0] @@ -3568,6 +3568,54 @@ proc viewnextline {dir} { allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}] } +# add a list of tag names at position pos +proc appendrefs {pos l} { + global ctext commitrow linknum curview idtags + + if {[catch {$ctext index $pos}]} return + set tags {} + foreach id $l { + foreach tag $idtags($id) { + lappend tags [concat $tag $id] + } + } + set tags [lsort -index 1 $tags] + set sep {} + foreach tag $tags { + set name [lindex $tag 0] + set id [lindex $tag 1] + set lk link$linknum + incr linknum + $ctext insert $pos $sep + $ctext insert $pos $name $lk + $ctext tag conf $lk -foreground blue + if {[info exists commitrow($curview,$id)]} { + $ctext tag bind $lk <1> \ + [list selectline $commitrow($curview,$id) 1] + $ctext tag conf $lk -underline 1 + $ctext tag bind $lk { %W configure -cursor hand2 } + $ctext tag bind $lk { %W configure -cursor $curtextcursor } + } + set sep ", " + } +} + +# called when we have finished computing the nearby tags +proc dispneartags {} { + global selectedline currentid ctext anc_tags desc_tags showneartags + + if {![info exists selectedline] || !$showneartags} return + set id $currentid + $ctext conf -state normal + if {[info exists anc_tags($id)]} { + appendrefs follows $anc_tags($id) + } + if {[info exists desc_tags($id)]} { + appendrefs precedes $desc_tags($id) + } + $ctext conf -state disabled +} + proc selectline {l isnew} { global canv canv2 canv3 ctext commitinfo selectedline global displayorder linehtag linentag linedtag @@ -3575,7 +3623,7 @@ proc selectline {l isnew} { global currentid sha1entry global commentend idtags linknum global mergemax numcommits pending_select - global cmitmode + global cmitmode desc_tags anc_tags showneartags allcommits catch {unset pending_select} $canv delete hover @@ -3678,16 +3726,35 @@ proc selectline {l isnew} { } } else { foreach p $olds { - append headers "Parent: [commit_descriptor $p]\n" + append headers "Parent: [commit_descriptor $p]" } } foreach c [lindex $childlist $l] { - append headers "Child: [commit_descriptor $c]\n" + append headers "Child: [commit_descriptor $c]" } # make anything that looks like a SHA1 ID be a clickable link appendwithlinks $headers {} + if {$showneartags} { + if {![info exists allcommits]} { + getallcommits + } + $ctext insert end "Follows: " + $ctext mark set follows "end -1c" + $ctext mark gravity follows left + if {[info exists anc_tags($id)]} { + appendrefs follows $anc_tags($id) + } + $ctext insert end "\nPrecedes: " + $ctext mark set precedes "end -1c" + $ctext mark gravity precedes left + if {[info exists desc_tags($id)]} { + appendrefs precedes $desc_tags($id) + } + $ctext insert end "\n" + } + $ctext insert end "\n" appendwithlinks [lindex $info 5] {comment} $ctext tag delete Comments @@ -4814,12 +4881,19 @@ proc domktag {} { proc redrawtags {id} { global canv linehtag commitrow idpos selectedline curview + global mainfont if {![info exists commitrow($curview,$id)]} return drawcmitrow $commitrow($curview,$id) $canv delete tag.$id set xt [eval drawtags $id $idpos($id)] $canv coords $linehtag($commitrow($curview,$id)) $xt [lindex $idpos($id) 2] + set text [$canv itemcget $linehtag($commitrow($curview,$id)) -text] + set xr [expr {$xt + [font measure $mainfont $text]}] + if {$xr > $canvxmax} { + set canvxmax $xr + setcanvscroll + } if {[info exists selectedline] && $selectedline == $commitrow($curview,$id)} { selectline $selectedline 0 @@ -4893,22 +4967,164 @@ proc wrcomcan {} { unset wrcomtop } -proc listrefs {id} { - global idtags idheads idotherrefs +# Stuff for finding nearby tags +proc getallcommits {} { + global allcstart allcommits - set x {} - if {[info exists idtags($id)]} { - set x $idtags($id) + set fd [open [concat | git rev-list --all --topo-order --parents] r] + fconfigure $fd -blocking 0 + set allcommits "reading" + nowbusy allcommits + restartgetall $fd +} + +proc restartgetall {fd} { + global allcstart + + fileevent $fd readable [list getallclines $fd] + set allcstart [clock clicks -milliseconds] +} + +proc combine_dtags {l1 l2} { + global tagisdesc notfirstd + + set res [lsort -unique [concat $l1 $l2]] + for {set i 0} {$i < [llength $res]} {incr i} { + set x [lindex $res $i] + for {set j [expr {$i+1}]} {$j < [llength $res]} {} { + set y [lindex $res $j] + if {[info exists tagisdesc($x,$y)]} { + if {$tagisdesc($x,$y) > 0} { + # x is a descendent of y, exclude x + set res [lreplace $res $i $i] + incr i -1 + break + } else { + # y is a descendent of x, exclude y + set res [lreplace $res $j $j] + } + } else { + # no relation, keep going + incr j + } + } } - set y {} - if {[info exists idheads($id)]} { - set y $idheads($id) + return $res +} + +proc combine_atags {l1 l2} { + global tagisdesc + + set res [lsort -unique [concat $l1 $l2]] + for {set i 0} {$i < [llength $res]} {incr i} { + set x [lindex $res $i] + for {set j [expr {$i+1}]} {$j < [llength $res]} {} { + set y [lindex $res $j] + if {[info exists tagisdesc($x,$y)]} { + if {$tagisdesc($x,$y) < 0} { + # x is an ancestor of y, exclude x + set res [lreplace $res $i $i] + incr i -1 + break + } else { + # y is an ancestor of x, exclude y + set res [lreplace $res $j $j] + } + } else { + # no relation, keep going + incr j + } + } } - set z {} - if {[info exists idotherrefs($id)]} { - set z $idotherrefs($id) + return $res +} + +proc getallclines {fd} { + global allparents allchildren allcommits allcstart + global desc_tags anc_tags idtags alldtags tagisdesc allids + + while {[gets $fd line] >= 0} { + set id [lindex $line 0] + lappend allids $id + set olds [lrange $line 1 end] + set allparents($id) $olds + if {![info exists allchildren($id)]} { + set allchildren($id) {} + } + foreach p $olds { + lappend allchildren($p) $id + } + # compute nearest tagged descendents as we go + set dtags {} + foreach child $allchildren($id) { + if {[info exists idtags($child)]} { + set ctags [list $child] + } else { + set ctags $desc_tags($child) + } + if {$dtags eq {}} { + set dtags $ctags + } elseif {$ctags ne $dtags} { + set dtags [combine_dtags $dtags $ctags] + } + } + set desc_tags($id) $dtags + if {[info exists idtags($id)]} { + set adt $dtags + foreach tag $dtags { + set adt [concat $adt $alldtags($tag)] + } + set adt [lsort -unique $adt] + set alldtags($id) $adt + foreach tag $adt { + set tagisdesc($id,$tag) -1 + set tagisdesc($tag,$id) 1 + } + } + if {[clock clicks -milliseconds] - $allcstart >= 50} { + fileevent $fd readable {} + after idle restartgetall $fd + return + } + } + if {[eof $fd]} { + after idle restartatags [llength $allids] + if {[catch {close $fd} err]} { + error_popup "Error reading full commit graph: $err.\n\ + Results may be incomplete." + } + } +} + +# walk backward through the tree and compute nearest tagged ancestors +proc restartatags {i} { + global allids allparents idtags anc_tags t0 + + set t0 [clock clicks -milliseconds] + while {[incr i -1] >= 0} { + set id [lindex $allids $i] + set atags {} + foreach p $allparents($id) { + if {[info exists idtags($p)]} { + set ptags [list $p] + } else { + set ptags $anc_tags($p) + } + if {$atags eq {}} { + set atags $ptags + } elseif {$ptags ne $atags} { + set atags [combine_atags $atags $ptags] + } + } + set anc_tags($id) $atags + if {[clock clicks -milliseconds] - $t0 >= 50} { + after idle restartatags $i + return + } } - return [list $x $y $z] + set allcommits "done" + notbusy allcommits + dispneartags } proc rereadrefs {} { @@ -4959,7 +5175,7 @@ proc doquit {} { proc doprefs {} { global maxwidth maxgraphpct diffopts - global oldprefs prefstop + global oldprefs prefstop showneartags set top .gitkprefs set prefstop $top @@ -4967,7 +5183,7 @@ proc doprefs {} { raise $top return } - foreach v {maxwidth maxgraphpct diffopts} { + foreach v {maxwidth maxgraphpct diffopts showneartags} { set oldprefs($v) [set $v] } toplevel $top @@ -4989,6 +5205,11 @@ proc doprefs {} { -font optionfont entry $top.diffopt -width 20 -textvariable diffopts grid x $top.diffoptl $top.diffopt -sticky w + frame $top.ntag + label $top.ntag.l -text "Display nearby tags" -font optionfont + checkbutton $top.ntag.b -variable showneartags + pack $top.ntag.b $top.ntag.l -side left + grid x $top.ntag -sticky w frame $top.buts button $top.buts.ok -text "OK" -command prefsok button $top.buts.can -text "Cancel" -command prefscan @@ -5000,9 +5221,9 @@ proc doprefs {} { proc prefscan {} { global maxwidth maxgraphpct diffopts - global oldprefs prefstop + global oldprefs prefstop showneartags - foreach v {maxwidth maxgraphpct diffopts} { + foreach v {maxwidth maxgraphpct diffopts showneartags} { set $v $oldprefs($v) } catch {destroy $prefstop} @@ -5011,13 +5232,15 @@ proc prefscan {} { proc prefsok {} { global maxwidth maxgraphpct - global oldprefs prefstop + global oldprefs prefstop showneartags catch {destroy $prefstop} unset prefstop if {$maxwidth != $oldprefs(maxwidth) || $maxgraphpct != $oldprefs(maxgraphpct)} { redisplay + } elseif {$showneartags != $oldprefs(showneartags)} { + reselectline } } @@ -5328,6 +5551,7 @@ set downarrowlen 7 set mingaplen 30 set cmitmode "patch" set wrapcomment "none" +set showneartags 1 set colors {green red blue magenta darkgrey brown orange} -- cgit v1.2.3 From ef030b8547eaeea1ef992310536b0b637e0c9431 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sun, 4 Jun 2006 11:50:38 +1000 Subject: gitk: Show branch name(s) as well, if "show nearby tags" is enabled This is a small extension to the code that reads the complete commit graph, to make it compute descendent heads as well as descendent tags. We don't exclude descendent heads that are descendents of other descendent heads as we do for tags, since it is useful to know all the branches that a commit is on. Signed-off-by: Paul Mackerras --- gitk | 54 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/gitk b/gitk index 3db662577b..91c11a368f 100755 --- a/gitk +++ b/gitk @@ -3568,14 +3568,17 @@ proc viewnextline {dir} { allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}] } -# add a list of tag names at position pos -proc appendrefs {pos l} { - global ctext commitrow linknum curview idtags +# add a list of tag or branch names at position pos +# returns the number of names inserted +proc appendrefs {pos l var} { + global ctext commitrow linknum curview idtags $var - if {[catch {$ctext index $pos}]} return + if {[catch {$ctext index $pos}]} { + return 0 + } set tags {} foreach id $l { - foreach tag $idtags($id) { + foreach tag [set $var\($id\)] { lappend tags [concat $tag $id] } } @@ -3598,20 +3601,27 @@ proc appendrefs {pos l} { } set sep ", " } + return [llength $tags] } # called when we have finished computing the nearby tags proc dispneartags {} { global selectedline currentid ctext anc_tags desc_tags showneartags + global desc_heads if {![info exists selectedline] || !$showneartags} return set id $currentid $ctext conf -state normal + if {[info exists desc_heads($id)]} { + if {[appendrefs branch $desc_heads($id) idheads] > 1} { + $ctext insert "branch -2c" "es" + } + } if {[info exists anc_tags($id)]} { - appendrefs follows $anc_tags($id) + appendrefs follows $anc_tags($id) idtags } if {[info exists desc_tags($id)]} { - appendrefs precedes $desc_tags($id) + appendrefs precedes $desc_tags($id) idtags } $ctext conf -state disabled } @@ -3623,7 +3633,7 @@ proc selectline {l isnew} { global currentid sha1entry global commentend idtags linknum global mergemax numcommits pending_select - global cmitmode desc_tags anc_tags showneartags allcommits + global cmitmode desc_tags anc_tags showneartags allcommits desc_heads catch {unset pending_select} $canv delete hover @@ -3740,17 +3750,26 @@ proc selectline {l isnew} { if {![info exists allcommits]} { getallcommits } - $ctext insert end "Follows: " + $ctext insert end "Branch: " + $ctext mark set branch "end -1c" + $ctext mark gravity branch left + if {[info exists desc_heads($id)]} { + if {[appendrefs branch $desc_heads($id) idheads] > 1} { + # turn "Branch" into "Branches" + $ctext insert "branch -2c" "es" + } + } + $ctext insert end "\nFollows: " $ctext mark set follows "end -1c" $ctext mark gravity follows left if {[info exists anc_tags($id)]} { - appendrefs follows $anc_tags($id) + appendrefs follows $anc_tags($id) idtags } $ctext insert end "\nPrecedes: " $ctext mark set precedes "end -1c" $ctext mark gravity precedes left if {[info exists desc_tags($id)]} { - appendrefs precedes $desc_tags($id) + appendrefs precedes $desc_tags($id) idtags } $ctext insert end "\n" } @@ -5042,6 +5061,7 @@ proc combine_atags {l1 l2} { proc getallclines {fd} { global allparents allchildren allcommits allcstart global desc_tags anc_tags idtags alldtags tagisdesc allids + global desc_heads idheads while {[gets $fd line] >= 0} { set id [lindex $line 0] @@ -5055,7 +5075,9 @@ proc getallclines {fd} { lappend allchildren($p) $id } # compute nearest tagged descendents as we go + # also compute descendent heads set dtags {} + set dheads {} foreach child $allchildren($id) { if {[info exists idtags($child)]} { set ctags [list $child] @@ -5067,6 +5089,12 @@ proc getallclines {fd} { } elseif {$ctags ne $dtags} { set dtags [combine_dtags $dtags $ctags] } + set cheads $desc_heads($child) + if {$dheads eq {}} { + set dheads $cheads + } elseif {$cheads ne $dheads} { + set dheads [lsort -unique [concat $dheads $cheads]] + } } set desc_tags($id) $dtags if {[info exists idtags($id)]} { @@ -5081,6 +5109,10 @@ proc getallclines {fd} { set tagisdesc($tag,$id) 1 } } + if {[info exists idheads($id)]} { + lappend dheads $id + } + set desc_heads($id) $dheads if {[clock clicks -milliseconds] - $allcstart >= 50} { fileevent $fd readable {} after idle restartgetall $fd -- cgit v1.2.3