Merge git://repo.or.cz/git-gui

* git://repo.or.cz/git-gui: (27 commits)
  git-gui: Update German translation.
  git-gui: Do not munge conflict marker lines in a normal diff
  git-gui: Add a simple implementation of SSH_ASKPASS.
  git-gui: Add a dialog that shows the OpenSSH public key.
  git-gui: Mark-up strings in show_{other,unmerged}_diff() for localization
  git-gui: Show a round number of bytes of large untracked text files
  git-gui: Fix the blame viewer destroy handler.
  git-gui: Add a search command to the blame viewer.
  git-gui: Fix the blame window shape.
  git-gui: Fix switch statement in lib/merge.tcl
  git-gui: Fix fetching from remotes when adding them
  git-gui: Fix removing non-pushable remotes
  git-gui: Make input boxes in init/clone/open dialogs consistent
  git-gui: Avoid using the term URL when specifying repositories
  git-gui: gui.autoexplore makes explorer to pop up automatically after picking
  git-gui: Add Explore Working Copy to the Repository menu
  git-gui: Use git web--browser for web browsing
  git-gui: mkdir -p when initializing new remote repository
  git-gui: Add support for removing remotes
  git-gui: Add support for adding remotes
  ...
This commit is contained in:
Junio C Hamano
2008-11-01 22:31:46 -07:00
17 changed files with 1084 additions and 194 deletions

View File

@ -21,9 +21,11 @@ field w_amov ; # text column: annotations + move tracking
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 status ; # status mega-widget instance
field old_height ; # last known height of $w.file_pane
# Tk UI colors
#
variable active_color #c0edc5
@ -59,7 +61,7 @@ field tooltip_timer {} ; # Current timer event for our tooltip
field tooltip_commit {} ; # Commit(s) in tooltip
constructor new {i_commit i_path i_jump} {
global cursor_ptr
global cursor_ptr M1B M1T have_tk85
variable active_color
variable group_colors
@ -69,6 +71,8 @@ constructor new {i_commit i_path i_jump} {
make_toplevel top w
wm title $top [append "[appname] ([reponame]): " [mc "File Viewer"]]
set font_w [font measure font_diff "0"]
frame $w.header -background gold
label $w.header.commit_l \
-text [mc "Commit:"] \
@ -114,9 +118,9 @@ constructor new {i_commit i_path i_jump} {
pack $w_path -fill x -side right
pack $w.header.path_l -side right
panedwindow $w.file_pane -orient vertical
frame $w.file_pane.out
frame $w.file_pane.cm
panedwindow $w.file_pane -orient vertical -borderwidth 0 -sashwidth 3
frame $w.file_pane.out -relief flat -borderwidth 1
frame $w.file_pane.cm -relief sunken -borderwidth 1
$w.file_pane add $w.file_pane.out \
-sticky nsew \
-minsize 100 \
@ -197,6 +201,11 @@ constructor new {i_commit i_path i_jump} {
-width 80 \
-xscrollcommand [list $w.file_pane.out.sbx set] \
-font font_diff
if {$have_tk85} {
$w_file configure -inactiveselectbackground darkblue
}
$w_file tag conf found \
-background yellow
set w_columns [list $w_amov $w_asim $w_line $w_file]
@ -217,6 +226,11 @@ constructor new {i_commit i_path i_jump} {
-weight 1
grid rowconfigure $w.file_pane.out 0 -weight 1
set finder [::searchbar::new \
$w.file_pane.out.ff $w_file \
-column [expr {[llength $w_columns] - 1}] \
]
set w_cviewer $w.file_pane.cm.t
text $w_cviewer \
-background white \
@ -257,6 +271,10 @@ constructor new {i_commit i_path i_jump} {
-label [mc "Copy Commit"] \
-command [cb _copycommit]
$w.ctxm add separator
$w.ctxm add command \
-label [mc "Find Text..."] \
-accelerator F7 \
-command [list searchbar::show $finder]
menu $w.ctxm.enc
build_encoding_menu $w.ctxm.enc [cb _setencoding]
$w.ctxm add cascade \
@ -278,9 +296,15 @@ constructor new {i_commit i_path i_jump} {
$i tag conf color$g -background [lindex $group_colors $g]
}
if {$i eq $w_file} {
$w_file tag raise found
}
$i tag raise sel
$i conf -cursor $cursor_ptr
$i conf -yscrollcommand [list many2scrollbar \
$w_columns yview $w.file_pane.out.sby]
$i conf -yscrollcommand \
"[list ::searchbar::scrolled $finder]
[list many2scrollbar $w_columns yview $w.file_pane.out.sby]"
bind $i <Button-1> "
[cb _hide_tooltip]
[cb _click $i @%x,%y]
@ -317,6 +341,11 @@ 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> [list focus $w_file]
bind $top <F7> [list searchbar::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]
catch { bind $top <Shift-Key-XF86_Switch_VT_3> [list searchbar::find_prev $finder] }
grid configure $w.header -sticky ew
grid configure $w.file_pane -sticky nsew
@ -328,9 +357,14 @@ constructor new {i_commit i_path i_jump} {
set req_w [winfo reqwidth $top]
set req_h [winfo reqheight $top]
set scr_h [expr {[winfo screenheight $top] - 100}]
if {$req_w < 600} {set req_w 600}
set scr_w [expr {[winfo screenwidth $top] - 40}]
set scr_h [expr {[winfo screenheight $top] - 120}]
set opt_w [expr {$font_w * (80 + 5*3 + 3)}]
if {$req_w < $opt_w} {set req_w $opt_w}
if {$req_w > $scr_w} {set req_w $scr_w}
set opt_h [expr {$req_w*4/3}]
if {$req_h < $scr_h} {set req_h $scr_h}
if {$req_h > $opt_h} {set req_h $opt_h}
set g "${req_w}x${req_h}"
wm geometry $top $g
update
@ -338,16 +372,23 @@ constructor new {i_commit i_path i_jump} {
set old_height [winfo height $w.file_pane]
$w.file_pane sash place 0 \
[lindex [$w.file_pane sash coord 0] 0] \
[expr {int($old_height * 0.70)}]
[expr {int($old_height * 0.80)}]
bind $w.file_pane <Configure> \
"if {{$w.file_pane} eq {%W}} {[cb _resize %h]}"
wm protocol $top WM_DELETE_WINDOW "destroy $top"
bind $top <Destroy> [cb _kill]
bind $top <Destroy> [cb _handle_destroy %W]
_load $this $i_jump
}
method _handle_destroy {win} {
if {$win eq $w} {
_kill $this
delete_this
}
}
method _kill {} {
if {$current_fd ne {}} {
kill_file_process $current_fd
@ -866,6 +907,10 @@ method _showcommit {cur_w lno} {
foreach i $w_columns {
$i tag conf g$cmit -background $active_color
$i tag raise g$cmit
if {$i eq $w_file} {
$w_file tag raise found
}
$i tag raise sel
}
set author_name {}

View File

@ -381,7 +381,8 @@ method _do_new {} {
label $w_body.where.l -text [mc "Directory:"]
entry $w_body.where.t \
-textvariable @local_path \
-font font_diff \
-borderwidth 1 \
-relief sunken \
-width 50
button $w_body.where.b \
-text [mc "Browse"] \
@ -463,20 +464,22 @@ method _do_clone {} {
frame $w_body.args
pack $args -fill both
label $args.origin_l -text [mc "URL:"]
label $args.origin_l -text [mc "Source Location:"]
entry $args.origin_t \
-textvariable @origin_url \
-font font_diff \
-borderwidth 1 \
-relief sunken \
-width 50
button $args.origin_b \
-text [mc "Browse"] \
-command [cb _open_origin]
grid $args.origin_l $args.origin_t $args.origin_b -sticky ew
label $args.where_l -text [mc "Directory:"]
label $args.where_l -text [mc "Target Directory:"]
entry $args.where_t \
-textvariable @local_path \
-font font_diff \
-borderwidth 1 \
-relief sunken \
-width 50
button $args.where_b \
-text [mc "Browse"] \
@ -979,7 +982,8 @@ method _do_open {} {
label $w_body.where.l -text [mc "Repository:"]
entry $w_body.where.t \
-textvariable @local_path \
-font font_diff \
-borderwidth 1 \
-relief sunken \
-width 50
button $w_body.where.b \
-text [mc "Browse"] \

View File

@ -117,22 +117,22 @@ proc show_unmerged_diff {cont_info} {
if {$merge_stages(2) eq {}} {
set is_conflict_diff 1
lappend current_diff_queue \
[list "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 "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 "LOCAL:\n" d======= \
[list [mc "LOCAL:\n"] d======= \
[list ":1:$current_diff_path" ":2:$current_diff_path"]]
lappend current_diff_queue \
[list "REMOTE:\n" d======= \
[list [mc "REMOTE:\n"] d======= \
[list ":1:$current_diff_path" ":3:$current_diff_path"]]
} else {
start_show_diff $cont_info
@ -164,7 +164,7 @@ proc show_other_diff {path w m cont_info} {
# - Git won't give us the diff, there's nothing to compare to!
#
if {$m eq {_O}} {
set max_sz [expr {128 * 1024}]
set max_sz 100000
set type unknown
if {[catch {
set type [file type $path]
@ -218,17 +218,17 @@ proc show_other_diff {path w m cont_info} {
d_@
} else {
if {$sz > $max_sz} {
$ui_diff insert end \
"* Untracked file is $sz bytes.
* Showing only first $max_sz bytes.
" d_@
$ui_diff insert end [mc \
"* Untracked file is %d bytes.
* Showing only first %d bytes.
" $sz $max_sz] d_@
}
$ui_diff insert end $content
if {$sz > $max_sz} {
$ui_diff insert end "
* Untracked file clipped here by [appname].
$ui_diff insert end [mc "
* Untracked file clipped here by %s.
* To see the entire file, use an external editor.
" d_@
" [appname]] d_@
}
}
$ui_diff conf -state disabled
@ -377,7 +377,6 @@ proc read_diff {fd cont_info} {
{+} {
if {[regexp {^\+([<>]{7} |={7})} $line _g op]} {
set is_conflict_diff 1
set line [string replace $line 0 0 { }]
set tags d$op
} else {
set tags d_+

View File

@ -298,11 +298,18 @@ proc add_helper {txt paths} {
set after {}
foreach path $paths {
switch -glob -- [lindex $file_states($path) 0] {
_U -
U? {
if {$path eq $current_diff_path} {
unlock_index
merge_stage_workdir $path
return
}
}
_O -
?M -
?D -
?T -
U? {
?T {
lappend pathList $path
if {$path eq $current_diff_path} {
set after {reshow_diff;}

View File

@ -40,6 +40,7 @@ The rescan will be automatically started now.
_O {
continue; # and pray it works!
}
_U -
U? {
error_popup [mc "You are in the middle of a conflicted merge.

View File

@ -23,13 +23,14 @@ This operation can be undone only by restarting the merge." \
}
}
proc merge_stage_workdir {path w lno} {
proc merge_stage_workdir {path {lno {}}} {
global current_diff_path diff_active
global current_diff_side ui_workdir
if {$diff_active} return
if {$path ne $current_diff_path} {
show_diff $path $w $lno {} [list do_merge_stage_workdir $path]
if {$path ne $current_diff_path || $ui_workdir ne $current_diff_side} {
show_diff $path $ui_workdir $lno {} [list do_merge_stage_workdir $path]
} else {
do_merge_stage_workdir $path
}
@ -375,14 +376,6 @@ proc merge_tool_finish {fd} {
}
}
# Check the modification time of the target file
if {!$failed && [file mtime $mtool_target] eq $mtool_mtime} {
if {[ask_popup [mc "File %s unchanged, still accept as resolved?" \
[short_path $mtool_target]]] ne {yes}} {
set failed 1
}
}
# Finish
if {$failed} {
file rename -force -- $backup $mtool_target
@ -395,6 +388,6 @@ proc merge_tool_finish {fd} {
delete_temp_files $mtool_tmpfiles
merge_add_resolution $mtool_target
reshow_diff
}
}

View File

@ -132,91 +132,145 @@ proc load_all_remotes {} {
set all_remotes [lsort -unique $all_remotes]
}
proc populate_fetch_menu {} {
global all_remotes repo_config
proc add_fetch_entry {r} {
global repo_config
set remote_m .mbar.remote
set fetch_m $remote_m.fetch
set prune_m $remote_m.prune
foreach r $all_remotes {
set enable 0
if {![catch {set a $repo_config(remote.$r.url)}]} {
if {![catch {set a $repo_config(remote.$r.fetch)}]} {
set enable 1
}
} else {
catch {
set fd [open [gitdir remotes $r] r]
while {[gets $fd n] >= 0} {
if {[regexp {^Pull:[ \t]*([^:]+):} $n]} {
set enable 1
break
}
set remove_m $remote_m.remove
set enable 0
if {![catch {set a $repo_config(remote.$r.url)}]} {
if {![catch {set a $repo_config(remote.$r.fetch)}]} {
set enable 1
}
} else {
catch {
set fd [open [gitdir remotes $r] r]
while {[gets $fd n] >= 0} {
if {[regexp {^Pull:[ \t]*([^:]+):} $n]} {
set enable 1
break
}
close $fd
}
close $fd
}
}
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
}
if {$enable} {
if {![winfo exists $fetch_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
}
$fetch_m add command \
-label $r \
-command [list fetch_from $r]
$prune_m add command \
-label $r \
-command [list prune_from $r]
}
$fetch_m add command \
-label $r \
-command [list fetch_from $r]
$prune_m add command \
-label $r \
-command [list prune_from $r]
$remove_m add command \
-label $r \
-command [list remove_remote $r]
}
}
proc populate_push_menu {} {
global all_remotes repo_config
proc add_push_entry {r} {
global repo_config
set remote_m .mbar.remote
set push_m $remote_m.push
foreach r $all_remotes {
set enable 0
if {![catch {set a $repo_config(remote.$r.url)}]} {
if {![catch {set a $repo_config(remote.$r.push)}]} {
set enable 1
}
} else {
catch {
set fd [open [gitdir remotes $r] r]
while {[gets $fd n] >= 0} {
if {[regexp {^Push:[ \t]*([^:]+):} $n]} {
set enable 1
break
}
}
close $fd
}
set enable 0
if {![catch {set a $repo_config(remote.$r.url)}]} {
if {![catch {set a $repo_config(remote.$r.push)}]} {
set enable 1
}
if {$enable} {
if {![winfo exists $push_m]} {
menu $push_m
$remote_m insert 0 cascade \
-label [mc "Push to"] \
-menu $push_m
} else {
catch {
set fd [open [gitdir remotes $r] r]
while {[gets $fd n] >= 0} {
if {[regexp {^Push:[ \t]*([^:]+):} $n]} {
set enable 1
break
}
}
$push_m add command \
-label $r \
-command [list push_to $r]
close $fd
}
}
if {$enable} {
if {![winfo exists $push_m]} {
menu $push_m
$remote_m insert 0 cascade \
-label [mc "Push to"] \
-menu $push_m
}
$push_m add command \
-label $r \
-command [list push_to $r]
}
}
proc populate_remotes_menu {} {
global all_remotes
foreach r $all_remotes {
add_fetch_entry $r
add_push_entry $r
}
}
proc add_single_remote {name location} {
global all_remotes repo_config
lappend all_remotes $name
git remote add $name $location
# XXX: Better re-read the config so that we will never get out
# of sync with git remote implementation?
set repo_config(remote.$name.url) $location
set repo_config(remote.$name.fetch) "+refs/heads/*:refs/remotes/$name/*"
add_fetch_entry $name
add_push_entry $name
}
proc delete_from_menu {menu name} {
if {[winfo exists $menu]} {
$menu delete $name
}
}
proc remove_remote {name} {
global all_remotes repo_config
git remote rm $name
catch {
# Missing values are ok
unset repo_config(remote.$name.url)
unset repo_config(remote.$name.fetch)
unset repo_config(remote.$name.push)
}
set i [lsearch -exact all_remotes $name]
lreplace all_remotes $i $i
set remote_m .mbar.remote
delete_from_menu $remote_m.fetch $name
delete_from_menu $remote_m.prune $name
delete_from_menu $remote_m.remove $name
# Not all remotes are in the push menu
catch { delete_from_menu $remote_m.push $name }
}

191
git-gui/lib/remote_add.tcl Normal file
View File

@ -0,0 +1,191 @@
# git-gui remote adding support
# Copyright (C) 2008 Petr Baudis
class remote_add {
field w ; # widget path
field w_name ; # new remote name widget
field w_loc ; # new remote location widget
field name {}; # name of the remote the user has chosen
field location {}; # location of the remote the user has chosen
field opt_action fetch; # action to do after registering the remote locally
constructor dialog {} {
global repo_config
make_toplevel top w
wm title $top [append "[appname] ([reponame]): " [mc "Add Remote"]]
if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
}
label $w.header -text [mc "Add New Remote"] -font font_uibold
pack $w.header -side top -fill x
frame $w.buttons
button $w.buttons.create -text [mc Add] \
-default active \
-command [cb _add]
pack $w.buttons.create -side right
button $w.buttons.cancel -text [mc Cancel] \
-command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
labelframe $w.desc -text [mc "Remote Details"]
label $w.desc.name_l -text [mc "Name:"]
set w_name $w.desc.name_t
entry $w_name \
-borderwidth 1 \
-relief sunken \
-width 40 \
-textvariable @name \
-validate key \
-validatecommand [cb _validate_name %d %S]
grid $w.desc.name_l $w_name -sticky we -padx {0 5}
label $w.desc.loc_l -text [mc "Location:"]
set w_loc $w.desc.loc_t
entry $w_loc \
-borderwidth 1 \
-relief sunken \
-width 40 \
-textvariable @location
grid $w.desc.loc_l $w_loc -sticky we -padx {0 5}
grid columnconfigure $w.desc 1 -weight 1
pack $w.desc -anchor nw -fill x -pady 5 -padx 5
labelframe $w.action -text [mc "Further Action"]
radiobutton $w.action.fetch \
-text [mc "Fetch Immediately"] \
-value fetch \
-variable @opt_action
pack $w.action.fetch -anchor nw
radiobutton $w.action.push \
-text [mc "Initialize Remote Repository and Push"] \
-value push \
-variable @opt_action
pack $w.action.push -anchor nw
radiobutton $w.action.none \
-text [mc "Do Nothing Else Now"] \
-value none \
-variable @opt_action
pack $w.action.none -anchor nw
grid columnconfigure $w.action 1 -weight 1
pack $w.action -anchor nw -fill x -pady 5 -padx 5
bind $w <Visibility> [cb _visible]
bind $w <Key-Escape> [list destroy $w]
bind $w <Key-Return> [cb _add]\;break
tkwait window $w
}
method _add {} {
global repo_config env
global M1B
if {$name eq {}} {
tk_messageBox \
-icon error \
-type ok \
-title [wm title $w] \
-parent $w \
-message [mc "Please supply a remote name."]
focus $w_name
return
}
# XXX: We abuse check-ref-format here, but
# that should be ok.
if {[catch {git check-ref-format "remotes/$name"}]} {
tk_messageBox \
-icon error \
-type ok \
-title [wm title $w] \
-parent $w \
-message [mc "'%s' is not an acceptable remote name." $name]
focus $w_name
return
}
if {[catch {add_single_remote $name $location}]} {
tk_messageBox \
-icon error \
-type ok \
-title [wm title $w] \
-parent $w \
-message [mc "Failed to add remote '%s' of location '%s'." $name $location]
focus $w_name
return
}
switch -- $opt_action {
fetch {
set c [console::new \
[mc "fetch %s" $name] \
[mc "Fetching the %s" $name]]
console::exec $c [list git fetch $name]
}
push {
set cmds [list]
# Parse the location
if { [regexp {(?:git\+)?ssh://([^/]+)(/.+)} $location xx host path]
|| [regexp {([^:][^:]+):(.+)} $location xx host path]} {
set ssh ssh
if {[info exists env(GIT_SSH)]} {
set ssh $env(GIT_SSH)
}
lappend cmds [list exec $ssh $host mkdir -p $location && git --git-dir=$path init --bare]
} elseif { ! [regexp {://} $location xx] } {
lappend cmds [list exec mkdir -p $location]
lappend cmds [list exec git --git-dir=$location init --bare]
} else {
tk_messageBox \
-icon error \
-type ok \
-title [wm title $w] \
-parent $w \
-message [mc "Do not know how to initialize repository at location '%s'." $location]
destroy $w
return
}
set c [console::new \
[mc "push %s" $name] \
[mc "Setting up the %s (at %s)" $name $location]]
lappend cmds [list exec git push -v --all $name]
console::chain $c $cmds
}
none {
}
}
destroy $w
}
method _validate_name {d S} {
if {$d == 1} {
if {[regexp {[~^:?*\[\0- ]} $S]} {
return 0
}
}
return 1
}
method _visible {} {
grab $w
$w_name icursor end
focus $w_name
}
}

View File

@ -26,12 +26,12 @@ constructor dialog {} {
global all_remotes M1B
make_toplevel top w
wm title $top [append "[appname] ([reponame]): " [mc "Delete Remote Branch"]]
wm title $top [append "[appname] ([reponame]): " [mc "Delete Branch Remotely"]]
if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
}
label $w.header -text [mc "Delete Remote Branch"] -font font_uibold
label $w.header -text [mc "Delete Branch Remotely"] -font font_uibold
pack $w.header -side top -fill x
frame $w.buttons
@ -63,7 +63,7 @@ constructor dialog {} {
set urltype url
}
radiobutton $w.dest.url_r \
-text [mc "Arbitrary URL:"] \
-text [mc "Arbitrary Location:"] \
-value url \
-variable @urltype
entry $w.dest.url_t \

190
git-gui/lib/search.tcl Normal file
View File

@ -0,0 +1,190 @@
# incremental search panel
# based on code from gitk, Copyright (C) Paul Mackerras
class searchbar {
field w
field ctext
field searchstring {}
field casesensitive 1
field searchdirn -forwards
field smarktop
field smarkbot
constructor new {i_w i_text args} {
set w $i_w
set ctext $i_text
frame $w
label $w.l -text [mc Find:]
button $w.bn -text [mc Next] -command [cb find_next]
button $w.bp -text [mc Prev] -command [cb find_prev]
checkbutton $w.cs -text [mc Case-Sensitive] \
-variable ${__this}::casesensitive -command [cb _incrsearch]
entry $w.ent -textvariable ${__this}::searchstring -background lightgreen
pack $w.l -side left
pack $w.cs -side right
pack $w.bp -side right
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 searchstring write [cb _incrsearch_cb]
bind $w <Destroy> [cb delete_this]
return $this
}
method show {} {
if {![winfo ismapped $w]} {
grid $w
}
focus -force $w.ent
}
method hide {} {
if {[winfo ismapped $w]} {
focus $ctext
grid remove $w
}
}
method _get_new_anchor {} {
# use start of selection if it is visible,
# or the bounds of the visible area
set top [$ctext index @0,0]
set bottom [$ctext index @0,[winfo height $ctext]]
set sel [$ctext tag ranges sel]
if {$sel ne {}} {
set spos [lindex $sel 0]
if {[lindex $spos 0] >= [lindex $top 0] &&
[lindex $spos 0] <= [lindex $bottom 0]} {
return $spos
}
}
if {$searchdirn eq "-forwards"} {
return $top
} else {
return $bottom
}
}
method _get_wrap_anchor {dir} {
if {$dir eq "-forwards"} {
return 1.0
} else {
return end
}
}
method _do_search {start {mlenvar {}} {dir {}} {endbound {}}} {
set cmd [list $ctext search]
if {$mlenvar ne {}} {
upvar $mlenvar mlen
lappend cmd -count mlen
}
if {!$casesensitive} {
lappend cmd -nocase
}
if {$dir eq {}} {
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]]
}
}
return $here
}
method _incrsearch_cb {name ix op} {
after idle [cb _incrsearch]
}
method _incrsearch {} {
$ctext tag remove found 1.0 end
if {[catch {$ctext index anchor}]} {
$ctext mark set anchor [_get_new_anchor $this]
}
if {$searchstring ne {}} {
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
_set_marks $this 1
} else {
$w.ent configure -background lightpink
}
}
}
method find_prev {} {
find_next $this -backwards
}
method find_next {{dir -forwards}} {
focus $w.ent
$w.ent icursor end
set searchdirn $dir
$ctext mark unset anchor
if {$searchstring ne {}} {
set start [_get_new_anchor $this]
if {$dir eq "-forwards"} {
set start "$start + 1c"
}
set match [_do_search $this $start mlen]
$ctext tag remove sel 1.0 end
if {$match ne {}} {
$ctext see $match
$ctext tag add sel $match "$match + $mlen c"
}
}
}
method _mark_range {first last} {
set mend $first.0
while {1} {
set match [_do_search $this $mend mlen -forwards $last.end]
if {$match eq {}} break
set mend "$match + $mlen c"
$ctext tag add found $match $mend
}
}
method _set_marks {doall} {
set topline [lindex [split [$ctext index @0,0] .] 0]
set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0]
if {$doall || $botline < $smarktop || $topline > $smarkbot} {
# no overlap with previous
_mark_range $this $topline $botline
set smarktop $topline
set smarkbot $botline
} else {
if {$topline < $smarktop} {
_mark_range $this $topline [expr {$smarktop-1}]
set smarktop $topline
}
if {$botline > $smarkbot} {
_mark_range $this [expr {$smarkbot+1}] $botline
set smarkbot $botline
}
}
}
method scrolled {} {
if {$searchstring ne {}} {
after idle [cb _set_marks 0]
}
}
}

View File

@ -80,7 +80,7 @@ method _connect {pipe_fd} {
error_popup [strcat [mc "Unrecognized spell checker"] ":\n\n$s_version"]
return
}
set s_version [string range $s_version 5 end]
set s_version [string range [string trim $s_version] 5 end]
regexp \
{International Ispell Version .* \(but really (Aspell .*?)\)$} \
$s_version _junk s_version
@ -314,6 +314,7 @@ method _run {} {
method _read {} {
while {[gets $s_fd line] >= 0} {
set lineno [lindex $s_pending 0 0]
set line [string trim $line]
if {$s_clear} {
$w_text tag remove misspelled "$lineno.0" "$lineno.end"

126
git-gui/lib/sshkey.tcl Normal file
View File

@ -0,0 +1,126 @@
# git-gui about git-gui dialog
# Copyright (C) 2006, 2007 Shawn Pearce
proc find_ssh_key {} {
foreach name {~/.ssh/id_dsa.pub ~/.ssh/id_rsa.pub ~/.ssh/identity.pub} {
if {[file exists $name]} {
set fh [open $name r]
set cont [read $fh]
close $fh
return [list $name $cont]
}
}
return {}
}
proc do_ssh_key {} {
global sshkey_title have_tk85 sshkey_fd
set w .sshkey_dialog
if {[winfo exists $w]} {
raise $w
return
}
toplevel $w
wm transient $w .
set finfo [find_ssh_key]
if {$finfo eq {}} {
set sshkey_title [mc "No keys found."]
set gen_state normal
} else {
set sshkey_title [mc "Found a public key in: %s" [lindex $finfo 0]]
set gen_state disabled
}
frame $w.header -relief flat
label $w.header.lbl -textvariable sshkey_title -anchor w
button $w.header.gen -text [mc "Generate Key"] \
-command [list make_ssh_key $w] -state $gen_state
pack $w.header.lbl -side left -expand 1 -fill x
pack $w.header.gen -side right
pack $w.header -fill x -pady 5 -padx 5
text $w.contents -width 60 -height 10 -wrap char -relief sunken
pack $w.contents -fill both -expand 1
if {$have_tk85} {
$w.contents configure -inactiveselectbackground darkblue
}
frame $w.buttons
button $w.buttons.close -text [mc Close] \
-default active -command [list destroy $w]
pack $w.buttons.close -side right
button $w.buttons.copy -text [mc "Copy To Clipboard"] \
-command [list tk_textCopy $w.contents]
pack $w.buttons.copy -side left
pack $w.buttons -side bottom -fill x -pady 5 -padx 5
if {$finfo ne {}} {
$w.contents insert end [lindex $finfo 1] sel
}
$w.contents configure -state disabled
bind $w <Visibility> "grab $w; focus $w.buttons.close"
bind $w <Key-Escape> "destroy $w"
bind $w <Key-Return> "destroy $w"
bind $w <Destroy> kill_sshkey
wm title $w [mc "Your OpenSSH Public Key"]
tk::PlaceWindow $w widget .
tkwait window $w
}
proc make_ssh_key {w} {
global sshkey_title sshkey_output sshkey_fd
set sshkey_title [mc "Generating..."]
$w.header.gen configure -state disabled
set cmdline [list sh -c {echo | ssh-keygen -q -t rsa -f ~/.ssh/id_rsa 2>&1}]
if {[catch { set sshkey_fd [_open_stdout_stderr $cmdline] } err]} {
error_popup [mc "Could not start ssh-keygen:\n\n%s" $err]
return
}
set sshkey_output {}
fconfigure $sshkey_fd -blocking 0
fileevent $sshkey_fd readable [list read_sshkey_output $sshkey_fd $w]
}
proc kill_sshkey {} {
global sshkey_fd
if {![info exists sshkey_fd]} return
catch { kill_file_process $sshkey_fd }
catch { close $sshkey_fd }
}
proc read_sshkey_output {fd w} {
global sshkey_fd sshkey_output sshkey_title
set sshkey_output "$sshkey_output[read $fd]"
if {![eof $fd]} return
fconfigure $fd -blocking 1
unset sshkey_fd
$w.contents configure -state normal
if {[catch {close $fd} err]} {
set sshkey_title [mc "Generation failed."]
$w.contents insert end $err
$w.contents insert end "\n"
$w.contents insert end $sshkey_output
} else {
set finfo [find_ssh_key]
if {$finfo eq {}} {
set sshkey_title [mc "Generation succeded, but no keys found."]
$w.contents insert end $sshkey_output
} else {
set sshkey_title [mc "Your key is in: %s" [lindex $finfo 0]]
$w.contents insert end [lindex $finfo 1] sel
}
}
$w.contents configure -state disable
}

View File

@ -135,7 +135,7 @@ proc do_push_anywhere {} {
set push_urltype url
}
radiobutton $w.dest.url_r \
-text [mc "Arbitrary URL:"] \
-text [mc "Arbitrary Location:"] \
-value url \
-variable push_urltype
entry $w.dest.url_t \