X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=git-gui.sh;h=7c25bb98089ec4c0a57993020a30d2d1afad8dae;hb=729ffa50f75a025935623bfc58d0932c65f7de2f;hp=daab7e44bbbb35621bfff12fd7a667e997311528;hpb=b2bd31006f02debe1ddf4fa8b73c52281516a871;p=git.git diff --git a/git-gui.sh b/git-gui.sh index daab7e44b..7c25bb980 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -6,11 +6,12 @@ echo 'git-gui version @@GITGUI_VERSION@@'; \ exit; \ fi; \ - exec wish "$0" -- "$@" + argv0=$0; \ + exec wish "$argv0" -- "$@" set appvers {@@GITGUI_VERSION@@} -set copyright { -Copyright © 2006, 2007 Shawn Pearce, et. al. +set copyright [encoding convertfrom utf-8 { +Copyright © 2006, 2007 Shawn Pearce, et. al. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,7 +25,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA} +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA}] ###################################################################### ## @@ -37,12 +38,12 @@ if {[catch {package require Tcl 8.4} err] tk_messageBox \ -icon error \ -type ok \ - -title "git-gui: fatal error" \ + -title [mc "git-gui: fatal error"] \ -message $err exit 1 } -rename send {} ; # What an evil concept... +catch {rename send {}} ; # What an evil concept... ###################################################################### ## @@ -86,7 +87,27 @@ if {![catch {set _verbose $env(GITGUI_VERBOSE)}]} { ## http://www.gnu.org/software/gettext/manual/html_node/Tcl.html package require msgcat -namespace import ::msgcat::mc + +proc _mc_trim {fmt} { + set cmk [string first @@ $fmt] + if {$cmk > 0} { + return [string range $fmt 0 [expr {$cmk - 1}]] + } + return $fmt +} + +proc mc {en_fmt args} { + set fmt [_mc_trim [::msgcat::mc $en_fmt]] + if {[catch {set msg [eval [list format $fmt] $args]} err]} { + set msg [eval [list format [_mc_trim $en_fmt]] $args] + } + return $msg +} + +proc strcat {args} { + return [join $args {}] +} + ::msgcat::mcload $oguimsg unset oguimsg @@ -94,7 +115,7 @@ unset oguimsg ## ## read only globals -set _appname [lindex [file split $argv0] end] +set _appname {Git Gui} set _gitdir {} set _gitexec {} set _reponame {} @@ -191,6 +212,7 @@ proc disable_option {option} { proc is_many_config {name} { switch -glob -- $name { + gui.recentrepo - remote.*.fetch - remote.*.push {return 1} @@ -219,51 +241,6 @@ proc get_config {name} { } } -proc load_config {include_global} { - global repo_config global_config default_config - - array unset global_config - if {$include_global} { - catch { - set fd_rc [git_read config --global --list] - while {[gets $fd_rc line] >= 0} { - if {[regexp {^([^=]+)=(.*)$} $line line name value]} { - if {[is_many_config $name]} { - lappend global_config($name) $value - } else { - set global_config($name) $value - } - } - } - close $fd_rc - } - } - - array unset repo_config - catch { - set fd_rc [git_read config --list] - while {[gets $fd_rc line] >= 0} { - if {[regexp {^([^=]+)=(.*)$} $line line name value]} { - if {[is_many_config $name]} { - lappend repo_config($name) $value - } else { - set repo_config($name) $value - } - } - } - close $fd_rc - } - - foreach name [array names default_config] { - if {[catch {set v $global_config($name)}]} { - set global_config($name) $default_config($name) - } - if {[catch {set v $repo_config($name)}]} { - set repo_config($name) $default_config($name) - } - } -} - ###################################################################### ## ## handy utils @@ -321,7 +298,7 @@ proc _which {what} { global env _search_exe _search_path if {$_search_path eq {}} { - if {[is_Cygwin]} { + if {[is_Cygwin] && [regexp {^(/|\.:)} $env(PATH)]} { set _search_path [split [exec cygpath \ --windows \ --path \ @@ -329,6 +306,9 @@ proc _which {what} { $env(PATH)] {;}] set _search_exe .exe } elseif {[is_Windows]} { + set gitguidir [file dirname [info script]] + regsub -all ";" $gitguidir "\\;" gitguidir + set env(PATH) "$gitguidir;$env(PATH)" set _search_path [split $env(PATH) {;}] set _search_exe .exe } else { @@ -458,6 +438,34 @@ proc git_write {args} { return [open [concat $opt $cmdp $args] w] } +proc githook_read {hook_name args} { + set pchook [gitdir hooks $hook_name] + lappend args 2>@1 + + # On Cygwin [file executable] might lie so we need to ask + # the shell if the hook is executable. Yes that's annoying. + # + if {[is_Cygwin]} { + upvar #0 _sh interp + if {![info exists interp]} { + set interp [_which sh] + } + if {$interp eq {}} { + error "hook execution requires sh (not in PATH)" + } + + set scr {if test -x "$1";then exec "$@";fi} + set sh_c [list | $interp -c $scr $interp $pchook] + return [_open_stdout_stderr [concat $sh_c $args]] + } + + if {[file executable $pchook]} { + return [_open_stdout_stderr [concat [list | $pchook] $args]] + } + + return {} +} + proc sq {value} { regsub -all ' $value "'\\''" value return "'$value'" @@ -497,6 +505,122 @@ proc tk_optionMenu {w varName args} { return $m } +proc rmsel_tag {text} { + $text tag conf sel \ + -background [$text cget -background] \ + -foreground [$text cget -foreground] \ + -borderwidth 0 + $text tag conf in_sel -background lightgray + bind $text break + return $text +} + +set root_exists 0 +bind . { + bind . {} + set root_exists 1 +} + +if {[is_Windows]} { + wm iconbitmap . -default $oguilib/git-gui.ico +} + +###################################################################### +## +## config defaults + +set cursor_ptr arrow +font create font_diff -family Courier -size 10 +font create font_ui +catch { + label .dummy + eval font configure font_ui [font actual [.dummy cget -font]] + destroy .dummy +} + +font create font_uiitalic +font create font_uibold +font create font_diffbold +font create font_diffitalic + +foreach class {Button Checkbutton Entry Label + Labelframe Listbox Menu Message + Radiobutton Spinbox Text} { + option add *$class.font font_ui +} +unset class + +if {[is_Windows] || [is_MacOSX]} { + option add *Menu.tearOff 0 +} + +if {[is_MacOSX]} { + set M1B M1 + set M1T Cmd +} else { + set M1B Control + set M1T Ctrl +} + +proc bind_button3 {w cmd} { + bind $w $cmd + if {[is_MacOSX]} { + # Mac OS X sends Button-2 on right click through three-button mouse, + # or through trackpad right-clicking (two-finger touch + click). + bind $w $cmd + bind $w $cmd + } +} + +proc apply_config {} { + global repo_config font_descs + + foreach option $font_descs { + set name [lindex $option 0] + set font [lindex $option 1] + if {[catch { + set need_weight 1 + foreach {cn cv} $repo_config(gui.$name) { + if {$cn eq {-weight}} { + set need_weight 0 + } + font configure $font $cn $cv + } + if {$need_weight} { + font configure $font -weight normal + } + } err]} { + error_popup [strcat [mc "Invalid font specified in %s:" "gui.$name"] "\n\n$err"] + } + foreach {cn cv} [font configure $font] { + font configure ${font}bold $cn $cv + font configure ${font}italic $cn $cv + } + font configure ${font}bold -weight bold + font configure ${font}italic -slant italic + } +} + +set default_config(merge.diffstat) true +set default_config(merge.summary) false +set default_config(merge.verbosity) 2 +set default_config(user.name) {} +set default_config(user.email) {} + +set default_config(gui.matchtrackingbranch) false +set default_config(gui.pruneduringfetch) false +set default_config(gui.trustmtime) false +set default_config(gui.diffcontext) 5 +set default_config(gui.commitmsgwidth) 75 +set default_config(gui.newbranchtemplate) {} +set default_config(gui.spellingdictionary) {} +set default_config(gui.fontui) [font configure font_ui] +set default_config(gui.fontdiff) [font configure font_diff] +set font_descs { + {fontui font_ui {mc "Main Font"}} + {fontdiff font_diff {mc "Diff/Console Font"}} +} + ###################################################################### ## ## find git @@ -504,7 +628,11 @@ proc tk_optionMenu {w varName args} { set _git [_which git] if {$_git eq {}} { catch {wm withdraw .} - error_popup [mc "Cannot find git in PATH."] + tk_messageBox \ + -icon error \ + -type ok \ + -title [mc "git-gui: fatal error"] \ + -message [mc "Cannot find git in PATH."] exit 1 } @@ -517,7 +645,7 @@ if {[catch {set _git_version [git --version]} err]} { tk_messageBox \ -icon error \ -type ok \ - -title "git-gui: fatal error" \ + -title [mc "git-gui: fatal error"] \ -message "Cannot determine Git version: $err @@ -530,16 +658,17 @@ if {![regsub {^git version } $_git_version {} _git_version]} { tk_messageBox \ -icon error \ -type ok \ - -title "git-gui: fatal error" \ - -message [append [mc "Cannot parse Git version string:"] "\n\n$_git_version"] + -title [mc "git-gui: fatal error"] \ + -message [strcat [mc "Cannot parse Git version string:"] "\n\n$_git_version"] exit 1 } set _real_git_version $_git_version -regsub -- {-dirty$} $_git_version {} _git_version +regsub -- {[\-\.]dirty$} $_git_version {} _git_version regsub {\.[0-9]+\.g[0-9a-f]+$} $_git_version {} _git_version regsub {\.rc[0-9]+$} $_git_version {} _git_version regsub {\.GIT$} $_git_version {} _git_version +regsub {\.[a-zA-Z]+\.[0-9]+$} $_git_version {} _git_version if {![regexp {^[1-9]+(\.[0-9]+)+$} $_git_version]} { catch {wm withdraw .} @@ -612,7 +741,7 @@ if {[git-version < 1.5]} { tk_messageBox \ -icon error \ -type ok \ - -title "git-gui: fatal error" \ + -title [mc "git-gui: fatal error"] \ -message "[appname] requires Git 1.5.0 or later. You are using [git-version]: @@ -631,7 +760,7 @@ if {[catch {set fd [open $idx r]} err]} { tk_messageBox \ -icon error \ -type ok \ - -title "git-gui: fatal error" \ + -title [mc "git-gui: fatal error"] \ -message $err exit 1 } @@ -660,11 +789,76 @@ if {$idx ne {}} { } unset -nocomplain idx fd +###################################################################### +## +## config file parsing + +git-version proc _parse_config {arr_name args} { + >= 1.5.3 { + upvar $arr_name arr + array unset arr + set buf {} + catch { + set fd_rc [eval \ + [list git_read config] \ + $args \ + [list --null --list]] + fconfigure $fd_rc -translation binary + set buf [read $fd_rc] + close $fd_rc + } + foreach line [split $buf "\0"] { + if {[regexp {^([^\n]+)\n(.*)$} $line line name value]} { + if {[is_many_config $name]} { + lappend arr($name) $value + } else { + set arr($name) $value + } + } + } + } + default { + upvar $arr_name arr + array unset arr + catch { + set fd_rc [eval [list git_read config --list] $args] + while {[gets $fd_rc line] >= 0} { + if {[regexp {^([^=]+)=(.*)$} $line line name value]} { + if {[is_many_config $name]} { + lappend arr($name) $value + } else { + set arr($name) $value + } + } + } + close $fd_rc + } + } +} + +proc load_config {include_global} { + global repo_config global_config default_config + + if {$include_global} { + _parse_config global_config --global + } + _parse_config repo_config + + foreach name [array names default_config] { + if {[catch {set v $global_config($name)}]} { + set global_config($name) $default_config($name) + } + if {[catch {set v $repo_config($name)}]} { + set repo_config($name) $default_config($name) + } + } +} + ###################################################################### ## ## feature option selection -if {[regexp {^git-(.+)$} [appname] _junk subcommand]} { +if {[regexp {^git-(.+)$} [file tail $argv0] _junk subcommand]} { unset _junk } else { set subcommand gui @@ -712,35 +906,35 @@ if {[catch { set _gitdir [git rev-parse --git-dir] set _prefix [git rev-parse --show-prefix] } err]} { - catch {wm withdraw .} - error_popup [append [mc "Cannot find the git directory:"] "\n\n$err"] - exit 1 + load_config 1 + apply_config + choose_repository::pick } if {![file isdirectory $_gitdir] && [is_Cygwin]} { - catch {set _gitdir [exec cygpath --unix $_gitdir]} + catch {set _gitdir [exec cygpath --windows $_gitdir]} } if {![file isdirectory $_gitdir]} { catch {wm withdraw .} - error_popup [append [mc "Git directory not found:"] "\n\n$_gitdir"] + error_popup [strcat [mc "Git directory not found:"] "\n\n$_gitdir"] exit 1 } if {$_prefix ne {}} { regsub -all {[^/]+/} $_prefix ../ cdup if {[catch {cd $cdup} err]} { catch {wm withdraw .} - error_popup "Cannot move to top of working directory:\n\n$err" + error_popup [strcat [mc "Cannot move to top of working directory:"] "\n\n$err"] exit 1 } unset cdup } elseif {![is_enabled bare]} { if {[lindex [file split $_gitdir] end] ne {.git}} { catch {wm withdraw .} - error_popup [append [mc "Cannot use funny .git directory:"] "\n\n$_gitdir"] + error_popup [strcat [mc "Cannot use funny .git directory:"] "\n\n$_gitdir"] exit 1 } if {[catch {cd [file dirname $_gitdir]} err]} { catch {wm withdraw .} - error_popup [append [mc "No working directory"] " [file dirname $_gitdir]:\n\n$err"] + error_popup [strcat [mc "No working directory"] " [file dirname $_gitdir]:\n\n$err"] exit 1 } } @@ -900,6 +1094,35 @@ proc rescan {after {honor_trustmtime 1}} { } } +if {[is_Cygwin]} { + set is_git_info_link {} + set is_git_info_exclude {} + proc have_info_exclude {} { + global is_git_info_link is_git_info_exclude + + if {$is_git_info_link eq {}} { + set is_git_info_link [file isfile [gitdir info.lnk]] + } + + if {$is_git_info_link} { + if {$is_git_info_exclude eq {}} { + if {[catch {exec test -f [gitdir info exclude]}]} { + set is_git_info_exclude 0 + } else { + set is_git_info_exclude 1 + } + } + return $is_git_info_exclude + } else { + return [file readable [gitdir info exclude]] + } + } +} else { + proc have_info_exclude {} { + return [file readable [gitdir info exclude]] + } +} + proc rescan_stage2 {fd after} { global rescan_active buf_rdi buf_rdf buf_rlo @@ -910,9 +1133,8 @@ proc rescan_stage2 {fd after} { } set ls_others [list --exclude-per-directory=.gitignore] - set info_exclude [gitdir info exclude] - if {[file readable $info_exclude]} { - lappend ls_others "--exclude-from=$info_exclude" + if {[have_info_exclude]} { + lappend ls_others "--exclude-from=[gitdir info exclude]" } set user_exclude [get_config core.excludesfile] if {$user_exclude ne {} && [file readable $user_exclude]} { @@ -1029,7 +1251,11 @@ proc read_ls_others {fd after} { set pck [split $buf_rlo "\0"] set buf_rlo [lindex $pck end] foreach p [lrange $pck 0 end-1] { - merge_state [encoding convertfrom $p] ?O + set p [encoding convertfrom $p] + if {[string index $p end] eq {/}} { + set p [string range $p 0 end-1] + } + merge_state $p ?O } rescan_done $fd buf_rlo $after } @@ -1086,11 +1312,17 @@ proc mapdesc {state path} { } proc ui_status {msg} { - $::main_status show $msg + global main_status + if {[info exists main_status]} { + $main_status show $msg + } } proc ui_ready {{test {}}} { - $::main_status show [mc "Ready."] $test + global main_status + if {[info exists main_status]} { + $main_status show [mc "Ready."] $test + } } proc escape_path {path} { @@ -1388,16 +1620,6 @@ unset i ## ## util -proc bind_button3 {w cmd} { - bind $w $cmd - if {[is_MacOSX]} { - # Mac OS X sends Button-2 on right click through three-button mouse, - # or through trackpad right-clicking (two-finger touch + click). - bind $w $cmd - bind $w $cmd - } -} - proc scrollbar2many {list mode args} { foreach w $list {eval $w $mode $args} } @@ -1430,7 +1652,27 @@ proc do_gitk {revs} { if {! [file exists $exe]} { error_popup [mc "Unable to start gitk:\n\n%s does not exist" $exe] } else { + global env + + if {[info exists env(GIT_DIR)]} { + set old_GIT_DIR $env(GIT_DIR) + } else { + set old_GIT_DIR {} + } + + set pwd [pwd] + cd [file dirname [gitdir]] + set env(GIT_DIR) [file tail [gitdir]] + eval exec $cmd $revs & + + if {$old_GIT_DIR eq {}} { + unset env(GIT_DIR) + } else { + set env(GIT_DIR) $old_GIT_DIR + } + cd $pwd + ui_status $::starting_gitk_msg after 10000 { ui_ready $starting_gitk_msg @@ -1443,6 +1685,7 @@ set is_quitting 0 proc do_quit {} { global ui_comm is_quitting repo_config commit_type global GITGUI_BCK_exists GITGUI_BCK_i + global ui_comm_spell if {$is_quitting} return set is_quitting 1 @@ -1470,6 +1713,12 @@ proc do_quit {} { } } + # -- Cancel our spellchecker if its running. + # + if {[info exists ui_comm_spell]} { + $ui_comm_spell stop + } + # -- Remove our editor backup, its not needed. # after cancel $GITGUI_BCK_i @@ -1481,8 +1730,8 @@ proc do_quit {} { # set cfg_geometry [list] lappend cfg_geometry [wm geometry .] - lappend cfg_geometry [lindex [.vpane sash coord 0] 1] - lappend cfg_geometry [lindex [.vpane.files sash coord 0] 0] + lappend cfg_geometry [lindex [.vpane sash coord 0] 0] + lappend cfg_geometry [lindex [.vpane.files sash coord 0] 1] if {[catch {set rc_geometry $repo_config(gui.geometry)}]} { set rc_geometry {} } @@ -1597,89 +1846,28 @@ proc add_range_to_selection {w x y} { $w tag add in_sel $begin.0 [expr {$end + 1}].0 } -###################################################################### -## -## config defaults - -set cursor_ptr arrow -font create font_diff -family Courier -size 10 -font create font_ui -catch { - label .dummy - eval font configure font_ui [font actual [.dummy cget -font]] - destroy .dummy -} - -font create font_uiitalic -font create font_uibold -font create font_diffbold -font create font_diffitalic - -foreach class {Button Checkbutton Entry Label - Labelframe Listbox Menu Message - Radiobutton Spinbox Text} { - option add *$class.font font_ui -} -unset class - -if {[is_Windows] || [is_MacOSX]} { - option add *Menu.tearOff 0 -} - -if {[is_MacOSX]} { - set M1B M1 - set M1T Cmd -} else { - set M1B Control - set M1T Ctrl -} - -proc apply_config {} { - global repo_config font_descs - - foreach option $font_descs { - set name [lindex $option 0] - set font [lindex $option 1] - if {[catch { - foreach {cn cv} $repo_config(gui.$name) { - font configure $font $cn $cv - } - } err]} { - error_popup [append [mc "Invalid font specified in %s:" "gui.$name"] "\n\n$err"] - } - foreach {cn cv} [font configure $font] { - font configure ${font}bold $cn $cv - font configure ${font}italic $cn $cv - } - font configure ${font}bold -weight bold - font configure ${font}italic -slant italic +proc show_more_context {} { + global repo_config + if {$repo_config(gui.diffcontext) < 99} { + incr repo_config(gui.diffcontext) + reshow_diff } } -set default_config(merge.diffstat) true -set default_config(merge.summary) false -set default_config(merge.verbosity) 2 -set default_config(user.name) {} -set default_config(user.email) {} - -set default_config(gui.matchtrackingbranch) false -set default_config(gui.pruneduringfetch) false -set default_config(gui.trustmtime) false -set default_config(gui.diffcontext) 5 -set default_config(gui.newbranchtemplate) {} -set default_config(gui.fontui) [font configure font_ui] -set default_config(gui.fontdiff) [font configure font_diff] -set font_descs { - {fontui font_ui {mc "Main Font"}} - {fontdiff font_diff {mc "Diff/Console Font"}} +proc show_less_context {} { + global repo_config + if {$repo_config(gui.diffcontext) >= 1} { + incr repo_config(gui.diffcontext) -1 + reshow_diff + } } -load_config 0 -apply_config ###################################################################### ## ## ui construction +load_config 0 +apply_config set ui_comm {} # -- Menu Bar @@ -1691,12 +1879,11 @@ if {[is_enabled branch]} { .mbar add cascade -label [mc Branch] -menu .mbar.branch } if {[is_enabled multicommit] || [is_enabled singlecommit]} { - .mbar add cascade -label [mc Commit] -menu .mbar.commit + .mbar add cascade -label [mc Commit@@noun] -menu .mbar.commit } if {[is_enabled transport]} { .mbar add cascade -label [mc Merge] -menu .mbar.merge - .mbar add cascade -label [mc Fetch] -menu .mbar.fetch - .mbar add cascade -label [mc Push] -menu .mbar.push + .mbar add cascade -label [mc Remote] -menu .mbar.remote } . configure -menu .mbar @@ -1852,7 +2039,8 @@ if {[is_enabled multicommit] || [is_enabled singlecommit]} { [list .mbar.commit entryconf [.mbar.commit index last] -state] .mbar.commit add command -label [mc "Stage To Commit"] \ - -command do_add_selection + -command do_add_selection \ + -accelerator $M1T-T lappend disable_on_lock \ [list .mbar.commit entryconf [.mbar.commit index last] -state] @@ -1874,11 +2062,21 @@ if {[is_enabled multicommit] || [is_enabled singlecommit]} { .mbar.commit add separator + .mbar.commit add command -label [mc "Show Less Context"] \ + -command show_less_context \ + -accelerator $M1T-\- + + .mbar.commit add command -label [mc "Show More Context"] \ + -command show_more_context \ + -accelerator $M1T-= + + .mbar.commit add separator + .mbar.commit add command -label [mc "Sign Off"] \ -command do_signoff \ -accelerator $M1T-S - .mbar.commit add command -label [mc Commit] \ + .mbar.commit add command -label [mc Commit@@verb] \ -command do_commit \ -accelerator $M1T-Return lappend disable_on_lock \ @@ -1903,26 +2101,31 @@ if {[is_enabled branch]} { # -- Transport Menu # if {[is_enabled transport]} { - menu .mbar.fetch + menu .mbar.remote - menu .mbar.push - .mbar.push add command -label [mc "Push..."] \ + .mbar.remote add command \ + -label [mc "Push..."] \ -command do_push_anywhere \ -accelerator $M1T-P - .mbar.push add command -label [mc "Delete..."] \ + .mbar.remote add command \ + -label [mc "Delete..."] \ -command remote_branch_delete::dialog } if {[is_MacOSX]} { # -- Apple Menu (Mac OS X only) # - .mbar add cascade -label [mc Apple] -menu .mbar.apple + .mbar add cascade -label Apple -menu .mbar.apple menu .mbar.apple .mbar.apple add command -label [mc "About %s" [appname]] \ -command do_about - .mbar.apple add command -label [mc "Options..."] \ - -command do_options + .mbar.apple add separator + .mbar.apple add command \ + -label [mc "Preferences..."] \ + -command do_options \ + -accelerator $M1T-, + bind . <$M1B-,> do_options } else { # -- Edit Menu # @@ -1979,12 +2182,6 @@ if {$browser ne {}} { } unset browser doc_path doc_url -set root_exists 0 -bind . { - bind . {} - set root_exists 1 -} - # -- Standard bindings # wm protocol . WM_DELETE_WINDOW do_quit @@ -2064,7 +2261,7 @@ blame { } blame { if {$head eq {} && ![file exists $path]} { - puts stderr "fatal: cannot stat path $path: No such file or directory" + puts stderr [mc "fatal: cannot stat path %s: No such file or directory" $path] exit 1 } blame::new $head $path @@ -2076,7 +2273,8 @@ citool - gui { if {[llength $argv] != 0} { puts -nonewline stderr "usage: $argv0" - if {$subcommand ne {gui} && [appname] ne "git-$subcommand"} { + if {$subcommand ne {gui} + && [file tail $argv0] ne "git-$subcommand"} { puts -nonewline stderr " $subcommand" } puts stderr {} @@ -2109,17 +2307,18 @@ pack .branch -side top -fill x # -- Main Window Layout # -panedwindow .vpane -orient vertical -panedwindow .vpane.files -orient horizontal +panedwindow .vpane -orient horizontal +panedwindow .vpane.files -orient vertical .vpane add .vpane.files -sticky nsew -height 100 -width 200 pack .vpane -anchor n -side top -fill both -expand 1 # -- Index File List # frame .vpane.files.index -height 100 -width 200 -label .vpane.files.index.title -text [mc "Staged Changes (Will Be Committed)"] \ - -background lightgreen -text $ui_index -background white -borderwidth 0 \ +label .vpane.files.index.title -text [mc "Staged Changes (Will Commit)"] \ + -background lightgreen -foreground black +text $ui_index -background white -foreground black \ + -borderwidth 0 \ -width 20 -height 10 \ -wrap none \ -cursor $cursor_ptr \ @@ -2132,14 +2331,14 @@ pack .vpane.files.index.title -side top -fill x pack .vpane.files.index.sx -side bottom -fill x pack .vpane.files.index.sy -side right -fill y pack $ui_index -side left -fill both -expand 1 -.vpane.files add .vpane.files.index -sticky nsew # -- Working Directory File List # frame .vpane.files.workdir -height 100 -width 200 -label .vpane.files.workdir.title -text [mc "Unstaged Changes (Will Not Be Committed)"] \ - -background lightsalmon -text $ui_workdir -background white -borderwidth 0 \ +label .vpane.files.workdir.title -text [mc "Unstaged Changes"] \ + -background lightsalmon -foreground black +text $ui_workdir -background white -foreground black \ + -borderwidth 0 \ -width 20 -height 10 \ -wrap none \ -cursor $cursor_ptr \ @@ -2152,11 +2351,13 @@ pack .vpane.files.workdir.title -side top -fill x pack .vpane.files.workdir.sx -side bottom -fill x pack .vpane.files.workdir.sy -side right -fill y pack $ui_workdir -side left -fill both -expand 1 + .vpane.files add .vpane.files.workdir -sticky nsew +.vpane.files add .vpane.files.index -sticky nsew foreach i [list $ui_index $ui_workdir] { - $i tag conf in_diff -background lightgray - $i tag conf in_sel -background lightgray + rmsel_tag $i + $i tag conf in_diff -background [$i tag cget in_sel -background] } unset i @@ -2165,8 +2366,8 @@ unset i frame .vpane.lower -height 300 -width 400 frame .vpane.lower.commarea frame .vpane.lower.diff -relief sunken -borderwidth 1 -pack .vpane.lower.commarea -side top -fill x -pack .vpane.lower.diff -side bottom -fill both -expand 1 +pack .vpane.lower.diff -fill both -expand 1 +pack .vpane.lower.commarea -side bottom -fill x .vpane add .vpane.lower -sticky nsew # -- Commit Area Buttons @@ -2194,7 +2395,7 @@ button .vpane.lower.commarea.buttons.signoff -text [mc "Sign Off"] \ -command do_signoff pack .vpane.lower.commarea.buttons.signoff -side top -fill x -button .vpane.lower.commarea.buttons.commit -text [mc Commit] \ +button .vpane.lower.commarea.buttons.commit -text [mc Commit@@verb] \ -command do_commit pack .vpane.lower.commarea.buttons.commit -side top -fill x lappend disable_on_lock \ @@ -2244,12 +2445,13 @@ pack $ui_coml -side left -fill x pack .vpane.lower.commarea.buffer.header.amend -side right pack .vpane.lower.commarea.buffer.header.new -side right -text $ui_comm -background white -borderwidth 1 \ +text $ui_comm -background white -foreground black \ + -borderwidth 1 \ -undo true \ -maxundo 20 \ -autoseparators true \ -relief sunken \ - -width 75 -height 9 -wrap none \ + -width $repo_config(gui.commitmsgwidth) -height 9 -wrap none \ -font font_diff \ -yscrollcommand {.vpane.lower.commarea.buffer.sby set} scrollbar .vpane.lower.commarea.buffer.sby \ @@ -2290,7 +2492,7 @@ $ctxm add separator $ctxm add command \ -label [mc "Sign Off"] \ -command do_signoff -bind_button3 $ui_comm "tk_popup $ctxm %X %Y" +set ui_comm_ctxm $ctxm # -- Diff Header # @@ -2321,15 +2523,18 @@ trace add variable current_diff_path write trace_current_diff_path frame .vpane.lower.diff.header -background gold label .vpane.lower.diff.header.status \ -background gold \ + -foreground black \ -width $max_status_desc \ -anchor w \ -justify left label .vpane.lower.diff.header.file \ -background gold \ + -foreground black \ -anchor w \ -justify left label .vpane.lower.diff.header.path \ -background gold \ + -foreground black \ -anchor w \ -justify left pack .vpane.lower.diff.header.status -side left @@ -2353,7 +2558,8 @@ bind_button3 .vpane.lower.diff.header.path "tk_popup $ctxm %X %Y" # frame .vpane.lower.diff.body set ui_diff .vpane.lower.diff.body.t -text $ui_diff -background white -borderwidth 0 \ +text $ui_diff -background white -foreground black \ + -borderwidth 0 \ -width 80 -height 15 -wrap none \ -font font_diff \ -xscrollcommand {.vpane.lower.diff.body.sbx set} \ @@ -2405,6 +2611,21 @@ $ui_diff tag raise sel # set ctxm .vpane.lower.diff.body.ctxm menu $ctxm -tearoff 0 +$ctxm add command \ + -label [mc "Apply/Reverse Hunk"] \ + -command {apply_hunk $cursorX $cursorY} +set ui_diff_applyhunk [$ctxm index last] +lappend diff_actions [list $ctxm entryconf $ui_diff_applyhunk -state] +$ctxm add separator +$ctxm add command \ + -label [mc "Show Less Context"] \ + -command show_less_context +lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] +$ctxm add command \ + -label [mc "Show More Context"] \ + -command show_more_context +lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] +$ctxm add separator $ctxm add command \ -label [mc Refresh] \ -command reshow_diff @@ -2426,12 +2647,6 @@ $ctxm add command \ } lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] $ctxm add separator -$ctxm add command \ - -label [mc "Apply/Reverse Hunk"] \ - -command {apply_hunk $cursorX $cursorY} -set ui_diff_applyhunk [$ctxm index last] -lappend diff_actions [list $ctxm entryconf $ui_diff_applyhunk -state] -$ctxm add separator $ctxm add command \ -label [mc "Decrease Font Size"] \ -command {incr_font_size font_diff -1} @@ -2441,21 +2656,6 @@ $ctxm add command \ -command {incr_font_size font_diff 1} lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] $ctxm add separator -$ctxm add command \ - -label [mc "Show Less Context"] \ - -command {if {$repo_config(gui.diffcontext) >= 1} { - incr repo_config(gui.diffcontext) -1 - reshow_diff - }} -lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] -$ctxm add command \ - -label [mc "Show More Context"] \ - -command {if {$repo_config(gui.diffcontext) < 99} { - incr repo_config(gui.diffcontext) - reshow_diff - }} -lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] -$ctxm add separator $ctxm add command -label [mc "Options..."] \ -command do_options proc popup_diff_menu {ctxm x y X Y} { @@ -2492,17 +2692,19 @@ catch { set gm $repo_config(gui.geometry) wm geometry . [lindex $gm 0] .vpane sash place 0 \ - [lindex [.vpane sash coord 0] 0] \ - [lindex $gm 1] + [lindex $gm 1] \ + [lindex [.vpane sash coord 0] 1] .vpane.files sash place 0 \ - [lindex $gm 2] \ - [lindex [.vpane.files sash coord 0] 1] + [lindex [.vpane.files sash coord 0] 0] \ + [lindex $gm 2] unset gm } # -- Key Bindings # bind $ui_comm <$M1B-Key-Return> {do_commit;break} +bind $ui_comm <$M1B-Key-t> {do_add_selection;break} +bind $ui_comm <$M1B-Key-T> {do_add_selection;break} bind $ui_comm <$M1B-Key-i> {do_add_all;break} bind $ui_comm <$M1B-Key-I> {do_add_all;break} bind $ui_comm <$M1B-Key-x> {tk_textCut %W;break} @@ -2513,6 +2715,11 @@ bind $ui_comm <$M1B-Key-v> {tk_textPaste %W; %W see insert; break} bind $ui_comm <$M1B-Key-V> {tk_textPaste %W; %W see insert; break} bind $ui_comm <$M1B-Key-a> {%W tag add sel 0.0 end;break} bind $ui_comm <$M1B-Key-A> {%W tag add sel 0.0 end;break} +bind $ui_comm <$M1B-Key-minus> {show_less_context;break} +bind $ui_comm <$M1B-Key-KP_Subtract> {show_less_context;break} +bind $ui_comm <$M1B-Key-equal> {show_more_context;break} +bind $ui_comm <$M1B-Key-plus> {show_more_context;break} +bind $ui_comm <$M1B-Key-KP_Add> {show_more_context;break} bind $ui_diff <$M1B-Key-x> {tk_textCopy %W;break} bind $ui_diff <$M1B-Key-X> {tk_textCopy %W;break} @@ -2552,8 +2759,15 @@ bind . <$M1B-Key-r> do_rescan bind . <$M1B-Key-R> do_rescan bind . <$M1B-Key-s> do_signoff bind . <$M1B-Key-S> do_signoff +bind . <$M1B-Key-t> do_add_selection +bind . <$M1B-Key-T> do_add_selection bind . <$M1B-Key-i> do_add_all bind . <$M1B-Key-I> do_add_all +bind . <$M1B-Key-minus> {show_less_context;break} +bind . <$M1B-Key-KP_Subtract> {show_less_context;break} +bind . <$M1B-Key-equal> {show_more_context;break} +bind . <$M1B-Key-plus> {show_more_context;break} +bind . <$M1B-Key-KP_Add> {show_more_context;break} bind . <$M1B-Key-Return> do_commit foreach i [list $ui_index $ui_workdir] { bind $i "toggle_or_diff $i %x %y; break" @@ -2575,13 +2789,13 @@ focus -force $ui_comm if {[is_Cygwin]} { set ignored_env 0 set suggest_user {} - set msg "Possible environment issues exist. + set msg [mc "Possible environment issues exist. The following environment variables are probably going to be ignored by any Git subprocess run -by [appname]: +by %s: -" +" [appname]] foreach name [array names env] { switch -regexp -- $name { {^GIT_INDEX_FILE$} - @@ -2605,18 +2819,18 @@ by [appname]: } } if {$ignored_env > 0} { - append msg " + append msg [mc " This is due to a known issue with the -Tcl binary distributed by Cygwin." +Tcl binary distributed by Cygwin."] if {$suggest_user ne {}} { - append msg " + append msg [mc " -A good replacement for $suggest_user +A good replacement for %s is placing values for the user.name and user.email settings into your personal ~/.gitconfig file. -" +" $suggest_user] } warn_popup $msg } @@ -2628,8 +2842,14 @@ user.email settings into your personal if {[is_enabled transport]} { load_all_remotes - populate_fetch_menu + set n [.mbar.remote index end] populate_push_menu + populate_fetch_menu + set n [expr {[.mbar.remote index end] - $n}] + if {$n > 0} { + .mbar.remote insert $n separator + } + unset n } if {[winfo exists $ui_comm]} { @@ -2683,6 +2903,30 @@ if {[winfo exists $ui_comm]} { } backup_commit_buffer + + # -- If the user has aspell available we can drive it + # in pipe mode to spellcheck the commit message. + # + set spell_cmd [list |] + set spell_dict [get_config gui.spellingdictionary] + lappend spell_cmd aspell + if {$spell_dict ne {}} { + lappend spell_cmd --master=$spell_dict + } + lappend spell_cmd --mode=none + lappend spell_cmd --encoding=utf-8 + lappend spell_cmd pipe + if {$spell_dict eq {none} + || [catch {set spell_fd [open $spell_cmd r+]} spell_err]} { + bind_button3 $ui_comm [list tk_popup $ui_comm_ctxm %X %Y] + } else { + set ui_comm_spell [spellcheck::init \ + $spell_fd \ + $ui_comm \ + $ui_comm_ctxm \ + ] + } + unset -nocomplain spell_cmd spell_fd spell_err spell_dict } lock_index begin-read