mirror of
https://github.com/git/git.git
synced 2024-11-24 18:33:43 +08:00
gitk: Fix the find and highlight functions
This reworks the way that the "Find" button (and the /, ?, ^F, and ^G keys) works. Previously, pressing the "Find" button would cause gitk to go off and scan through every commit to see which commits matched, and the user interface was completely unreponsive during that time. Now the searching is done in chunks using the scheduler, so the UI still responds, and the search stops as soon as a matching commit is found. The highlighting of matches using a yellow background is now done in the commit-drawing code and the highlighting code. This ensures that all the commits that are visible that match are highlighted without the search code having to find them all. This also fixes a bug where previously-drawn commits that need to be highlighted were not being highlighted. Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
parent
281404ca1d
commit
4fb0fa197e
331
gitk
331
gitk
@ -1758,7 +1758,7 @@ proc showview {n} {
|
||||
global colormap rowtextx commitrow nextcolor canvxmax
|
||||
global numcommits rowrangelist commitlisted idrowranges rowchk
|
||||
global selectedline currentid canv canvy0
|
||||
global matchinglines treediffs
|
||||
global treediffs
|
||||
global pending_select phase
|
||||
global commitidx rowlaidout rowoptim
|
||||
global commfd
|
||||
@ -1802,7 +1802,6 @@ proc showview {n} {
|
||||
[list {} $rowidlist $rowoffsets $rowrangelist]
|
||||
}
|
||||
}
|
||||
catch {unset matchinglines}
|
||||
catch {unset treediffs}
|
||||
clear_display
|
||||
if {[info exists hlview] && $hlview == $n} {
|
||||
@ -2132,7 +2131,7 @@ proc readfhighlight {} {
|
||||
|
||||
proc find_change {name ix op} {
|
||||
global nhighlights mainfont boldnamerows
|
||||
global findstring findpattern findtype
|
||||
global findstring findpattern findtype markingmatches
|
||||
|
||||
# delete previous highlights, if any
|
||||
foreach row $boldnamerows {
|
||||
@ -2141,17 +2140,32 @@ proc find_change {name ix op} {
|
||||
set boldnamerows {}
|
||||
catch {unset nhighlights}
|
||||
unbolden
|
||||
unmarkmatches
|
||||
if {$findtype ne "Regexp"} {
|
||||
set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \
|
||||
$findstring]
|
||||
set findpattern "*$e*"
|
||||
}
|
||||
set markingmatches [expr {$findstring ne {}}]
|
||||
drawvisible
|
||||
}
|
||||
|
||||
proc doesmatch {f} {
|
||||
global findtype findstring findpattern
|
||||
|
||||
if {$findtype eq "Regexp"} {
|
||||
return [regexp $findstring $f]
|
||||
} elseif {$findtype eq "IgnCase"} {
|
||||
return [string match -nocase $findpattern $f]
|
||||
} else {
|
||||
return [string match $findpattern $f]
|
||||
}
|
||||
}
|
||||
|
||||
proc askfindhighlight {row id} {
|
||||
global nhighlights commitinfo iddrawn mainfont
|
||||
global findstring findtype findloc findpattern
|
||||
global findloc
|
||||
global markingmatches
|
||||
|
||||
if {![info exists commitinfo($id)]} {
|
||||
getcommit $id
|
||||
@ -2160,35 +2174,47 @@ proc askfindhighlight {row id} {
|
||||
set isbold 0
|
||||
set fldtypes {Headline Author Date Committer CDate Comments}
|
||||
foreach f $info ty $fldtypes {
|
||||
if {$findloc ne "All fields" && $findloc ne $ty} {
|
||||
continue
|
||||
}
|
||||
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 {($findloc eq "All fields" || $findloc eq $ty) &&
|
||||
[doesmatch $f]} {
|
||||
if {$ty eq "Author"} {
|
||||
set isbold 2
|
||||
} else {
|
||||
set isbold 1
|
||||
break
|
||||
}
|
||||
set isbold 1
|
||||
}
|
||||
}
|
||||
if {[info exists iddrawn($id)]} {
|
||||
if {$isbold && ![ishighlighted $row]} {
|
||||
bolden $row [concat $mainfont bold]
|
||||
if {$isbold && [info exists iddrawn($id)]} {
|
||||
set f [concat $mainfont bold]
|
||||
if {![ishighlighted $row]} {
|
||||
bolden $row $f
|
||||
if {$isbold > 1} {
|
||||
bolden_name $row $f
|
||||
}
|
||||
}
|
||||
if {$isbold >= 2} {
|
||||
bolden_name $row [concat $mainfont bold]
|
||||
if {$markingmatches} {
|
||||
markrowmatches $row [lindex $info 0] [lindex $info 1]
|
||||
}
|
||||
}
|
||||
set nhighlights($row) $isbold
|
||||
}
|
||||
|
||||
proc markrowmatches {row headline author} {
|
||||
global canv canv2 linehtag linentag
|
||||
|
||||
$canv delete match$row
|
||||
$canv2 delete match$row
|
||||
set m [findmatches $headline]
|
||||
if {$m ne {}} {
|
||||
markmatches $canv $row $headline $linehtag($row) $m \
|
||||
[$canv itemcget $linehtag($row) -font]
|
||||
}
|
||||
set m [findmatches $author]
|
||||
if {$m ne {}} {
|
||||
markmatches $canv2 $row $author $linentag($row) $m \
|
||||
[$canv2 itemcget $linentag($row) -font]
|
||||
}
|
||||
}
|
||||
|
||||
proc vrel_change {name ix op} {
|
||||
global highlight_related
|
||||
|
||||
@ -3309,7 +3335,7 @@ proc drawcmittext {id row col} {
|
||||
global linespc canv canv2 canv3 canvy0 fgcolor
|
||||
global commitlisted commitinfo rowidlist parentlist
|
||||
global rowtextx idpos idtags idheads idotherrefs
|
||||
global linehtag linentag linedtag
|
||||
global linehtag linentag linedtag markingmatches
|
||||
global mainfont canvxmax boldrows boldnamerows fgcolor nullid
|
||||
|
||||
if {$id eq $nullid} {
|
||||
@ -3366,6 +3392,9 @@ proc drawcmittext {id row col} {
|
||||
set linedtag($row) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
|
||||
-text $date -font $mainfont -tags text]
|
||||
set xr [expr {$xt + [font measure $mainfont $headline]}]
|
||||
if {$markingmatches} {
|
||||
markrowmatches $row $headline $name
|
||||
}
|
||||
if {$xr > $canvxmax} {
|
||||
set canvxmax $xr
|
||||
setcanvscroll
|
||||
@ -3436,9 +3465,7 @@ proc drawcommits {row {endrow {}}} {
|
||||
for {} {$r <= $er} {incr r} {
|
||||
set id [lindex $displayorder $r]
|
||||
set wasdrawn [info exists iddrawn($id)]
|
||||
if {!$wasdrawn} {
|
||||
drawcmitrow $r
|
||||
}
|
||||
drawcmitrow $r
|
||||
if {$r == $er} break
|
||||
set nextid [lindex $displayorder [expr {$r + 1}]]
|
||||
if {$wasdrawn && [info exists iddrawn($nextid)]} {
|
||||
@ -3889,101 +3916,166 @@ proc notbusy {what} {
|
||||
}
|
||||
|
||||
proc findmatches {f} {
|
||||
global findtype foundstring foundstrlen
|
||||
global findtype findstring
|
||||
if {$findtype == "Regexp"} {
|
||||
set matches [regexp -indices -all -inline $foundstring $f]
|
||||
set matches [regexp -indices -all -inline $findstring $f]
|
||||
} else {
|
||||
set fs $findstring
|
||||
if {$findtype == "IgnCase"} {
|
||||
set str [string tolower $f]
|
||||
} else {
|
||||
set str $f
|
||||
set f [string tolower $f]
|
||||
set fs [string tolower $fs]
|
||||
}
|
||||
set matches {}
|
||||
set i 0
|
||||
while {[set j [string first $foundstring $str $i]] >= 0} {
|
||||
lappend matches [list $j [expr {$j+$foundstrlen-1}]]
|
||||
set i [expr {$j + $foundstrlen}]
|
||||
set l [string length $fs]
|
||||
while {[set j [string first $fs $f $i]] >= 0} {
|
||||
lappend matches [list $j [expr {$j+$l-1}]]
|
||||
set i [expr {$j + $l}]
|
||||
}
|
||||
}
|
||||
return $matches
|
||||
}
|
||||
|
||||
proc dofind {} {
|
||||
global findtype findloc findstring markedmatches commitinfo
|
||||
global numcommits displayorder linehtag linentag linedtag
|
||||
global mainfont canv canv2 canv3 selectedline
|
||||
global matchinglines foundstring foundstrlen matchstring
|
||||
global commitdata
|
||||
proc dofind {{rev 0}} {
|
||||
global findstring findstartline findcurline selectedline numcommits
|
||||
|
||||
stopfindproc
|
||||
unmarkmatches
|
||||
cancel_next_highlight
|
||||
focus .
|
||||
set matchinglines {}
|
||||
if {$findtype == "IgnCase"} {
|
||||
set foundstring [string tolower $findstring]
|
||||
} else {
|
||||
set foundstring $findstring
|
||||
}
|
||||
set foundstrlen [string length $findstring]
|
||||
if {$foundstrlen == 0} return
|
||||
regsub -all {[*?\[\\]} $foundstring {\\&} matchstring
|
||||
set matchstring "*$matchstring*"
|
||||
if {$findstring eq {} || $numcommits == 0} return
|
||||
if {![info exists selectedline]} {
|
||||
set oldsel -1
|
||||
set findstartline [lindex [visiblerows] $rev]
|
||||
} else {
|
||||
set oldsel $selectedline
|
||||
set findstartline $selectedline
|
||||
}
|
||||
set didsel 0
|
||||
set fldtypes {Headline Author Date Committer CDate Comments}
|
||||
set l -1
|
||||
foreach id $displayorder {
|
||||
set d $commitdata($id)
|
||||
incr l
|
||||
if {$findtype == "Regexp"} {
|
||||
set doesmatch [regexp $foundstring $d]
|
||||
} elseif {$findtype == "IgnCase"} {
|
||||
set doesmatch [string match -nocase $matchstring $d]
|
||||
} else {
|
||||
set doesmatch [string match $matchstring $d]
|
||||
set findcurline $findstartline
|
||||
nowbusy finding
|
||||
if {!$rev} {
|
||||
run findmore
|
||||
} else {
|
||||
set findcurline $findstartline
|
||||
if {$findcurline == 0} {
|
||||
set findcurline $numcommits
|
||||
}
|
||||
if {!$doesmatch} continue
|
||||
incr findcurline -1
|
||||
run findmorerev
|
||||
}
|
||||
}
|
||||
|
||||
proc findnext {restart} {
|
||||
global findcurline
|
||||
if {![info exists findcurline]} {
|
||||
if {$restart} {
|
||||
dofind
|
||||
} else {
|
||||
bell
|
||||
}
|
||||
} else {
|
||||
run findmore
|
||||
nowbusy finding
|
||||
}
|
||||
}
|
||||
|
||||
proc findprev {} {
|
||||
global findcurline
|
||||
if {![info exists findcurline]} {
|
||||
dofind 1
|
||||
} else {
|
||||
run findmorerev
|
||||
nowbusy finding
|
||||
}
|
||||
}
|
||||
|
||||
proc findmore {} {
|
||||
global commitdata commitinfo numcommits findstring findpattern findloc
|
||||
global findstartline findcurline markingmatches displayorder
|
||||
|
||||
set fldtypes {Headline Author Date Committer CDate Comments}
|
||||
set l [expr {$findcurline + 1}]
|
||||
if {$l >= $numcommits} {
|
||||
set l 0
|
||||
}
|
||||
if {$l <= $findstartline} {
|
||||
set lim [expr {$findstartline + 1}]
|
||||
} else {
|
||||
set lim $numcommits
|
||||
}
|
||||
if {$lim - $l > 500} {
|
||||
set lim [expr {$l + 500}]
|
||||
}
|
||||
set last 0
|
||||
for {} {$l < $lim} {incr l} {
|
||||
set id [lindex $displayorder $l]
|
||||
if {![doesmatch $commitdata($id)]} continue
|
||||
if {![info exists commitinfo($id)]} {
|
||||
getcommit $id
|
||||
}
|
||||
set info $commitinfo($id)
|
||||
set doesmatch 0
|
||||
foreach f $info ty $fldtypes {
|
||||
if {$findloc != "All fields" && $findloc != $ty} {
|
||||
continue
|
||||
}
|
||||
set matches [findmatches $f]
|
||||
if {$matches == {}} continue
|
||||
set doesmatch 1
|
||||
if {$ty == "Headline"} {
|
||||
drawcommits $l
|
||||
markmatches $canv $l $f $linehtag($l) $matches $mainfont
|
||||
} elseif {$ty == "Author"} {
|
||||
drawcommits $l
|
||||
markmatches $canv2 $l $f $linentag($l) $matches $mainfont
|
||||
} elseif {$ty == "Date"} {
|
||||
drawcommits $l
|
||||
markmatches $canv3 $l $f $linedtag($l) $matches $mainfont
|
||||
}
|
||||
}
|
||||
if {$doesmatch} {
|
||||
lappend matchinglines $l
|
||||
if {!$didsel && $l > $oldsel} {
|
||||
if {($findloc eq "All fields" || $findloc eq $ty) &&
|
||||
[doesmatch $f]} {
|
||||
set markingmatches 1
|
||||
findselectline $l
|
||||
set didsel 1
|
||||
notbusy finding
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
if {$matchinglines == {}} {
|
||||
if {$l == $findstartline + 1} {
|
||||
bell
|
||||
} elseif {!$didsel} {
|
||||
findselectline [lindex $matchinglines 0]
|
||||
unset findcurline
|
||||
notbusy finding
|
||||
return 0
|
||||
}
|
||||
set findcurline [expr {$l - 1}]
|
||||
return 1
|
||||
}
|
||||
|
||||
proc findmorerev {} {
|
||||
global commitdata commitinfo numcommits findstring findpattern findloc
|
||||
global findstartline findcurline markingmatches displayorder
|
||||
|
||||
set fldtypes {Headline Author Date Committer CDate Comments}
|
||||
set l $findcurline
|
||||
if {$l == 0} {
|
||||
set l $numcommits
|
||||
}
|
||||
incr l -1
|
||||
if {$l >= $findstartline} {
|
||||
set lim [expr {$findstartline - 1}]
|
||||
} else {
|
||||
set lim -1
|
||||
}
|
||||
if {$l - $lim > 500} {
|
||||
set lim [expr {$l - 500}]
|
||||
}
|
||||
set last 0
|
||||
for {} {$l > $lim} {incr l -1} {
|
||||
set id [lindex $displayorder $l]
|
||||
if {![doesmatch $commitdata($id)]} continue
|
||||
if {![info exists commitinfo($id)]} {
|
||||
getcommit $id
|
||||
}
|
||||
set info $commitinfo($id)
|
||||
foreach f $info ty $fldtypes {
|
||||
if {($findloc eq "All fields" || $findloc eq $ty) &&
|
||||
[doesmatch $f]} {
|
||||
set markingmatches 1
|
||||
findselectline $l
|
||||
notbusy finding
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
if {$l == -1} {
|
||||
bell
|
||||
unset findcurline
|
||||
notbusy finding
|
||||
return 0
|
||||
}
|
||||
set findcurline [expr {$l + 1}]
|
||||
return 1
|
||||
}
|
||||
|
||||
proc findselectline {l} {
|
||||
@ -4001,43 +4093,6 @@ proc findselectline {l} {
|
||||
}
|
||||
}
|
||||
|
||||
proc findnext {restart} {
|
||||
global matchinglines selectedline
|
||||
if {![info exists matchinglines]} {
|
||||
if {$restart} {
|
||||
dofind
|
||||
}
|
||||
return
|
||||
}
|
||||
if {![info exists selectedline]} return
|
||||
foreach l $matchinglines {
|
||||
if {$l > $selectedline} {
|
||||
findselectline $l
|
||||
return
|
||||
}
|
||||
}
|
||||
bell
|
||||
}
|
||||
|
||||
proc findprev {} {
|
||||
global matchinglines selectedline
|
||||
if {![info exists matchinglines]} {
|
||||
dofind
|
||||
return
|
||||
}
|
||||
if {![info exists selectedline]} return
|
||||
set prev {}
|
||||
foreach l $matchinglines {
|
||||
if {$l >= $selectedline} break
|
||||
set prev $l
|
||||
}
|
||||
if {$prev != {}} {
|
||||
findselectline $prev
|
||||
} else {
|
||||
bell
|
||||
}
|
||||
}
|
||||
|
||||
proc stopfindproc {{done 0}} {
|
||||
global findprocpid findprocfile findids
|
||||
global ctext findoldcursor phase maincursor textcursor
|
||||
@ -4055,18 +4110,7 @@ proc stopfindproc {{done 0}} {
|
||||
notbusy find
|
||||
}
|
||||
|
||||
# mark a commit as matching by putting a yellow background
|
||||
# behind the headline
|
||||
proc markheadline {l id} {
|
||||
global canv mainfont linehtag
|
||||
|
||||
drawcommits $l
|
||||
set bbox [$canv bbox $linehtag($l)]
|
||||
set t [$canv create rect $bbox -outline {} -tags matches -fill yellow]
|
||||
$canv lower $t
|
||||
}
|
||||
|
||||
# mark the bits of a headline, author or date that match a find string
|
||||
# mark the bits of a headline or author that match a find string
|
||||
proc markmatches {canv l str tag matches font} {
|
||||
set bbox [$canv bbox $tag]
|
||||
set x0 [lindex $bbox 0]
|
||||
@ -4080,16 +4124,18 @@ proc markmatches {canv l str tag matches font} {
|
||||
set xlen [font measure $font [string range $str 0 [expr {$end}]]]
|
||||
set t [$canv create rect [expr {$x0+$xoff}] $y0 \
|
||||
[expr {$x0+$xlen+2}] $y1 \
|
||||
-outline {} -tags matches -fill yellow]
|
||||
-outline {} -tags [list match$l matches] -fill yellow]
|
||||
$canv lower $t
|
||||
}
|
||||
}
|
||||
|
||||
proc unmarkmatches {} {
|
||||
global matchinglines findids
|
||||
global findids markingmatches findcurline
|
||||
|
||||
allcanvs delete matches
|
||||
catch {unset matchinglines}
|
||||
catch {unset findids}
|
||||
set markingmatches 0
|
||||
catch {unset findcurline}
|
||||
}
|
||||
|
||||
proc selcanvline {w x y} {
|
||||
@ -7471,6 +7517,7 @@ set searchdirn -forwards
|
||||
set boldrows {}
|
||||
set boldnamerows {}
|
||||
set diffelide {0 0}
|
||||
set markingmatches 0
|
||||
|
||||
set optim_delay 16
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user