@matheusbsbs / matheus-bagliano / commits / 29853b9010
Fork 0

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>

Alexander Gavrilov committed Aug 31, 2008 at 01:02 UTC 29853b901045ff09ac8e5b48a01ebbc96fa4874d
3 files changed +109 -39
git-gui.sh
+95 -27
@@ -1326,6 +1326,8 @@ proc rescan_done {fd buf after} {
1326 unlock_index
1327 display_all_files
1328 if {$current_diff_path ne {}} reshow_diff
1329 + if {$current_diff_path eq {}} select_first_diff
1330 +
1331 uplevel #0 $after
1332 }
1333
@@ -1821,7 +1823,98 @@ proc do_commit {} {
1823
1824 proc next_diff {} {
1825 global next_diff_p next_diff_w next_diff_i
1824 - show_diff $next_diff_p $next_diff_w $next_diff_i
1826 + show_diff $next_diff_p $next_diff_w {}
1827 +}
1828 +
1829 +proc find_anchor_pos {lst name} {
1830 + set lid [lsearch -sorted -exact $lst $name]
1831 +
1832 + if {$lid == -1} {
1833 + set lid 0
1834 + foreach lname $lst {
1835 + if {$lname >= $name} break
1836 + incr lid
1837 + }
1838 + }
1839 +
1840 + return $lid
1841 +}
1842 +
1843 +proc find_file_from {flist idx delta path mmask} {
1844 + global file_states
1845 +
1846 + set len [llength $flist]
1847 + while {$idx >= 0 && $idx < $len} {
1848 + set name [lindex $flist $idx]
1849 +
1850 + if {$name ne $path && [info exists file_states($name)]} {
1851 + set state [lindex $file_states($name) 0]
1852 +
1853 + if {$mmask eq {} || [regexp $mmask $state]} {
1854 + return $idx
1855 + }
1856 + }
1857 +
1858 + incr idx $delta
1859 + }
1860 +
1861 + return {}
1862 +}
1863 +
1864 +proc find_next_diff {w path {lno {}} {mmask {}}} {
1865 + global next_diff_p next_diff_w next_diff_i
1866 + global file_lists ui_index ui_workdir
1867 +
1868 + set flist $file_lists($w)
1869 + if {$lno eq {}} {
1870 + set lno [find_anchor_pos $flist $path]
1871 + } else {
1872 + incr lno -1
1873 + }
1874 +
1875 + if {$mmask ne {} && ![regexp {(^\^)|(\$$)} $mmask]} {
1876 + if {$w eq $ui_index} {
1877 + set mmask "^$mmask"
1878 + } else {
1879 + set mmask "$mmask\$"
1880 + }
1881 + }
1882 +
1883 + set idx [find_file_from $flist $lno 1 $path $mmask]
1884 + if {$idx eq {}} {
1885 + incr lno -1
1886 + set idx [find_file_from $flist $lno -1 $path $mmask]
1887 + }
1888 +
1889 + if {$idx ne {}} {
1890 + set next_diff_w $w
1891 + set next_diff_p [lindex $flist $idx]
1892 + set next_diff_i [expr {$idx+1}]
1893 + return 1
1894 + } else {
1895 + return 0
1896 + }
1897 +}
1898 +
1899 +proc next_diff_after_action {w path {lno {}} {mmask {}}} {
1900 + global current_diff_path
1901 +
1902 + if {$path ne $current_diff_path} {
1903 + return {}
1904 + } elseif {[find_next_diff $w $path $lno $mmask]} {
1905 + return {next_diff;}
1906 + } else {
1907 + return {reshow_diff;}
1908 + }
1909 +}
1910 +
1911 +proc select_first_diff {} {
1912 + global ui_workdir
1913 +
1914 + if {[find_next_diff $ui_workdir {} 1 {^_?U}] ||
1915 + [find_next_diff $ui_workdir {} 1 {[^O]$}]} {
1916 + next_diff
1917 + }
1918 }
1919
1920 proc toggle_or_diff {w x y} {
@@ -1851,32 +1944,7 @@ proc toggle_or_diff {w x y} {
1944 }
1945
1946 if {$col == 0 && $y > 1} {
1854 - set i [expr {$lno-1}]
1855 - set ll [expr {[llength $file_lists($w)]-1}]
1856 -
1857 - if {$i == $ll && $i == 0} {
1858 - set after {reshow_diff;}
1859 - } else {
1860 - global next_diff_p next_diff_w next_diff_i
1861 -
1862 - set next_diff_w $w
1863 -
1864 - if {$i < $ll} {
1865 - set i [expr {$i + 1}]
1866 - set next_diff_i $i
1867 - } else {
1868 - set next_diff_i $i
1869 - set i [expr {$i - 1}]
1870 - }
1871 -
1872 - set next_diff_p [lindex $file_lists($w) $i]
1873 -
1874 - if {$next_diff_p ne {} && $current_diff_path ne {}} {
1875 - set after {next_diff;}
1876 - } else {
1877 - set after {}
1878 - }
1879 - }
1947 + set after [next_diff_after_action $w $path $lno]
1948
1949 if {$w eq $ui_index} {
1950 update_indexinfo \
lib/diff.tcl
+12 -6
@@ -24,10 +24,16 @@ proc reshow_diff {} {
24 set p $current_diff_path
25 if {$p eq {}} {
26 # No diff is being shown.
27 - } elseif {$current_diff_side eq {}
28 - || [catch {set s $file_states($p)}]
29 - || [lsearch -sorted -exact $file_lists($current_diff_side) $p] == -1} {
27 + } elseif {$current_diff_side eq {}} {
28 clear_diff
29 + } elseif {[catch {set s $file_states($p)}]
30 + || [lsearch -sorted -exact $file_lists($current_diff_side) $p] == -1} {
31 +
32 + if {[find_next_diff $current_diff_side $p {} {[^O]}]} {
33 + next_diff
34 + } else {
35 + clear_diff
36 + }
37 } else {
38 set save_pos [lindex [$ui_diff yview] 0]
39 show_diff $p $current_diff_side {} $save_pos
@@ -71,6 +77,7 @@ proc show_diff {path w {lno {}} {scroll_pos {}}} {
77 }
78 if {$lno >= 1} {
79 $w tag add in_diff $lno.0 [expr {$lno + 1}].0
80 + $w see $lno.0
81 }
82
83 set s $file_states($path)
@@ -366,10 +373,9 @@ proc apply_hunk {x y} {
373 }
374 unlock_index
375 display_file $current_diff_path $mi
376 + # This should trigger shift to the next changed file
377 if {$o eq {_}} {
370 - clear_diff
371 - } else {
372 - set current_diff_path $current_diff_path
378 + reshow_diff
379 }
380 }
381
lib/mergetool.tcl
+2 -6
@@ -24,13 +24,9 @@ This operation can be undone only by restarting the merge." \
24 }
25
26 proc merge_add_resolution {path} {
27 - global current_diff_path
27 + global current_diff_path ui_workdir
28
29 - if {$path eq $current_diff_path} {
30 - set after {reshow_diff;}
31 - } else {
32 - set after {}
33 - }
29 + set after [next_diff_after_action $ui_workdir $path {} {^_?U}]
30
31 update_index \
32 [mc "Adding resolution for %s" [short_path $path]] \