summaryrefslogtreecommitdiff
path: root/git-gui/lib
diff options
context:
space:
mode:
Diffstat (limited to 'git-gui/lib')
-rw-r--r--git-gui/lib/blame.tcl70
-rw-r--r--git-gui/lib/branch_rename.tcl2
-rw-r--r--git-gui/lib/browser.tcl10
-rw-r--r--git-gui/lib/choose_repository.tcl25
-rw-r--r--git-gui/lib/choose_rev.tcl5
-rw-r--r--git-gui/lib/class.tcl1
-rw-r--r--git-gui/lib/commit.tcl26
-rw-r--r--git-gui/lib/diff.tcl151
-rw-r--r--git-gui/lib/index.tcl31
-rw-r--r--git-gui/lib/line.tcl81
-rw-r--r--git-gui/lib/merge.tcl2
-rw-r--r--git-gui/lib/mergetool.tcl101
-rw-r--r--git-gui/lib/option.tcl21
-rw-r--r--git-gui/lib/remote.tcl91
-rw-r--r--git-gui/lib/remote_branch_delete.tcl9
-rw-r--r--git-gui/lib/search.tcl127
-rw-r--r--git-gui/lib/shortcut.tcl4
-rw-r--r--git-gui/lib/sshkey.tcl2
-rw-r--r--git-gui/lib/status_bar.tcl1
-rw-r--r--git-gui/lib/themed.tcl99
-rw-r--r--git-gui/lib/tools.tcl10
-rw-r--r--git-gui/lib/transport.tcl35
-rw-r--r--git-gui/lib/win32.tcl4
23 files changed, 745 insertions, 163 deletions
diff --git a/git-gui/lib/blame.tcl b/git-gui/lib/blame.tcl
index 786b50b8c2..324f7744c4 100644
--- a/git-gui/lib/blame.tcl
+++ b/git-gui/lib/blame.tcl
@@ -22,6 +22,7 @@ field w_asim ; # text column: annotations (simple computation)
field w_file ; # text column: actual file data
field w_cviewer ; # pane showing commit message
field finder ; # find mini-dialog frame
+field gotoline ; # line goto mini-dialog frame
field status ; # status mega-widget instance
field old_height ; # last known height of $w.file_pane
@@ -218,7 +219,8 @@ constructor new {i_commit i_path i_jump} {
eval grid $w_columns $w.file_pane.out.sby -sticky nsew
grid conf \
$w.file_pane.out.sbx \
- -column [expr {[llength $w_columns] - 1}] \
+ -column 0 \
+ -columnspan [expr {[llength $w_columns] + 1}] \
-sticky we
grid columnconfigure \
$w.file_pane.out \
@@ -228,7 +230,14 @@ constructor new {i_commit i_path i_jump} {
set finder [::searchbar::new \
$w.file_pane.out.ff $w_file \
- -column [expr {[llength $w_columns] - 1}] \
+ -column 0 \
+ -columnspan [expr {[llength $w_columns] + 1}] \
+ ]
+
+ set gotoline [::linebar::new \
+ $w.file_pane.out.lf $w_file \
+ -column 0 \
+ -columnspan [expr {[llength $w_columns] + 1}] \
]
set w_cviewer $w.file_pane.cm.t
@@ -274,7 +283,11 @@ constructor new {i_commit i_path i_jump} {
$w.ctxm add command \
-label [mc "Find Text..."] \
-accelerator F7 \
- -command [list searchbar::show $finder]
+ -command [cb _show_finder]
+ $w.ctxm add command \
+ -label [mc "Goto Line..."] \
+ -accelerator "Ctrl-G" \
+ -command [cb _show_linebar]
menu $w.ctxm.enc
build_encoding_menu $w.ctxm.enc [cb _setencoding]
$w.ctxm add cascade \
@@ -341,10 +354,13 @@ constructor new {i_commit i_path i_jump} {
bind $w_cviewer <Tab> "[list focus $w_file];break"
bind $w_cviewer <Button-1> [list focus $w_cviewer]
bind $w_file <Visibility> [cb _focus_search $w_file]
- bind $top <F7> [list searchbar::show $finder]
+ bind $top <F7> [cb _show_finder]
+ bind $top <Key-slash> [cb _show_finder]
+ bind $top <Control-Key-s> [cb _show_finder]
bind $top <Escape> [list searchbar::hide $finder]
bind $top <F3> [list searchbar::find_next $finder]
bind $top <Shift-F3> [list searchbar::find_prev $finder]
+ bind $top <Control-Key-g> [cb _show_linebar]
catch { bind $top <Shift-Key-XF86_Switch_VT_3> [list searchbar::find_prev $finder] }
grid configure $w.header -sticky ew
@@ -449,11 +465,28 @@ method _load {jump} {
$status show [mc "Reading %s..." "$commit:[escape_path $path]"]
$w_path conf -text [escape_path $path]
+
+ set do_textconv 0
+ if {![is_config_false gui.textconv] && [git-version >= 1.7.2]} {
+ set filter [gitattr $path diff set]
+ set textconv [get_config [join [list diff $filter textconv] .]]
+ if {$filter ne {set} && $textconv ne {}} {
+ set do_textconv 1
+ }
+ }
if {$commit eq {}} {
- set fd [open $path r]
+ if {$do_textconv ne 0} {
+ set fd [open_cmd_pipe $textconv $path]
+ } else {
+ set fd [open $path r]
+ }
fconfigure $fd -eofchar {}
} else {
- set fd [git_read cat-file blob "$commit:$path"]
+ if {$do_textconv ne 0} {
+ set fd [git_read cat-file --textconv "$commit:$path"]
+ } else {
+ set fd [git_read cat-file blob "$commit:$path"]
+ }
}
fconfigure $fd \
-blocking 0 \
@@ -535,7 +568,11 @@ method _read_file {fd jump} {
foreach i $w_columns {$i conf -state disabled}
if {[eof $fd]} {
- close $fd
+ fconfigure $fd -blocking 1; # enable error reporting on close
+ if {[catch {close $fd} err]} {
+ tk_messageBox -icon error -title [mc Error] \
+ -message $err
+ }
# If we don't force Tk to update the widgets *right now*
# none of our jump commands will cause a change in the UI.
@@ -1025,7 +1062,7 @@ method _gitkcommit {} {
set radius [get_config gui.blamehistoryctx]
set cmdline [list --select-commit=$cmit]
- if {$radius > 0} {
+ if {$radius > 0} {
set author_time {}
set committer_time {}
@@ -1133,7 +1170,7 @@ method _read_diff_load_commit {fd cparent new_path tline} {
}
if {[eof $fd]} {
- close $fd;
+ close $fd
set current_fd {}
_load_new_commit $this \
@@ -1164,6 +1201,7 @@ method _open_tooltip {cur_w} {
_hide_tooltip $this
set tooltip_wm [toplevel $cur_w.tooltip -borderwidth 1]
+ catch {wm attributes $tooltip_wm -type tooltip}
wm overrideredirect $tooltip_wm 1
wm transient $tooltip_wm [winfo toplevel $cur_w]
set tooltip_t $tooltip_wm.label
@@ -1274,9 +1312,9 @@ method _position_tooltip {} {
set pos_y [expr {[winfo pointery .] + 10}]
set g "${req_w}x${req_h}"
- if {$pos_x >= 0} {append g +}
+ if {[tk windowingsystem] eq "win32" || $pos_x >= 0} {append g +}
append g $pos_x
- if {$pos_y >= 0} {append g +}
+ if {[tk windowingsystem] eq "win32" || $pos_y >= 0} {append g +}
append g $pos_y
wm geometry $tooltip_wm $g
@@ -1312,4 +1350,14 @@ method _resize {new_height} {
set old_height $new_height
}
+method _show_finder {} {
+ linebar::hide $gotoline
+ searchbar::show $finder
+}
+
+method _show_linebar {} {
+ searchbar::hide $finder
+ linebar::show $gotoline
+}
+
}
diff --git a/git-gui/lib/branch_rename.tcl b/git-gui/lib/branch_rename.tcl
index 63988773ba..6e510ec2e3 100644
--- a/git-gui/lib/branch_rename.tcl
+++ b/git-gui/lib/branch_rename.tcl
@@ -53,7 +53,7 @@ constructor dialog {} {
return 1
}
- grid $w.rename.oldname_l $w.rename.oldname_m -sticky w -padx {0 5}
+ grid $w.rename.oldname_l $w.rename.oldname_m -sticky we -padx {0 5}
grid $w.rename.newname_l $w.rename.newname_t -sticky we -padx {0 5}
grid columnconfigure $w.rename 1 -weight 1
pack $w.rename -anchor nw -fill x -pady 5 -padx 5
diff --git a/git-gui/lib/browser.tcl b/git-gui/lib/browser.tcl
index c2415729e0..0328338fda 100644
--- a/git-gui/lib/browser.tcl
+++ b/git-gui/lib/browser.tcl
@@ -26,8 +26,14 @@ constructor new {commit {path {}}} {
wm withdraw $top
wm title $top [append "[appname] ([reponame]): " [mc "File Browser"]]
+ if {$path ne {}} {
+ if {[string index $path end] ne {/}} {
+ append path /
+ }
+ }
+
set browser_commit $commit
- set browser_path $browser_commit:$path
+ set browser_path "$browser_commit:[escape_path $path]"
${NS}::label $w.path \
-textvariable @browser_path \
@@ -121,7 +127,7 @@ method _parent {} {
if {$browser_stack eq {}} {
regsub {:.*$} $browser_path {:} browser_path
} else {
- regsub {/[^/]+$} $browser_path {} browser_path
+ regsub {/[^/]+/$} $browser_path {/} browser_path
}
set browser_status [mc "Loading %s..." $browser_path]
_ls $this [lindex $parent 0] [lindex $parent 1]
diff --git a/git-gui/lib/choose_repository.tcl b/git-gui/lib/choose_repository.tcl
index 64f06748b6..657f7d5dc1 100644
--- a/git-gui/lib/choose_repository.tcl
+++ b/git-gui/lib/choose_repository.tcl
@@ -100,12 +100,17 @@ constructor pick {} {
$opts insert end [mc "Clone Existing Repository"] link_clone
$opts insert end "\n"
if {$m_repo ne {}} {
+ if {[tk windowingsystem] eq "win32"} {
+ set key L
+ } else {
+ set key C
+ }
$m_repo add command \
-command [cb _next clone] \
- -accelerator $M1T-C \
+ -accelerator $M1T-$key \
-label [mc "Clone..."]
- bind $top <$M1B-c> [cb _next clone]
- bind $top <$M1B-C> [cb _next clone]
+ bind $top <$M1B-[string tolower $key]> [cb _next clone]
+ bind $top <$M1B-[string toupper $key]> [cb _next clone]
}
$opts tag conf link_open -foreground blue -underline 1
@@ -209,14 +214,6 @@ constructor pick {} {
}
}
-proc _home {} {
- if {[catch {set h $::env(HOME)}]
- || ![file isdirectory $h]} {
- set h .
- }
- return $h
-}
-
method _center {} {
set nx [winfo reqwidth $top]
set ny [winfo reqheight $top]
@@ -415,7 +412,7 @@ method _new_local_path {} {
if {$local_path ne {}} {
set p [file dirname $local_path]
} else {
- set p [_home]
+ set p [pwd]
}
set p [tk_chooseDirectory \
@@ -536,7 +533,7 @@ method _open_origin {} {
if {$origin_url ne {} && [file isdirectory $origin_url]} {
set p $origin_url
} else {
- set p [_home]
+ set p [pwd]
}
set p [tk_chooseDirectory \
@@ -1037,7 +1034,7 @@ method _open_local_path {} {
if {$local_path ne {}} {
set p $local_path
} else {
- set p [_home]
+ set p [pwd]
}
set p [tk_chooseDirectory \
diff --git a/git-gui/lib/choose_rev.tcl b/git-gui/lib/choose_rev.tcl
index c12d5e1698..6dae7937d5 100644
--- a/git-gui/lib/choose_rev.tcl
+++ b/git-gui/lib/choose_rev.tcl
@@ -497,6 +497,7 @@ method _open_tooltip {} {
if {$tooltip_wm eq {}} {
set tooltip_wm [toplevel $w_list.tooltip -borderwidth 1]
+ catch {wm attributes $tooltip_wm -type tooltip}
wm overrideredirect $tooltip_wm 1
wm transient $tooltip_wm [winfo toplevel $w_list]
set tooltip_t $tooltip_wm.label
@@ -610,9 +611,9 @@ method _position_tooltip {} {
set pos_y [expr {[winfo pointery .] + 10}]
set g "${req_w}x${req_h}"
- if {$pos_x >= 0} {append g +}
+ if {[tk windowingsystem] eq "win32" || $pos_x >= 0} {append g +}
append g $pos_x
- if {$pos_y >= 0} {append g +}
+ if {[tk windowingsystem] eq "win32" || $pos_y >= 0} {append g +}
append g $pos_y
wm geometry $tooltip_wm $g
diff --git a/git-gui/lib/class.tcl b/git-gui/lib/class.tcl
index c27b71476a..f08506f383 100644
--- a/git-gui/lib/class.tcl
+++ b/git-gui/lib/class.tcl
@@ -138,6 +138,7 @@ proc make_dialog {t w args} {
upvar $t top $w pfx this this
global use_ttk
uplevel [linsert $args 0 make_toplevel $t $w]
+ catch {wm attributes $top -type dialog}
pave_toplevel $pfx
}
diff --git a/git-gui/lib/commit.tcl b/git-gui/lib/commit.tcl
index 7f459cd564..0d81432af5 100644
--- a/git-gui/lib/commit.tcl
+++ b/git-gui/lib/commit.tcl
@@ -161,11 +161,12 @@ The rescan will be automatically started now.
#
set files_ready 0
foreach path [array names file_states] {
- switch -glob -- [lindex $file_states($path) 0] {
+ set s $file_states($path)
+ switch -glob -- [lindex $s 0] {
_? {continue}
A? -
D? -
- T_ -
+ T? -
M? {set files_ready 1}
_U -
U? {
@@ -259,8 +260,25 @@ proc commit_prehook_wait {fd_ph curHEAD msg_p} {
}
proc commit_commitmsg {curHEAD msg_p} {
+ global is_detached repo_config
global pch_error
+ if {$is_detached
+ && ![file exists [gitdir rebase-merge head-name]]
+ && [is_config_true gui.warndetachedcommit]} {
+ set msg [mc "You are about to commit on a detached head.\
+This is a potentially dangerous thing to do because if you switch\
+to another branch you will loose your changes and it can be difficult\
+to retrieve them later from the reflog. You should probably cancel this\
+commit and create a new branch to continue.\n\
+\n\
+Do you really want to proceed with your Commit?"]
+ if {[ask_popup $msg] ne yes} {
+ unlock_index
+ return
+ }
+ }
+
# -- Run the commit-msg hook.
#
set fd_ph [githook_read commit-msg $msg_p]
@@ -452,7 +470,11 @@ A rescan will be automatically started now.
}
AM -
AD -
+ AT -
+ TM -
+ TD -
MM -
+ MT -
MD {
set file_states($path) [list \
_[string index $m 1] \
diff --git a/git-gui/lib/diff.tcl b/git-gui/lib/diff.tcl
index ec8c11eeb7..ec4405567a 100644
--- a/git-gui/lib/diff.tcl
+++ b/git-gui/lib/diff.tcl
@@ -55,7 +55,7 @@ proc handle_empty_diff {} {
set path $current_diff_path
set s $file_states($path)
- if {[lindex $s 0] ne {_M}} return
+ if {[lindex $s 0] ne {_M} || [has_textconv $path]} return
# Prevent infinite rescan loops
incr diff_empty_count
@@ -122,22 +122,22 @@ proc show_unmerged_diff {cont_info} {
if {$merge_stages(2) eq {}} {
set is_conflict_diff 1
lappend current_diff_queue \
- [list [mc "LOCAL: deleted\nREMOTE:\n"] d======= \
+ [list [mc "LOCAL: deleted\nREMOTE:\n"] d= \
[list ":1:$current_diff_path" ":3:$current_diff_path"]]
} elseif {$merge_stages(3) eq {}} {
set is_conflict_diff 1
lappend current_diff_queue \
- [list [mc "REMOTE: deleted\nLOCAL:\n"] d======= \
+ [list [mc "REMOTE: deleted\nLOCAL:\n"] d= \
[list ":1:$current_diff_path" ":2:$current_diff_path"]]
} elseif {[lindex $merge_stages(1) 0] eq {120000}
|| [lindex $merge_stages(2) 0] eq {120000}
|| [lindex $merge_stages(3) 0] eq {120000}} {
set is_conflict_diff 1
lappend current_diff_queue \
- [list [mc "LOCAL:\n"] d======= \
+ [list [mc "LOCAL:\n"] d= \
[list ":1:$current_diff_path" ":2:$current_diff_path"]]
lappend current_diff_queue \
- [list [mc "REMOTE:\n"] d======= \
+ [list [mc "REMOTE:\n"] d= \
[list ":1:$current_diff_path" ":3:$current_diff_path"]]
} else {
start_show_diff $cont_info
@@ -208,32 +208,32 @@ proc show_other_diff {path w m cont_info} {
$ui_diff insert end [append \
"* " \
[mc "Git Repository (subproject)"] \
- "\n"] d_@
+ "\n"] d_info
} elseif {![catch {set type [exec file $path]}]} {
set n [string length $path]
if {[string equal -length $n $path $type]} {
set type [string range $type $n end]
regsub {^:?\s*} $type {} type
}
- $ui_diff insert end "* $type\n" d_@
+ $ui_diff insert end "* $type\n" d_info
}
if {[string first "\0" $content] != -1} {
$ui_diff insert end \
[mc "* Binary file (not showing content)."] \
- d_@
+ d_info
} else {
if {$sz > $max_sz} {
$ui_diff insert end [mc \
"* Untracked file is %d bytes.
* Showing only first %d bytes.
-" $sz $max_sz] d_@
+" $sz $max_sz] d_info
}
$ui_diff insert end $content
if {$sz > $max_sz} {
$ui_diff insert end [mc "
* Untracked file clipped here by %s.
* To see the entire file, use an external editor.
-" [appname]] d_@
+" [appname]] d_info
}
}
$ui_diff conf -state disabled
@@ -253,6 +253,19 @@ proc show_other_diff {path w m cont_info} {
}
}
+proc get_conflict_marker_size {path} {
+ set size 7
+ catch {
+ set fd_rc [eval [list git_read check-attr "conflict-marker-size" -- $path]]
+ set ret [gets $fd_rc line]
+ close $fd_rc
+ if {$ret > 0} {
+ regexp {.*: conflict-marker-size: (\d+)$} $line line size
+ }
+ }
+ return $size
+}
+
proc start_show_diff {cont_info {add_opts {}}} {
global file_states file_lists
global is_3way_diff is_submodule_diff diff_active repo_config
@@ -268,6 +281,7 @@ proc start_show_diff {cont_info {add_opts {}}} {
set is_submodule_diff 0
set diff_active 1
set current_diff_header {}
+ set conflict_size [get_conflict_marker_size $path]
set cmd [list]
if {$w eq $ui_index} {
@@ -280,6 +294,9 @@ proc start_show_diff {cont_info {add_opts {}}} {
lappend cmd diff-files
}
}
+ if {![is_config_false gui.textconv] && [git-version >= 1.6.1]} {
+ lappend cmd --textconv
+ }
if {[string match {160000 *} [lindex $s 2]]
|| [string match {160000 *} [lindex $s 3]]} {
@@ -291,7 +308,8 @@ proc start_show_diff {cont_info {add_opts {}}} {
}
lappend cmd -p
- lappend cmd --no-color
+ lappend cmd --color
+ set cmd [concat $cmd $repo_config(gui.diffopts)]
if {$repo_config(gui.diffcontext) >= 1} {
lappend cmd "-U$repo_config(gui.diffcontext)"
}
@@ -326,10 +344,35 @@ proc start_show_diff {cont_info {add_opts {}}} {
-blocking 0 \
-encoding [get_path_encoding $path] \
-translation lf
- fileevent $fd readable [list read_diff $fd $cont_info]
+ fileevent $fd readable [list read_diff $fd $conflict_size $cont_info]
}
-proc read_diff {fd cont_info} {
+proc parse_color_line {line} {
+ set start 0
+ set result ""
+ set markup [list]
+ set regexp {\033\[((?:\d+;)*\d+)?m}
+ set need_reset 0
+ while {[regexp -indices -start $start $regexp $line match code]} {
+ foreach {begin end} $match break
+ append result [string range $line $start [expr {$begin - 1}]]
+ set pos [string length $result]
+ set col [eval [linsert $code 0 string range $line]]
+ set start [incr end]
+ if {$col eq "0" || $col eq ""} {
+ if {!$need_reset} continue
+ set need_reset 0
+ } else {
+ set need_reset 1
+ }
+ lappend markup $pos $col
+ }
+ append result [string range $line $start end]
+ if {[llength $markup] < 4} {set markup {}}
+ return [list $result $markup]
+}
+
+proc read_diff {fd conflict_size cont_info} {
global ui_diff diff_active is_submodule_diff
global is_3way_diff is_conflict_diff current_diff_header
global current_diff_queue
@@ -337,37 +380,53 @@ proc read_diff {fd cont_info} {
$ui_diff conf -state normal
while {[gets $fd line] >= 0} {
- # -- Cleanup uninteresting diff header lines.
+ foreach {line markup} [parse_color_line $line] break
+ set line [string map {\033 ^} $line]
+
+ set tags {}
+
+ # -- Check for start of diff header.
+ if { [string match {diff --git *} $line]
+ || [string match {diff --cc *} $line]
+ || [string match {diff --combined *} $line]} {
+ set ::current_diff_inheader 1
+ }
+
+ # -- Check for end of diff header (any hunk line will do this).
+ #
+ if {[regexp {^@@+ } $line]} {set ::current_diff_inheader 0}
+
+ # -- Automatically detect if this is a 3 way diff.
#
+ if {[string match {@@@ *} $line]} {set is_3way_diff 1}
+
if {$::current_diff_inheader} {
+
+ # -- These two lines stop a diff header and shouldn't be in there
+ if { [string match {Binary files * and * differ} $line]
+ || [regexp {^\* Unmerged path } $line]} {
+ set ::current_diff_inheader 0
+ } else {
+ append current_diff_header $line "\n"
+ }
+
+ # -- Cleanup uninteresting diff header lines.
+ #
if { [string match {diff --git *} $line]
|| [string match {diff --cc *} $line]
|| [string match {diff --combined *} $line]
|| [string match {--- *} $line]
- || [string match {+++ *} $line]} {
- append current_diff_header $line "\n"
+ || [string match {+++ *} $line]
+ || [string match {index *} $line]} {
continue
}
- }
- if {[string match {index *} $line]} continue
- if {$line eq {deleted file mode 120000}} {
- set line "deleted symlink"
- }
- set ::current_diff_inheader 0
- # -- Automatically detect if this is a 3 way diff.
- #
- if {[string match {@@@ *} $line]} {set is_3way_diff 1}
+ # -- Name it symlink, not 120000
+ # Note, that the original line is in $current_diff_header
+ regsub {^(deleted|new) file mode 120000} $line {\1 symlink} line
- if {[string match {mode *} $line]
- || [string match {new file *} $line]
- || [regexp {^(old|new) mode *} $line]
- || [string match {deleted file *} $line]
- || [string match {deleted symlink} $line]
- || [string match {Binary files * and * differ} $line]
- || $line eq {\ No newline at end of file}
- || [regexp {^\* Unmerged path } $line]} {
- set tags {}
+ } elseif { $line eq {\ No newline at end of file}} {
+ # -- Handle some special lines
} elseif {$is_3way_diff} {
set op [string range $line 0 1]
switch -- $op {
@@ -379,7 +438,9 @@ proc read_diff {fd cont_info} {
{- } {set tags d_-s}
{--} {set tags d_--}
{++} {
- if {[regexp {^\+\+([<>]{7} |={7})} $line _g op]} {
+ set regexp [string map [list %conflict_size $conflict_size]\
+ {^\+\+([<>=]){%conflict_size}(?: |$)}]
+ if {[regexp $regexp $line _g op]} {
set is_conflict_diff 1
set line [string replace $line 0 1 { }]
set tags d$op
@@ -395,10 +456,10 @@ proc read_diff {fd cont_info} {
} elseif {$is_submodule_diff} {
if {$line == ""} continue
if {[regexp {^Submodule } $line]} {
- set tags d_@
+ set tags d_info
} elseif {[regexp {^\* } $line]} {
set line [string replace $line 0 1 {Submodule }]
- set tags d_@
+ set tags d_info
} else {
set op [string range $line 0 2]
switch -- $op {
@@ -418,7 +479,9 @@ proc read_diff {fd cont_info} {
{@} {set tags d_@}
{-} {set tags d_-}
{+} {
- if {[regexp {^\+([<>]{7} |={7})} $line _g op]} {
+ set regexp [string map [list %conflict_size $conflict_size]\
+ {^\+([<>=]){%conflict_size}(?: |$)}]
+ if {[regexp $regexp $line _g op]} {
set is_conflict_diff 1
set tags d$op
} else {
@@ -431,11 +494,23 @@ proc read_diff {fd cont_info} {
}
}
}
+ set mark [$ui_diff index "end - 1 line linestart"]
$ui_diff insert end $line $tags
if {[string index $line end] eq "\r"} {
$ui_diff tag add d_cr {end - 2c}
}
$ui_diff insert end "\n" $tags
+
+ foreach {posbegin colbegin posend colend} $markup {
+ set prefix clr
+ foreach style [lsort -integer [split $colbegin ";"]] {
+ if {$style eq "7"} {append prefix i; continue}
+ if {$style != 4 && ($style < 30 || $style > 47)} {continue}
+ set a "$mark linestart + $posbegin chars"
+ set b "$mark linestart + $posend chars"
+ catch {$ui_diff tag add $prefix$style $a $b}
+ }
+ }
}
$ui_diff conf -state disabled
diff --git a/git-gui/lib/index.tcl b/git-gui/lib/index.tcl
index e9db0c4989..8efbbdde21 100644
--- a/git-gui/lib/index.tcl
+++ b/git-gui/lib/index.tcl
@@ -103,8 +103,11 @@ proc write_update_indexinfo {fd pathList totalCnt batch after} {
set s $file_states($path)
switch -glob -- [lindex $s 0] {
A? {set new _O}
- M? {set new _M}
+ MT -
+ TM -
T_ {set new _T}
+ M? {set new _M}
+ TD -
D_ {set new _D}
D? {set new _?}
?? {continue}
@@ -167,7 +170,10 @@ proc write_update_index {fd pathList totalCnt batch after} {
AD {set new __}
?D {set new D_}
_O -
+ AT -
AM {set new A_}
+ TM -
+ MT -
_T {set new T_}
_U -
U? {
@@ -261,7 +267,7 @@ proc unstage_helper {txt paths} {
switch -glob -- [lindex $file_states($path) 0] {
A? -
M? -
- T_ -
+ T? -
D? {
lappend pathList $path
if {$path eq $current_diff_path} {
@@ -350,12 +356,33 @@ proc do_add_all {} {
global file_states
set paths [list]
+ set untracked_paths [list]
foreach path [array names file_states] {
switch -glob -- [lindex $file_states($path) 0] {
U? {continue}
?M -
?T -
?D {lappend paths $path}
+ ?O {lappend untracked_paths $path}
+ }
+ }
+ if {[llength $untracked_paths]} {
+ set reply 0
+ switch -- [get_config gui.stageuntracked] {
+ no {
+ set reply 0
+ }
+ yes {
+ set reply 1
+ }
+ ask -
+ default {
+ set reply [ask_popup [mc "Stage %d untracked files?" \
+ [llength $untracked_paths]]]
+ }
+ }
+ if {$reply} {
+ set paths [concat $paths $untracked_paths]
}
}
add_helper {Adding all changed files} $paths
diff --git a/git-gui/lib/line.tcl b/git-gui/lib/line.tcl
new file mode 100644
index 0000000000..a026de954c
--- /dev/null
+++ b/git-gui/lib/line.tcl
@@ -0,0 +1,81 @@
+# goto line number
+# based on code from gitk, Copyright (C) Paul Mackerras
+
+class linebar {
+
+field w
+field ctext
+
+field linenum {}
+
+constructor new {i_w i_text args} {
+ global use_ttk NS
+ set w $i_w
+ set ctext $i_text
+
+ ${NS}::frame $w
+ ${NS}::label $w.l -text [mc "Goto Line:"]
+ tentry $w.ent \
+ -textvariable ${__this}::linenum \
+ -background lightgreen \
+ -validate key \
+ -validatecommand [cb _validate %P]
+ ${NS}::button $w.bn -text [mc Go] -command [cb _goto]
+
+ pack $w.l -side left
+ pack $w.bn -side right
+ pack $w.ent -side left -expand 1 -fill x
+
+ eval grid conf $w -sticky we $args
+ grid remove $w
+
+ trace add variable linenum write [cb _goto_cb]
+ bind $w.ent <Return> [cb _goto]
+ bind $w.ent <Escape> [cb hide]
+
+ bind $w <Destroy> [list delete_this $this]
+ return $this
+}
+
+method show {} {
+ if {![visible $this]} {
+ grid $w
+ }
+ focus -force $w.ent
+}
+
+method hide {} {
+ if {[visible $this]} {
+ $w.ent delete 0 end
+ focus $ctext
+ grid remove $w
+ }
+}
+
+method visible {} {
+ return [winfo ismapped $w]
+}
+
+method editor {} {
+ return $w.ent
+}
+
+method _validate {P} {
+ # only accept numbers as input
+ string is integer $P
+}
+
+method _goto_cb {name ix op} {
+ after idle [cb _goto 1]
+}
+
+method _goto {{nohide {0}}} {
+ if {$linenum ne {}} {
+ $ctext see $linenum.0
+ if {!$nohide} {
+ hide $this
+ }
+ }
+}
+
+}
diff --git a/git-gui/lib/merge.tcl b/git-gui/lib/merge.tcl
index 5cded2341c..460d32fa22 100644
--- a/git-gui/lib/merge.tcl
+++ b/git-gui/lib/merge.tcl
@@ -83,6 +83,7 @@ method _visualize {} {
method _start {} {
global HEAD current_branch remote_url
+ global _last_merged_branch
set name [_rev $this]
if {$name eq {}} {
@@ -109,6 +110,7 @@ method _start {} {
regsub ^refs/heads/ $branch {} branch
puts $fh "$cmit\t\tbranch '$branch' of $remote"
close $fh
+ set _last_merged_branch $branch
set cmd [list git]
lappend cmd merge
diff --git a/git-gui/lib/mergetool.tcl b/git-gui/lib/mergetool.tcl
index 3fe90e6970..3c8e73bceb 100644
--- a/git-gui/lib/mergetool.tcl
+++ b/git-gui/lib/mergetool.tcl
@@ -175,43 +175,56 @@ proc merge_resolve_tool2 {} {
# Build the command line
switch -- $tool {
- kdiff3 {
+ araxis {
if {$base_stage ne {}} {
- set cmdline [list "$merge_tool_path" --auto --L1 "$MERGED (Base)" \
- --L2 "$MERGED (Local)" --L3 "$MERGED (Remote)" -o "$MERGED" "$BASE" "$LOCAL" "$REMOTE"]
+ set cmdline [list "$merge_tool_path" -wait -merge -3 -a1 \
+ -title1:"'$MERGED (Base)'" -title2:"'$MERGED (Local)'" \
+ -title3:"'$MERGED (Remote)'" \
+ "$BASE" "$LOCAL" "$REMOTE" "$MERGED"]
} else {
- set cmdline [list "$merge_tool_path" --auto --L1 "$MERGED (Local)" \
- --L2 "$MERGED (Remote)" -o "$MERGED" "$LOCAL" "$REMOTE"]
+ set cmdline [list "$merge_tool_path" -wait -2 \
+ -title1:"'$MERGED (Local)'" -title2:"'$MERGED (Remote)'" \
+ "$LOCAL" "$REMOTE" "$MERGED"]
}
}
- tkdiff {
+ bc3 {
if {$base_stage ne {}} {
- set cmdline [list "$merge_tool_path" -a "$BASE" -o "$MERGED" "$LOCAL" "$REMOTE"]
+ set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" "$BASE" -mergeoutput="$MERGED"]
} else {
- set cmdline [list "$merge_tool_path" -o "$MERGED" "$LOCAL" "$REMOTE"]
+ set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" -mergeoutput="$MERGED"]
}
}
- meld {
- set cmdline [list "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"]
+ ecmerge {
+ if {$base_stage ne {}} {
+ set cmdline [list "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" --default --mode=merge3 --to="$MERGED"]
+ } else {
+ set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" --default --mode=merge2 --to="$MERGED"]
+ }
+ }
+ emerge {
+ if {$base_stage ne {}} {
+ set cmdline [list "$merge_tool_path" -f emerge-files-with-ancestor-command \
+ "$LOCAL" "$REMOTE" "$BASE" "$basename"]
+ } else {
+ set cmdline [list "$merge_tool_path" -f emerge-files-command \
+ "$LOCAL" "$REMOTE" "$basename"]
+ }
}
gvimdiff {
set cmdline [list "$merge_tool_path" -f "$LOCAL" "$MERGED" "$REMOTE"]
}
- xxdiff {
+ kdiff3 {
if {$base_stage ne {}} {
- set cmdline [list "$merge_tool_path" -X --show-merged-pane \
- -R {Accel.SaveAsMerged: "Ctrl-S"} \
- -R {Accel.Search: "Ctrl+F"} \
- -R {Accel.SearchForward: "Ctrl-G"} \
- --merged-file "$MERGED" "$LOCAL" "$BASE" "$REMOTE"]
+ set cmdline [list "$merge_tool_path" --auto --L1 "$MERGED (Base)" \
+ --L2 "$MERGED (Local)" --L3 "$MERGED (Remote)" -o "$MERGED" "$BASE" "$LOCAL" "$REMOTE"]
} else {
- set cmdline [list "$merge_tool_path" -X --show-merged-pane \
- -R {Accel.SaveAsMerged: "Ctrl-S"} \
- -R {Accel.Search: "Ctrl+F"} \
- -R {Accel.SearchForward: "Ctrl-G"} \
- --merged-file "$MERGED" "$LOCAL" "$REMOTE"]
+ set cmdline [list "$merge_tool_path" --auto --L1 "$MERGED (Local)" \
+ --L2 "$MERGED (Remote)" -o "$MERGED" "$LOCAL" "$REMOTE"]
}
}
+ meld {
+ set cmdline [list "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"]
+ }
opendiff {
if {$base_stage ne {}} {
set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" -ancestor "$BASE" -merge "$MERGED"]
@@ -219,22 +232,20 @@ proc merge_resolve_tool2 {} {
set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" -merge "$MERGED"]
}
}
- ecmerge {
- if {$base_stage ne {}} {
- set cmdline [list "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" --default --mode=merge3 --to="$MERGED"]
- } else {
- set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" --default --mode=merge2 --to="$MERGED"]
- }
+ p4merge {
+ set cmdline [list "$merge_tool_path" "$BASE" "$REMOTE" "$LOCAL" "$MERGED"]
}
- emerge {
+ tkdiff {
if {$base_stage ne {}} {
- set cmdline [list "$merge_tool_path" -f emerge-files-with-ancestor-command \
- "$LOCAL" "$REMOTE" "$BASE" "$basename"]
+ set cmdline [list "$merge_tool_path" -a "$BASE" -o "$MERGED" "$LOCAL" "$REMOTE"]
} else {
- set cmdline [list "$merge_tool_path" -f emerge-files-command \
- "$LOCAL" "$REMOTE" "$basename"]
+ set cmdline [list "$merge_tool_path" -o "$MERGED" "$LOCAL" "$REMOTE"]
}
}
+ vimdiff {
+ error_popup [mc "Not a GUI merge tool: '%s'" $tool]
+ return
+ }
winmerge {
if {$base_stage ne {}} {
# This tool does not support 3-way merges.
@@ -245,25 +256,21 @@ proc merge_resolve_tool2 {} {
-dl "Theirs File" -dr "Mine File" "$REMOTE" "$LOCAL" "$MERGED"]
}
}
- araxis {
+ xxdiff {
if {$base_stage ne {}} {
- set cmdline [list "$merge_tool_path" -wait -merge -3 -a1 \
- -title1:"'$MERGED (Base)'" -title2:"'$MERGED (Local)'" \
- -title3:"'$MERGED (Remote)'" \
- "$BASE" "$LOCAL" "$REMOTE" "$MERGED"]
+ set cmdline [list "$merge_tool_path" -X --show-merged-pane \
+ -R {Accel.SaveAsMerged: "Ctrl-S"} \
+ -R {Accel.Search: "Ctrl+F"} \
+ -R {Accel.SearchForward: "Ctrl-G"} \
+ --merged-file "$MERGED" "$LOCAL" "$BASE" "$REMOTE"]
} else {
- set cmdline [list "$merge_tool_path" -wait -2 \
- -title1:"'$MERGED (Local)'" -title2:"'$MERGED (Remote)'" \
- "$LOCAL" "$REMOTE" "$MERGED"]
+ set cmdline [list "$merge_tool_path" -X --show-merged-pane \
+ -R {Accel.SaveAsMerged: "Ctrl-S"} \
+ -R {Accel.Search: "Ctrl+F"} \
+ -R {Accel.SearchForward: "Ctrl-G"} \
+ --merged-file "$MERGED" "$LOCAL" "$REMOTE"]
}
}
- p4merge {
- set cmdline [list "$merge_tool_path" "$BASE" "$REMOTE" "$LOCAL" "$MERGED"]
- }
- vimdiff {
- error_popup [mc "Not a GUI merge tool: '%s'" $tool]
- return
- }
default {
error_popup [mc "Unsupported merge tool '%s'" $tool]
return
diff --git a/git-gui/lib/option.tcl b/git-gui/lib/option.tcl
index d4c5e45c8a..0cf1da1d7e 100644
--- a/git-gui/lib/option.tcl
+++ b/git-gui/lib/option.tcl
@@ -148,13 +148,17 @@ proc do_options {} {
{b gui.trustmtime {mc "Trust File Modification Timestamps"}}
{b gui.pruneduringfetch {mc "Prune Tracking Branches During Fetch"}}
{b gui.matchtrackingbranch {mc "Match Tracking Branches"}}
+ {b gui.textconv {mc "Use Textconv For Diffs and Blames"}}
{b gui.fastcopyblame {mc "Blame Copy Only On Changed Files"}}
{i-20..200 gui.copyblamethreshold {mc "Minimum Letters To Blame Copy On"}}
{i-0..300 gui.blamehistoryctx {mc "Blame History Context Radius (days)"}}
{i-1..99 gui.diffcontext {mc "Number of Diff Context Lines"}}
+ {t gui.diffopts {mc "Additional Diff Parameters"}}
{i-0..99 gui.commitmsgwidth {mc "Commit Message Text Width"}}
{t gui.newbranchtemplate {mc "New Branch Name Template"}}
{c gui.encoding {mc "Default File Contents Encoding"}}
+ {b gui.warndetachedcommit {mc "Warn before committing to a detached head"}}
+ {s gui.stageuntracked {mc "Staging of untracked files"} {list "yes" "no" "ask"}}
} {
set type [lindex $option 0]
set name [lindex $option 1]
@@ -207,6 +211,23 @@ proc do_options {} {
}
pack $w.$f.$optid -side top -anchor w -fill x
}
+ s {
+ set opts [eval [lindex $option 3]]
+ ${NS}::frame $w.$f.$optid
+ ${NS}::label $w.$f.$optid.l -text "$text:"
+ if {$use_ttk} {
+ ttk::combobox $w.$f.$optid.v \
+ -textvariable ${f}_config_new($name) \
+ -values $opts -state readonly
+ } else {
+ eval tk_optionMenu $w.$f.$optid.v \
+ ${f}_config_new($name) \
+ $opts
+ }
+ pack $w.$f.$optid.l -side left -anchor w -fill x
+ pack $w.$f.$optid.v -side right -anchor e -padx 5
+ pack $w.$f.$optid -side top -anchor w -fill x
+ }
}
}
}
diff --git a/git-gui/lib/remote.tcl b/git-gui/lib/remote.tcl
index b92b429cf7..5e4e7f4c83 100644
--- a/git-gui/lib/remote.tcl
+++ b/git-gui/lib/remote.tcl
@@ -157,22 +157,7 @@ proc add_fetch_entry {r} {
}
if {$enable} {
- if {![winfo exists $fetch_m]} {
- menu $remove_m
- $remote_m insert 0 cascade \
- -label [mc "Remove Remote"] \
- -menu $remove_m
-
- menu $prune_m
- $remote_m insert 0 cascade \
- -label [mc "Prune from"] \
- -menu $prune_m
-
- menu $fetch_m
- $remote_m insert 0 cascade \
- -label [mc "Fetch from"] \
- -menu $fetch_m
- }
+ make_sure_remote_submenues_exist $remote_m
$fetch_m add command \
-label $r \
@@ -222,6 +207,70 @@ proc add_push_entry {r} {
}
}
+proc make_sure_remote_submenues_exist {remote_m} {
+ set fetch_m $remote_m.fetch
+ set prune_m $remote_m.prune
+ set remove_m $remote_m.remove
+
+ if {![winfo exists $fetch_m]} {
+ menu $remove_m
+ $remote_m insert 0 cascade \
+ -label [mc "Remove Remote"] \
+ -menu $remove_m
+
+ menu $prune_m
+ $remote_m insert 0 cascade \
+ -label [mc "Prune from"] \
+ -menu $prune_m
+
+ menu $fetch_m
+ $remote_m insert 0 cascade \
+ -label [mc "Fetch from"] \
+ -menu $fetch_m
+ }
+}
+
+proc update_all_remotes_menu_entry {} {
+ global all_remotes
+
+ if {[git-version < 1.6.6]} { return }
+
+ set have_remote 0
+ foreach r $all_remotes {
+ incr have_remote
+ }
+
+ set remote_m .mbar.remote
+ set fetch_m $remote_m.fetch
+ set prune_m $remote_m.prune
+ if {$have_remote > 1} {
+ make_sure_remote_submenues_exist $remote_m
+ if {[$fetch_m entrycget end -label] ne "All"} {
+
+ $fetch_m insert end separator
+ $fetch_m insert end command \
+ -label "All" \
+ -command fetch_from_all
+
+ $prune_m insert end separator
+ $prune_m insert end command \
+ -label "All" \
+ -command prune_from_all
+ }
+ } else {
+ if {[winfo exists $fetch_m]} {
+ if {[$fetch_m entrycget end -label] eq "All"} {
+
+ delete_from_menu $fetch_m end
+ delete_from_menu $fetch_m end
+
+ delete_from_menu $prune_m end
+ delete_from_menu $prune_m end
+ }
+ }
+ }
+}
+
proc populate_remotes_menu {} {
global all_remotes
@@ -229,6 +278,8 @@ proc populate_remotes_menu {} {
add_fetch_entry $r
add_push_entry $r
}
+
+ update_all_remotes_menu_entry
}
proc add_single_remote {name location} {
@@ -244,6 +295,8 @@ proc add_single_remote {name location} {
add_fetch_entry $name
add_push_entry $name
+
+ update_all_remotes_menu_entry
}
proc delete_from_menu {menu name} {
@@ -264,8 +317,8 @@ proc remove_remote {name} {
unset repo_config(remote.$name.push)
}
- set i [lsearch -exact all_remotes $name]
- lreplace all_remotes $i $i
+ set i [lsearch -exact $all_remotes $name]
+ set all_remotes [lreplace $all_remotes $i $i]
set remote_m .mbar.remote
delete_from_menu $remote_m.fetch $name
@@ -273,4 +326,6 @@ proc remove_remote {name} {
delete_from_menu $remote_m.remove $name
# Not all remotes are in the push menu
catch { delete_from_menu $remote_m.push $name }
+
+ update_all_remotes_menu_entry
}
diff --git a/git-gui/lib/remote_branch_delete.tcl b/git-gui/lib/remote_branch_delete.tcl
index f872a3d89d..fcc06d03a1 100644
--- a/git-gui/lib/remote_branch_delete.tcl
+++ b/git-gui/lib/remote_branch_delete.tcl
@@ -251,7 +251,7 @@ method _write_url {args} { set urltype url }
method _write_check_head {args} { set checktype head }
method _write_head_list {args} {
- global current_branch
+ global current_branch _last_merged_branch
$head_m delete 0 end
foreach abr $head_list {
@@ -267,6 +267,13 @@ method _write_head_list {args} {
set check_head $current_branch
}
}
+ set lmb [lsearch -exact -sorted $head_list $_last_merged_branch]
+ if {$lmb >= 0} {
+ $w.heads.l conf -state normal
+ $w.heads.l select set $lmb
+ $w.heads.l yview $lmb
+ $w.heads.l conf -state disabled
+ }
}
method _write_urltype {args} {
diff --git a/git-gui/lib/search.tcl b/git-gui/lib/search.tcl
index 7fdbf87bcd..ef1e55521d 100644
--- a/git-gui/lib/search.tcl
+++ b/git-gui/lib/search.tcl
@@ -7,9 +7,16 @@ field w
field ctext
field searchstring {}
-field casesensitive 1
+field regexpsearch
+field default_regexpsearch
+field casesensitive
+field default_casesensitive
+field smartcase
field searchdirn -forwards
+field history
+field history_index
+
field smarktop
field smarkbot
@@ -18,15 +25,37 @@ constructor new {i_w i_text args} {
set w $i_w
set ctext $i_text
+ set default_regexpsearch [is_config_true gui.search.regexp]
+ switch -- [get_config gui.search.case] {
+ no {
+ set default_casesensitive 0
+ set smartcase 0
+ }
+ smart {
+ set default_casesensitive 0
+ set smartcase 1
+ }
+ yes -
+ default {
+ set default_casesensitive 1
+ set smartcase 0
+ }
+ }
+
+ set history [list]
+
${NS}::frame $w
${NS}::label $w.l -text [mc Find:]
- entry $w.ent -textvariable ${__this}::searchstring -background lightgreen
+ tentry $w.ent -textvariable ${__this}::searchstring -background lightgreen
${NS}::button $w.bn -text [mc Next] -command [cb find_next]
${NS}::button $w.bp -text [mc Prev] -command [cb find_prev]
- ${NS}::checkbutton $w.cs -text [mc Case-Sensitive] \
+ ${NS}::checkbutton $w.re -text [mc RegExp] \
+ -variable ${__this}::regexpsearch -command [cb _incrsearch]
+ ${NS}::checkbutton $w.cs -text [mc Case] \
-variable ${__this}::casesensitive -command [cb _incrsearch]
pack $w.l -side left
pack $w.cs -side right
+ pack $w.re -side right
pack $w.bp -side right
pack $w.bn -side right
pack $w.ent -side left -expand 1 -fill x
@@ -35,6 +64,10 @@ constructor new {i_w i_text args} {
grid remove $w
trace add variable searchstring write [cb _incrsearch_cb]
+ bind $w.ent <Return> [cb find_next]
+ bind $w.ent <Shift-Return> [cb find_prev]
+ bind $w.ent <Key-Up> [cb _prev_search]
+ bind $w.ent <Key-Down> [cb _next_search]
bind $w <Destroy> [list delete_this $this]
return $this
@@ -43,6 +76,10 @@ constructor new {i_w i_text args} {
method show {} {
if {![visible $this]} {
grid $w
+ $w.ent delete 0 end
+ set regexpsearch $default_regexpsearch
+ set casesensitive $default_casesensitive
+ set history_index [llength $history]
}
focus -force $w.ent
}
@@ -51,6 +88,7 @@ method hide {} {
if {[visible $this]} {
focus $ctext
grid remove $w
+ _save_search $this
}
}
@@ -96,6 +134,9 @@ method _do_search {start {mlenvar {}} {dir {}} {endbound {}}} {
upvar $mlenvar mlen
lappend cmd -count mlen
}
+ if {$regexpsearch} {
+ lappend cmd -regexp
+ }
if {!$casesensitive} {
lappend cmd -nocase
}
@@ -103,14 +144,16 @@ method _do_search {start {mlenvar {}} {dir {}} {endbound {}}} {
set dir $searchdirn
}
lappend cmd $dir -- $searchstring
- if {$endbound ne {}} {
- set here [eval $cmd [list $start] [list $endbound]]
- } else {
- set here [eval $cmd [list $start]]
- if {$here eq {}} {
- set here [eval $cmd [_get_wrap_anchor $this $dir]]
+ if {[catch {
+ if {$endbound ne {}} {
+ set here [eval $cmd [list $start] [list $endbound]]
+ } else {
+ set here [eval $cmd [list $start]]
+ if {$here eq {}} {
+ set here [eval $cmd [_get_wrap_anchor $this $dir]]
+ }
}
- }
+ } err]} { set here {} }
return $here
}
@@ -124,19 +167,76 @@ method _incrsearch {} {
$ctext mark set anchor [_get_new_anchor $this]
}
if {$searchstring ne {}} {
+ if {$smartcase && [regexp {[[:upper:]]} $searchstring]} {
+ set casesensitive 1
+ }
set here [_do_search $this anchor mlen]
if {$here ne {}} {
$ctext see $here
$ctext tag remove sel 1.0 end
$ctext tag add sel $here "$here + $mlen c"
- $w.ent configure -background lightgreen
+ #$w.ent configure -background lightgreen
+ $w.ent state !pressed
_set_marks $this 1
} else {
- $w.ent configure -background lightpink
+ #$w.ent configure -background lightpink
+ $w.ent state pressed
}
+ } elseif {$smartcase} {
+ # clearing the field resets the smart case detection
+ set casesensitive 0
+ }
+}
+
+method _save_search {} {
+ if {$searchstring eq {}} {
+ return
+ }
+ if {[llength $history] > 0} {
+ foreach {s_regexp s_case s_expr} [lindex $history end] break
+ } else {
+ set s_regexp $regexpsearch
+ set s_case $casesensitive
+ set s_expr ""
+ }
+ if {$searchstring eq $s_expr} {
+ # update modes
+ set history [lreplace $history end end \
+ [list $regexpsearch $casesensitive $searchstring]]
+ } else {
+ lappend history [list $regexpsearch $casesensitive $searchstring]
+ }
+ set history_index [llength $history]
+}
+
+method _prev_search {} {
+ if {$history_index > 0} {
+ incr history_index -1
+ foreach {s_regexp s_case s_expr} [lindex $history $history_index] break
+ $w.ent delete 0 end
+ $w.ent insert 0 $s_expr
+ set regexpsearch $s_regexp
+ set casesensitive $s_case
}
}
+method _next_search {} {
+ if {$history_index < [llength $history]} {
+ incr history_index
+ }
+ if {$history_index < [llength $history]} {
+ foreach {s_regexp s_case s_expr} [lindex $history $history_index] break
+ } else {
+ set s_regexp $default_regexpsearch
+ set s_case $default_casesensitive
+ set s_expr ""
+ }
+ $w.ent delete 0 end
+ $w.ent insert 0 $s_expr
+ set regexpsearch $s_regexp
+ set casesensitive $s_case
+}
+
method find_prev {} {
find_next $this -backwards
}
@@ -147,6 +247,7 @@ method find_next {{dir -forwards}} {
set searchdirn $dir
$ctext mark unset anchor
if {$searchstring ne {}} {
+ _save_search $this
set start [_get_new_anchor $this]
if {$dir eq "-forwards"} {
set start "$start + 1c"
@@ -196,4 +297,4 @@ method scrolled {} {
}
}
-} \ No newline at end of file
+}
diff --git a/git-gui/lib/shortcut.tcl b/git-gui/lib/shortcut.tcl
index 79c1888e11..78878ef89d 100644
--- a/git-gui/lib/shortcut.tcl
+++ b/git-gui/lib/shortcut.tcl
@@ -16,7 +16,7 @@ proc do_windows_shortcut {} {
[info nameofexecutable] \
[file normalize $::argv0] \
] \
- [file normalize [$_gitworktree]]
+ [file normalize $_gitworktree]
} err]} {
error_popup [strcat [mc "Cannot write shortcut:"] "\n\n$err"]
}
@@ -57,7 +57,7 @@ proc do_cygwin_shortcut {} {
$sh -c \
"CHERE_INVOKING=1 source /etc/profile;[sq $me] &" \
] \
- [file normalize [$_gitworktree]]
+ [file normalize $_gitworktree]
} err]} {
error_popup [strcat [mc "Cannot write shortcut:"] "\n\n$err"]
}
diff --git a/git-gui/lib/sshkey.tcl b/git-gui/lib/sshkey.tcl
index 5f75bc96b3..aa6457bbb5 100644
--- a/git-gui/lib/sshkey.tcl
+++ b/git-gui/lib/sshkey.tcl
@@ -117,7 +117,7 @@ proc read_sshkey_output {fd w} {
} else {
set finfo [find_ssh_key]
if {$finfo eq {}} {
- set sshkey_title [mc "Generation succeded, but no keys found."]
+ set sshkey_title [mc "Generation succeeded, but no keys found."]
$w.contents insert end $sshkey_output
} else {
set sshkey_title [mc "Your key is in: %s" [lindex $finfo 0]]
diff --git a/git-gui/lib/status_bar.tcl b/git-gui/lib/status_bar.tcl
index 5fe3aad382..95cb44991f 100644
--- a/git-gui/lib/status_bar.tcl
+++ b/git-gui/lib/status_bar.tcl
@@ -39,6 +39,7 @@ method _oneline_pack {} {
}
constructor two_line {path} {
+ global NS
set w $path
set w_l $w.l
set w_c $w.c
diff --git a/git-gui/lib/themed.tcl b/git-gui/lib/themed.tcl
index 1da458673b..8b88d3678b 100644
--- a/git-gui/lib/themed.tcl
+++ b/git-gui/lib/themed.tcl
@@ -23,10 +23,59 @@ proc InitTheme {} {
ttk::style configure Gold.TFrame -background gold -relief flat
# listboxes should have a theme border so embed in ttk::frame
ttk::style layout SListbox.TFrame {
- SListbox.Frame.Entry.field -sticky news -border true -children {
- SListbox.Frame.padding -sticky news
- }
- }
+ SListbox.Frame.Entry.field -sticky news -border true -children {
+ SListbox.Frame.padding -sticky news
+ }
+ }
+
+ # Handle either current Tk or older versions of 8.5
+ if {[catch {set theme [ttk::style theme use]}]} {
+ set theme $::ttk::currentTheme
+ }
+
+ if {[lsearch -exact {default alt classic clam} $theme] != -1} {
+ # Simple override of standard ttk::entry to change the field
+ # packground according to a state flag. We should use 'user1'
+ # but not all versions of 8.5 support that so make use of 'pressed'
+ # which is not normally in use for entry widgets.
+ ttk::style layout Edged.Entry [ttk::style layout TEntry]
+ ttk::style map Edged.Entry {*}[ttk::style map TEntry]
+ ttk::style configure Edged.Entry {*}[ttk::style configure TEntry] \
+ -fieldbackground lightgreen
+ ttk::style map Edged.Entry -fieldbackground {
+ {pressed !disabled} lightpink
+ }
+ } else {
+ # For fancier themes, in particular the Windows ones, the field
+ # element may not support changing the background color. So instead
+ # override the fill using the default fill element. If we overrode
+ # the vista theme field element we would loose the themed border
+ # of the widget.
+ catch {
+ ttk::style element create color.fill from default
+ }
+
+ ttk::style layout Edged.Entry {
+ Edged.Entry.field -sticky nswe -border 0 -children {
+ Edged.Entry.border -sticky nswe -border 1 -children {
+ Edged.Entry.padding -sticky nswe -children {
+ Edged.Entry.color.fill -sticky nswe -children {
+ Edged.Entry.textarea -sticky nswe
+ }
+ }
+ }
+ }
+ }
+
+ ttk::style configure Edged.Entry {*}[ttk::style configure TEntry] \
+ -background lightgreen -padding 0 -borderwidth 0
+ ttk::style map Edged.Entry {*}[ttk::style map TEntry] \
+ -background {{pressed !disabled} lightpink}
+ }
+
+ if {[lsearch [bind . <<ThemeChanged>>] InitTheme] == -1} {
+ bind . <<ThemeChanged>> +[namespace code [list InitTheme]]
+ }
}
proc gold_frame {w args} {
@@ -74,6 +123,7 @@ proc paddedlabel {w args} {
# place a themed frame over the surface.
proc Dialog {w args} {
eval [linsert $args 0 toplevel $w -class Dialog]
+ catch {wm attributes $w -type dialog}
pave_toplevel $w
return $w
}
@@ -143,6 +193,47 @@ proc tspinbox {w args} {
}
}
+proc tentry {w args} {
+ global use_ttk
+ if {$use_ttk} {
+ InitTheme
+ ttk::entry $w -style Edged.Entry
+ } else {
+ entry $w
+ }
+
+ rename $w _$w
+ interp alias {} $w {} tentry_widgetproc $w
+ eval [linsert $args 0 tentry_widgetproc $w configure]
+ return $w
+}
+proc tentry_widgetproc {w cmd args} {
+ global use_ttk
+ switch -- $cmd {
+ state {
+ if {$use_ttk} {
+ return [uplevel 1 [list _$w $cmd] $args]
+ } else {
+ if {[lsearch -exact $args pressed] != -1} {
+ _$w configure -background lightpink
+ } else {
+ _$w configure -background lightgreen
+ }
+ }
+ }
+ configure {
+ if {$use_ttk} {
+ if {[set n [lsearch -exact $args -background]] != -1} {
+ set args [lreplace $args $n [incr n]]
+ if {[llength $args] == 0} {return}
+ }
+ }
+ return [uplevel 1 [list _$w $cmd] $args]
+ }
+ default { return [uplevel 1 [list _$w $cmd] $args] }
+ }
+}
+
# Tk 8.6 provides a standard font selection dialog. This uses the native
# dialogs on Windows and MacOSX or a standard Tk dialog on X11.
proc tchoosefont {w title familyvar sizevar} {
diff --git a/git-gui/lib/tools.tcl b/git-gui/lib/tools.tcl
index 95e6e5553e..6ec94113db 100644
--- a/git-gui/lib/tools.tcl
+++ b/git-gui/lib/tools.tcl
@@ -87,8 +87,14 @@ proc tools_exec {fullname} {
return
}
} elseif {[is_config_true "guitool.$fullname.confirm"]} {
- if {[ask_popup [mc "Are you sure you want to run %s?" $fullname]] ne {yes}} {
- return
+ if {[is_config_true "guitool.$fullname.needsfile"]} {
+ if {[ask_popup [mc "Are you sure you want to run %1\$s on file \"%2\$s\"?" $fullname $current_diff_path]] ne {yes}} {
+ return
+ }
+ } else {
+ if {[ask_popup [mc "Are you sure you want to run %s?" $fullname]] ne {yes}} {
+ return
+ }
}
}
diff --git a/git-gui/lib/transport.tcl b/git-gui/lib/transport.tcl
index 60e3a642c5..e5d211edea 100644
--- a/git-gui/lib/transport.tcl
+++ b/git-gui/lib/transport.tcl
@@ -20,6 +20,35 @@ proc prune_from {remote} {
console::exec $w [list git remote prune $remote]
}
+proc fetch_from_all {} {
+ set w [console::new \
+ [mc "fetch all remotes"] \
+ [mc "Fetching new changes from all remotes"]]
+
+ set cmd [list git fetch --all]
+ if {[is_config_true gui.pruneduringfetch]} {
+ lappend cmd --prune
+ }
+
+ console::exec $w $cmd
+}
+
+proc prune_from_all {} {
+ global all_remotes
+
+ set w [console::new \
+ [mc "remote prune all remotes"] \
+ [mc "Pruning tracking branches deleted from all remotes"]]
+
+ set cmd [list git remote prune]
+
+ foreach r $all_remotes {
+ lappend cmd $r
+ }
+
+ console::exec $w $cmd
+}
+
proc push_to {remote} {
set w [console::new \
[mc "push %s" $remote] \
@@ -95,6 +124,7 @@ proc do_push_anywhere {} {
set w .push_setup
toplevel $w
+ catch {wm attributes $w -type dialog}
wm withdraw $w
wm geometry $w "+[winfo rootx .]+[winfo rooty .]"
pave_toplevel $w
@@ -123,6 +153,7 @@ proc do_push_anywhere {} {
$w.source.l insert end $h
if {$h eq $current_branch} {
$w.source.l select set end
+ $w.source.l yview end
}
}
pack $w.source.l -side left -fill both -expand 1
@@ -135,7 +166,9 @@ proc do_push_anywhere {} {
-value remote \
-variable push_urltype
if {$use_ttk} {
- ttk::combobox $w.dest.remote_m -textvariable push_remote \
+ ttk::combobox $w.dest.remote_m -state readonly \
+ -exportselection false \
+ -textvariable push_remote \
-values $all_remotes
} else {
eval tk_optionMenu $w.dest.remote_m push_remote $all_remotes
diff --git a/git-gui/lib/win32.tcl b/git-gui/lib/win32.tcl
index d7f93d045d..db91ab84a5 100644
--- a/git-gui/lib/win32.tcl
+++ b/git-gui/lib/win32.tcl
@@ -18,9 +18,9 @@ proc win32_create_lnk {lnk_path lnk_exec lnk_dir} {
eval [list exec wscript.exe \
/E:jscript \
/nologo \
- [file join $oguilib win32_shortcut.js] \
+ [file nativename [file join $oguilib win32_shortcut.js]] \
$lnk_path \
- [file join $oguilib git-gui.ico] \
+ [file nativename [file join $oguilib git-gui.ico]] \
$lnk_dir \
$lnk_exec] $lnk_args
}