git-gui: Reimplement and enhance auto-selection of diffs.
Generalize the next_diff system, and implement auto-reselection for merge tool resolution and reshow_diff. Also add auto-selection of diffs after rescan, if no diff is already selected. New auto-select rules: - Rescan auto-selects the first conflicting file, or if none a modified tracked file, if nothing was selected previously. - Resolving a conflict auto-selects the nearest conflicting file, or nothing if everything is resolved. - Staging the last remaining hunk auto-selects the nearest modified staged file. - Staging a file through its icon auto-selects the nearest file. Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
This commit is contained in:
parent
ff515d81fa
commit
29853b9010
122
git-gui.sh
122
git-gui.sh
@ -1326,6 +1326,8 @@ proc rescan_done {fd buf after} {
|
||||
unlock_index
|
||||
display_all_files
|
||||
if {$current_diff_path ne {}} reshow_diff
|
||||
if {$current_diff_path eq {}} select_first_diff
|
||||
|
||||
uplevel #0 $after
|
||||
}
|
||||
|
||||
@ -1821,7 +1823,98 @@ proc do_commit {} {
|
||||
|
||||
proc next_diff {} {
|
||||
global next_diff_p next_diff_w next_diff_i
|
||||
show_diff $next_diff_p $next_diff_w $next_diff_i
|
||||
show_diff $next_diff_p $next_diff_w {}
|
||||
}
|
||||
|
||||
proc find_anchor_pos {lst name} {
|
||||
set lid [lsearch -sorted -exact $lst $name]
|
||||
|
||||
if {$lid == -1} {
|
||||
set lid 0
|
||||
foreach lname $lst {
|
||||
if {$lname >= $name} break
|
||||
incr lid
|
||||
}
|
||||
}
|
||||
|
||||
return $lid
|
||||
}
|
||||
|
||||
proc find_file_from {flist idx delta path mmask} {
|
||||
global file_states
|
||||
|
||||
set len [llength $flist]
|
||||
while {$idx >= 0 && $idx < $len} {
|
||||
set name [lindex $flist $idx]
|
||||
|
||||
if {$name ne $path && [info exists file_states($name)]} {
|
||||
set state [lindex $file_states($name) 0]
|
||||
|
||||
if {$mmask eq {} || [regexp $mmask $state]} {
|
||||
return $idx
|
||||
}
|
||||
}
|
||||
|
||||
incr idx $delta
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
|
||||
proc find_next_diff {w path {lno {}} {mmask {}}} {
|
||||
global next_diff_p next_diff_w next_diff_i
|
||||
global file_lists ui_index ui_workdir
|
||||
|
||||
set flist $file_lists($w)
|
||||
if {$lno eq {}} {
|
||||
set lno [find_anchor_pos $flist $path]
|
||||
} else {
|
||||
incr lno -1
|
||||
}
|
||||
|
||||
if {$mmask ne {} && ![regexp {(^\^)|(\$$)} $mmask]} {
|
||||
if {$w eq $ui_index} {
|
||||
set mmask "^$mmask"
|
||||
} else {
|
||||
set mmask "$mmask\$"
|
||||
}
|
||||
}
|
||||
|
||||
set idx [find_file_from $flist $lno 1 $path $mmask]
|
||||
if {$idx eq {}} {
|
||||
incr lno -1
|
||||
set idx [find_file_from $flist $lno -1 $path $mmask]
|
||||
}
|
||||
|
||||
if {$idx ne {}} {
|
||||
set next_diff_w $w
|
||||
set next_diff_p [lindex $flist $idx]
|
||||
set next_diff_i [expr {$idx+1}]
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
proc next_diff_after_action {w path {lno {}} {mmask {}}} {
|
||||
global current_diff_path
|
||||
|
||||
if {$path ne $current_diff_path} {
|
||||
return {}
|
||||
} elseif {[find_next_diff $w $path $lno $mmask]} {
|
||||
return {next_diff;}
|
||||
} else {
|
||||
return {reshow_diff;}
|
||||
}
|
||||
}
|
||||
|
||||
proc select_first_diff {} {
|
||||
global ui_workdir
|
||||
|
||||
if {[find_next_diff $ui_workdir {} 1 {^_?U}] ||
|
||||
[find_next_diff $ui_workdir {} 1 {[^O]$}]} {
|
||||
next_diff
|
||||
}
|
||||
}
|
||||
|
||||
proc toggle_or_diff {w x y} {
|
||||
@ -1851,32 +1944,7 @@ proc toggle_or_diff {w x y} {
|
||||
}
|
||||
|
||||
if {$col == 0 && $y > 1} {
|
||||
set i [expr {$lno-1}]
|
||||
set ll [expr {[llength $file_lists($w)]-1}]
|
||||
|
||||
if {$i == $ll && $i == 0} {
|
||||
set after {reshow_diff;}
|
||||
} else {
|
||||
global next_diff_p next_diff_w next_diff_i
|
||||
|
||||
set next_diff_w $w
|
||||
|
||||
if {$i < $ll} {
|
||||
set i [expr {$i + 1}]
|
||||
set next_diff_i $i
|
||||
} else {
|
||||
set next_diff_i $i
|
||||
set i [expr {$i - 1}]
|
||||
}
|
||||
|
||||
set next_diff_p [lindex $file_lists($w) $i]
|
||||
|
||||
if {$next_diff_p ne {} && $current_diff_path ne {}} {
|
||||
set after {next_diff;}
|
||||
} else {
|
||||
set after {}
|
||||
}
|
||||
}
|
||||
set after [next_diff_after_action $w $path $lno]
|
||||
|
||||
if {$w eq $ui_index} {
|
||||
update_indexinfo \
|
||||
|
18
lib/diff.tcl
18
lib/diff.tcl
@ -24,10 +24,16 @@ proc reshow_diff {} {
|
||||
set p $current_diff_path
|
||||
if {$p eq {}} {
|
||||
# No diff is being shown.
|
||||
} elseif {$current_diff_side eq {}
|
||||
|| [catch {set s $file_states($p)}]
|
||||
|| [lsearch -sorted -exact $file_lists($current_diff_side) $p] == -1} {
|
||||
} elseif {$current_diff_side eq {}} {
|
||||
clear_diff
|
||||
} elseif {[catch {set s $file_states($p)}]
|
||||
|| [lsearch -sorted -exact $file_lists($current_diff_side) $p] == -1} {
|
||||
|
||||
if {[find_next_diff $current_diff_side $p {} {[^O]}]} {
|
||||
next_diff
|
||||
} else {
|
||||
clear_diff
|
||||
}
|
||||
} else {
|
||||
set save_pos [lindex [$ui_diff yview] 0]
|
||||
show_diff $p $current_diff_side {} $save_pos
|
||||
@ -71,6 +77,7 @@ proc show_diff {path w {lno {}} {scroll_pos {}}} {
|
||||
}
|
||||
if {$lno >= 1} {
|
||||
$w tag add in_diff $lno.0 [expr {$lno + 1}].0
|
||||
$w see $lno.0
|
||||
}
|
||||
|
||||
set s $file_states($path)
|
||||
@ -366,10 +373,9 @@ proc apply_hunk {x y} {
|
||||
}
|
||||
unlock_index
|
||||
display_file $current_diff_path $mi
|
||||
# This should trigger shift to the next changed file
|
||||
if {$o eq {_}} {
|
||||
clear_diff
|
||||
} else {
|
||||
set current_diff_path $current_diff_path
|
||||
reshow_diff
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,13 +24,9 @@ This operation can be undone only by restarting the merge." \
|
||||
}
|
||||
|
||||
proc merge_add_resolution {path} {
|
||||
global current_diff_path
|
||||
global current_diff_path ui_workdir
|
||||
|
||||
if {$path eq $current_diff_path} {
|
||||
set after {reshow_diff;}
|
||||
} else {
|
||||
set after {}
|
||||
}
|
||||
set after [next_diff_after_action $ui_workdir $path {} {^_?U}]
|
||||
|
||||
update_index \
|
||||
[mc "Adding resolution for %s" [short_path $path]] \
|
||||
|
Loading…
Reference in New Issue
Block a user