X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=gitk;h=4aa57c01ce56e505aba5384f716376a68a7fdc7a;hb=de1d4fa2a1273e09c32653c7a21602e36223348c;hp=f983deee8b7814d8e8ed8f13ceec63b75a5c03f8;hpb=f8b28a4078a29cbf93cac6f9edd8d5c203777313;p=git.git diff --git a/gitk b/gitk index f983deee..4aa57c01 100755 --- a/gitk +++ b/gitk @@ -16,100 +16,112 @@ proc gitdir {} { } } -proc start_rev_list {} { +proc start_rev_list {view} { global startmsecs nextupdate ncmupdate global commfd leftover tclencoding datemode - global revtreeargs curview viewfiles + global viewargs viewfiles commitidx set startmsecs [clock clicks -milliseconds] set nextupdate [expr {$startmsecs + 100}] set ncmupdate 1 - initlayout - set args $revtreeargs - if {$viewfiles($curview) ne {}} { - set args [concat $args "--" $viewfiles($curview)] + set commitidx($view) 0 + set args $viewargs($view) + if {$viewfiles($view) ne {}} { + set args [concat $args "--" $viewfiles($view)] } set order "--topo-order" if {$datemode} { set order "--date-order" } if {[catch { - set commfd [open [concat | git-rev-list --header $order \ - --parents --boundary --default HEAD $args] r] + set fd [open [concat | git-rev-list --header $order \ + --parents --boundary --default HEAD $args] r] } err]} { puts stderr "Error executing git-rev-list: $err" exit 1 } - set leftover {} - fconfigure $commfd -blocking 0 -translation lf + set commfd($view) $fd + set leftover($view) {} + fconfigure $fd -blocking 0 -translation lf if {$tclencoding != {}} { - fconfigure $commfd -encoding $tclencoding + fconfigure $fd -encoding $tclencoding } - fileevent $commfd readable [list getcommitlines $commfd] - . config -cursor watch - settextcursor watch + fileevent $fd readable [list getcommitlines $fd $view] + nowbusy $view } proc stop_rev_list {} { - global commfd + global commfd curview - if {![info exists commfd]} return + if {![info exists commfd($curview)]} return + set fd $commfd($curview) catch { - set pid [pid $commfd] + set pid [pid $fd] exec kill $pid } - catch {close $commfd} - unset commfd + catch {close $fd} + unset commfd($curview) } proc getcommits {} { - global phase canv mainfont + global phase canv mainfont curview set phase getcommits - start_rev_list - $canv delete all - $canv create text 3 3 -anchor nw -text "Reading commits..." \ - -font $mainfont -tags textitems + initlayout + start_rev_list $curview + show_status "Reading commits..." } -proc getcommitlines {commfd} { +proc getcommitlines {fd view} { global commitlisted nextupdate - global leftover + global leftover commfd global displayorder commitidx commitrow commitdata - global parentlist childlist children + global parentlist childlist children curview hlview + global vparentlist vchildlist vdisporder vcmitlisted - set stuff [read $commfd] + set stuff [read $fd] if {$stuff == {}} { - if {![eof $commfd]} return + if {![eof $fd]} return + global viewname + unset commfd($view) + notbusy $view # set it blocking so we wait for the process to terminate - fconfigure $commfd -blocking 1 - if {![catch {close $commfd} err]} { - after idle finishcommits - return + fconfigure $fd -blocking 1 + if {[catch {close $fd} err]} { + set fv {} + if {$view != $curview} { + set fv " for the \"$viewname($view)\" view" + } + if {[string range $err 0 4] == "usage"} { + set err "Gitk: error reading commits$fv:\ + bad arguments to git-rev-list." + if {$viewname($view) eq "Command line"} { + append err \ + " (Note: arguments to gitk are passed to git-rev-list\ + to allow selection of commits to be displayed.)" + } + } else { + set err "Error reading commits$fv: $err" + } + error_popup $err } - if {[string range $err 0 4] == "usage"} { - set err \ - "Gitk: error reading commits: bad arguments to git-rev-list.\ - (Note: arguments to gitk are passed to git-rev-list\ - to allow selection of commits to be displayed.)" - } else { - set err "Error reading commits: $err" + if {$view == $curview} { + after idle finishcommits } - error_popup $err - exit 1 + return } set start 0 set gotsome 0 while 1 { set i [string first "\0" $stuff $start] if {$i < 0} { - append leftover [string range $stuff $start end] + append leftover($view) [string range $stuff $start end] break } if {$start == 0} { - set cmit $leftover + set cmit $leftover($view) append cmit [string range $stuff 0 [expr {$i - 1}]] - set leftover {} + set leftover($view) {} } else { set cmit [string range $stuff $start [expr {$i - 1}]] } @@ -145,40 +157,49 @@ proc getcommitlines {commfd} { set i 0 foreach p $olds { if {$i == 0 || [lsearch -exact $olds $p] >= $i} { - lappend children($p) $id + lappend children($view,$p) $id } incr i } } else { set olds {} } - lappend parentlist $olds - if {[info exists children($id)]} { - lappend childlist $children($id) - unset children($id) - } else { - lappend childlist {} + if {![info exists children($view,$id)]} { + set children($view,$id) {} } set commitdata($id) [string range $cmit [expr {$j + 1}] end] - set commitrow($id) $commitidx - incr commitidx - lappend displayorder $id - lappend commitlisted $listed + set commitrow($view,$id) $commitidx($view) + incr commitidx($view) + if {$view == $curview} { + lappend parentlist $olds + lappend childlist $children($view,$id) + lappend displayorder $id + lappend commitlisted $listed + } else { + lappend vparentlist($view) $olds + lappend vchildlist($view) $children($view,$id) + lappend vdisporder($view) $id + lappend vcmitlisted($view) $listed + } set gotsome 1 } if {$gotsome} { - layoutmore + if {$view == $curview} { + layoutmore + } elseif {[info exists hlview] && $view == $hlview} { + highlightmore + } } if {[clock clicks -milliseconds] >= $nextupdate} { - doupdate 1 + doupdate } } -proc doupdate {reading} { +proc doupdate {} { global commfd nextupdate numcommits ncmupdate - if {$reading} { - fileevent $commfd readable {} + foreach v [array names commfd] { + fileevent $commfd($v) readable {} } update set nextupdate [expr {[clock clicks -milliseconds] + 100}] @@ -189,8 +210,9 @@ proc doupdate {reading} { } else { set ncmupdate [expr {$numcommits + 100}] } - if {$reading} { - fileevent $commfd readable [list getcommitlines $commfd] + foreach v [array names commfd] { + set fd $commfd($v) + fileevent $fd readable [list getcommitlines $fd $v] } } @@ -200,13 +222,18 @@ proc readcommit {id} { } proc updatecommits {} { - global viewdata curview revtreeargs phase + global viewdata curview phase displayorder + global children commitrow if {$phase ne {}} { stop_rev_list set phase {} } set n $curview + foreach id $displayorder { + catch {unset children($n,$id)} + catch {unset commitrow($n,$id)} + } set curview -1 catch {unset viewdata($n)} readrefs @@ -330,10 +357,7 @@ proc readrefs {} { close $refd } -proc error_popup msg { - set w .error - toplevel $w - wm transient $w . +proc show_error {w msg} { message $w.m -text $msg -justify center -aspect 400 pack $w.m -side top -fill x -padx 20 -pady 20 button $w.ok -text OK -command "destroy $w" @@ -343,6 +367,13 @@ proc error_popup msg { tkwait window $w } +proc error_popup msg { + set w .error + toplevel $w + wm transient $w . + show_error $w $msg +} + proc makewindow {} { global canv canv2 canv3 linespc charspc ctext cflist global textfont mainfont uifont @@ -363,14 +394,23 @@ proc makewindow {} { .bar add cascade -label "Edit" -menu .bar.edit .bar.edit add command -label "Preferences" -command doprefs .bar.edit configure -font $uifont + menu .bar.view -font $uifont + menu .bar.view.hl -font $uifont -tearoff 0 .bar add cascade -label "View" -menu .bar.view - .bar.view add command -label "New view..." -command newview - .bar.view add command -label "Edit view..." -command editview + .bar.view add command -label "New view..." -command {newview 0} + .bar.view add command -label "Edit view..." -command editview \ + -state disabled .bar.view add command -label "Delete view" -command delview -state disabled + .bar.view add cascade -label "Highlight" -menu .bar.view.hl .bar.view add separator .bar.view add radiobutton -label "All files" -command {showview 0} \ -variable selectedview -value 0 + .bar.view.hl add command -label "New view..." -command {newview 1} + .bar.view.hl add command -label "Remove" -command delhighlight \ + -state disabled + .bar.view.hl add separator + menu .bar.help .bar add cascade -label "Help" -menu .bar.help .bar.help add command -label "About gitk" -command about @@ -481,7 +521,7 @@ proc makewindow {} { set ctext .ctop.cdet.left.ctext text $ctext -bg white -state disabled -font $textfont \ -width $geometry(ctextw) -height $geometry(ctexth) \ - -yscrollcommand scrolltext -wrap none + -yscrollcommand {.ctop.cdet.left.sb set} -wrap none scrollbar .ctop.cdet.left.sb -command "$ctext yview" pack .ctop.cdet.left.sb -side right -fill y pack $ctext -side left -fill both -expand 1 @@ -531,7 +571,8 @@ proc makewindow {} { scrollbar .ctop.cdet.right.sb -command "$cflist yview" pack .ctop.cdet.right.sb -side right -fill y pack $cflist -side left -fill both -expand 1 - $cflist tag configure highlight -background yellow + $cflist tag configure highlight \ + -background [$cflist cget -selectbackground] .ctop.cdet add .ctop.cdet.right bind .ctop.cdet {resizecdetpanes %W %w} @@ -654,7 +695,7 @@ proc savestuff {w} { global canv canv2 canv3 ctext cflist mainfont textfont uifont global stuffsaved findmergefiles maxgraphpct global maxwidth - global viewname viewfiles viewperm nextviewnum + global viewname viewfiles viewargs viewperm nextviewnum global cmitmode if {$stuffsaved} return @@ -683,7 +724,7 @@ proc savestuff {w} { puts -nonewline $f "set permviews {" for {set v 0} {$v < $nextviewnum} {incr v} { if {$viewperm($v)} { - puts $f "{[list $viewname($v) $viewfiles($v)]}" + puts $f "{[list $viewname($v) $viewfiles($v) $viewargs($v)]}" } } puts $f "}" @@ -1061,14 +1102,13 @@ image create bitmap tri-dn -background black -foreground blue -data { } proc init_flist {first} { - global cflist cflist_top cflist_bot selectedline difffilestart + global cflist cflist_top selectedline difffilestart $cflist conf -state normal $cflist delete 0.0 end if {$first ne {}} { $cflist insert end $first set cflist_top 1 - set cflist_bot 1 $cflist tag add highlight 1.0 "1.0 lineend" } else { catch {unset cflist_top} @@ -1095,68 +1135,117 @@ proc sel_flist {w x y} { if {$cmitmode eq "tree"} return if {![info exists cflist_top]} return set l [lindex [split [$w index "@$x,$y"] "."] 0] + $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend" + $cflist tag add highlight $l.0 "$l.0 lineend" + set cflist_top $l if {$l == 1} { $ctext yview 1.0 } else { catch {$ctext yview [lindex $difffilestart [expr {$l - 2}]]} } - highlight_flist $l } -proc scrolltext {f0 f1} { - global cflist_top +# Functions for adding and removing shell-type quoting - .ctop.cdet.left.sb set $f0 $f1 - if {[info exists cflist_top]} { - highlight_flist $cflist_top +proc shellquote {str} { + if {![string match "*\['\"\\ \t]*" $str]} { + return $str } -} - -# Given an index $tl in the $ctext window, this works out which line -# of the $cflist window displays the filename whose patch is shown -# at the given point in the $ctext window. $ll is a hint about which -# line it might be, and is used as the starting point of the search. -proc ctext_index {tl ll} { - global ctext difffilestart - - while {$ll >= 2 && [$ctext compare $tl < \ - [lindex $difffilestart [expr {$ll - 2}]]]} { - incr ll -1 + if {![string match "*\['\"\\]*" $str]} { + return "\"$str\"" } - set nfiles [llength $difffilestart] - while {$ll - 1 < $nfiles && [$ctext compare $tl >= \ - [lindex $difffilestart [expr {$ll - 1}]]]} { - incr ll + if {![string match "*'*" $str]} { + return "'$str'" } - return $ll + return "\"[string map {\" \\\" \\ \\\\} $str]\"" } -proc highlight_flist {ll} { - global ctext cflist cflist_top cflist_bot difffilestart - - if {![info exists difffilestart] || [llength $difffilestart] == 0} return - set ll [ctext_index [$ctext index @0,1] $ll] - set lb $cflist_bot - if {$lb < $ll} { - set lb $ll +proc shellarglist {l} { + set str {} + foreach a $l { + if {$str ne {}} { + append str " " + } + append str [shellquote $a] } - set y [expr {[winfo height $ctext] - 2}] - set lb [ctext_index [$ctext index @0,$y] $lb] - if {$ll != $cflist_top || $lb != $cflist_bot} { - $cflist tag remove highlight $cflist_top.0 "$cflist_bot.0 lineend" - for {set l $ll} {$l <= $lb} {incr l} { - $cflist tag add highlight $l.0 "$l.0 lineend" + return $str +} + +proc shelldequote {str} { + set ret {} + set used -1 + while {1} { + incr used + if {![regexp -start $used -indices "\['\"\\\\ \t]" $str first]} { + append ret [string range $str $used end] + set used [string length $str] + break + } + set first [lindex $first 0] + set ch [string index $str $first] + if {$first > $used} { + append ret [string range $str $used [expr {$first - 1}]] + set used $first + } + if {$ch eq " " || $ch eq "\t"} break + incr used + if {$ch eq "'"} { + set first [string first "'" $str $used] + if {$first < 0} { + error "unmatched single-quote" + } + append ret [string range $str $used [expr {$first - 1}]] + set used $first + continue + } + if {$ch eq "\\"} { + if {$used >= [string length $str]} { + error "trailing backslash" + } + append ret [string index $str $used] + continue + } + # here ch == "\"" + while {1} { + if {![regexp -start $used -indices "\[\"\\\\]" $str first]} { + error "unmatched double-quote" + } + set first [lindex $first 0] + set ch [string index $str $first] + if {$first > $used} { + append ret [string range $str $used [expr {$first - 1}]] + set used $first + } + if {$ch eq "\""} break + incr used + append ret [string index $str $used] + incr used } - set cflist_top $ll - set cflist_bot $lb } + return [list $used $ret] +} + +proc shellsplit {str} { + set l {} + while {1} { + set str [string trimleft $str] + if {$str eq {}} break + set dq [shelldequote $str] + set n [lindex $dq 0] + set word [lindex $dq 1] + set str [string range $str $n end] + lappend l $word + } + return $l } # Code to implement multiple views -proc newview {} { - global nextviewnum newviewname newviewperm uifont +proc newview {ishighlight} { + global nextviewnum newviewname newviewperm uifont newishighlight + global newviewargs revtreeargs + set newishighlight $ishighlight set top .gitkview if {[winfo exists $top]} { raise $top @@ -1164,12 +1253,14 @@ proc newview {} { } set newviewname($nextviewnum) "View $nextviewnum" set newviewperm($nextviewnum) 0 + set newviewargs($nextviewnum) [shellarglist $revtreeargs] vieweditor $top $nextviewnum "Gitk view definition" } proc editview {} { global curview global viewname viewperm newviewname newviewperm + global viewargs newviewargs set top .gitkvedit-$curview if {[winfo exists $top]} { @@ -1178,6 +1269,7 @@ proc editview {} { } set newviewname($curview) $viewname($curview) set newviewperm($curview) $viewperm($curview) + set newviewargs($curview) [shellarglist $viewargs($curview)] vieweditor $top $curview "Gitk: edit view $viewname($curview)" } @@ -1192,7 +1284,13 @@ proc vieweditor {top n title} { grid $top.nl $top.name -sticky w -pady 5 checkbutton $top.perm -text "Remember this view" -variable newviewperm($n) grid $top.perm - -pady 5 -sticky w - message $top.l -aspect 500 -font $uifont \ + message $top.al -aspect 1000 -font $uifont \ + -text "Commits to include (arguments to git-rev-list):" + grid $top.al - -sticky w -pady 5 + entry $top.args -width 50 -textvariable newviewargs($n) \ + -background white + grid $top.args - -sticky ew -padx 5 + message $top.l -aspect 1000 -font $uifont \ -text "Enter files and directories to include, one per line:" grid $top.l - -sticky w text $top.t -width 40 -height 10 -background white @@ -1204,7 +1302,7 @@ proc vieweditor {top n title} { $top.t delete {end - 1c} end $top.t mark set insert 0.0 } - grid $top.t - -sticky w -padx 5 + grid $top.t - -sticky ew -padx 5 frame $top.buts button $top.buts.ok -text "OK" -command [list newviewok $top $n] button $top.buts.can -text "Cancel" -command [list destroy $top] @@ -1215,21 +1313,34 @@ proc vieweditor {top n title} { focus $top.t } -proc viewmenuitem {n} { - set nmenu [.bar.view index end] - set targetcmd [list showview $n] - for {set i 6} {$i <= $nmenu} {incr i} { - if {[.bar.view entrycget $i -command] eq $targetcmd} { - return $i +proc doviewmenu {m first cmd op args} { + set nmenu [$m index end] + for {set i $first} {$i <= $nmenu} {incr i} { + if {[$m entrycget $i -command] eq $cmd} { + eval $m $op $i $args + break } } - return {} +} + +proc allviewmenus {n op args} { + doviewmenu .bar.view 7 [list showview $n] $op $args + doviewmenu .bar.view.hl 3 [list addhighlight $n] $op $args } proc newviewok {top n} { - global nextviewnum newviewperm newviewname + global nextviewnum newviewperm newviewname newishighlight global viewname viewfiles viewperm selectedview curview + global viewargs newviewargs + if {[catch { + set newargs [shellsplit $newviewargs($n)] + } err]} { + error_popup "Error in commit selection arguments: $err" + wm raise $top + focus $top + return + } set files {} foreach f [split [$top.t get 0.0 end] "\n"] { set ft [string trim $f] @@ -1243,21 +1354,23 @@ proc newviewok {top n} { set viewname($n) $newviewname($n) set viewperm($n) $newviewperm($n) set viewfiles($n) $files - .bar.view add radiobutton -label $viewname($n) \ - -command [list showview $n] -variable selectedview -value $n - after idle showview $n + set viewargs($n) $newargs + addviewmenu $n + if {!$newishighlight} { + after idle showview $n + } else { + after idle addhighlight $n + } } else { # editing an existing view set viewperm($n) $newviewperm($n) if {$newviewname($n) ne $viewname($n)} { set viewname($n) $newviewname($n) - set i [viewmenuitem $n] - if {$i ne {}} { - .bar.view entryconf $i -label $viewname($n) - } + allviewmenus $n entryconf -label $viewname($n) } - if {$files ne $viewfiles($n)} { + if {$files ne $viewfiles($n) || $newargs ne $viewargs($n)} { set viewfiles($n) $files + set viewargs($n) $newargs if {$curview == $n} { after idle updatecommits } @@ -1270,15 +1383,21 @@ proc delview {} { global curview viewdata viewperm if {$curview == 0} return - set i [viewmenuitem $curview] - if {$i ne {}} { - .bar.view delete $i - } + allviewmenus $curview delete set viewdata($curview) {} set viewperm($curview) 0 showview 0 } +proc addviewmenu {n} { + global viewname + + .bar.view add radiobutton -label $viewname($n) \ + -command [list showview $n] -variable selectedview -value $n + .bar.view.hl add radiobutton -label $viewname($n) \ + -command [list addhighlight $n] -variable selectedhlview -value $n +} + proc flatten {var} { global $var @@ -1301,14 +1420,15 @@ proc unflatten {var l} { proc showview {n} { global curview viewdata viewfiles global displayorder parentlist childlist rowidlist rowoffsets - global colormap rowtextx commitrow + global colormap rowtextx commitrow nextcolor canvxmax global numcommits rowrangelist commitlisted idrowranges global selectedline currentid canv canvy0 global matchinglines treediffs global pending_select phase - global commitidx rowlaidout rowoptim linesegends leftover + global commitidx rowlaidout rowoptim linesegends global commfd nextupdate - global selectedview + global selectedview hlview selectedhlview + global vparentlist vchildlist vdisporder vcmitlisted if {$n == $curview} return set selid {} @@ -1329,20 +1449,19 @@ proc showview {n} { normalline stopfindproc if {$curview >= 0} { + set vparentlist($curview) $parentlist + set vchildlist($curview) $childlist + set vdisporder($curview) $displayorder + set vcmitlisted($curview) $commitlisted if {$phase ne {}} { set viewdata($curview) \ - [list $phase $displayorder $parentlist $childlist $rowidlist \ - $rowoffsets $rowrangelist $commitlisted \ - [flatten children] [flatten idrowranges] \ - [flatten idinlist] \ - $commitidx $rowlaidout $rowoptim $numcommits \ - $linesegends $leftover $commfd] - fileevent $commfd readable {} + [list $phase $rowidlist $rowoffsets $rowrangelist \ + [flatten idrowranges] [flatten idinlist] \ + $rowlaidout $rowoptim $numcommits $linesegends] } elseif {![info exists viewdata($curview)] || [lindex $viewdata($curview) 0] ne {}} { set viewdata($curview) \ - [list {} $displayorder $parentlist $childlist $rowidlist \ - $rowoffsets $rowrangelist $commitlisted] + [list {} $rowidlist $rowoffsets $rowrangelist] } } catch {unset matchinglines} @@ -1351,8 +1470,11 @@ proc showview {n} { set curview $n set selectedview $n + set selectedhlview -1 .bar.view entryconf 2 -state [expr {$n == 0? "disabled": "normal"}] .bar.view entryconf 3 -state [expr {$n == 0? "disabled": "normal"}] + catch {unset hlview} + .bar.view.hl entryconf 1 -state disabled if {![info exists viewdata($n)]} { set pending_select $selid @@ -1362,46 +1484,36 @@ proc showview {n} { set v $viewdata($n) set phase [lindex $v 0] - set displayorder [lindex $v 1] - set parentlist [lindex $v 2] - set childlist [lindex $v 3] - set rowidlist [lindex $v 4] - set rowoffsets [lindex $v 5] - set rowrangelist [lindex $v 6] - set commitlisted [lindex $v 7] + set displayorder $vdisporder($n) + set parentlist $vparentlist($n) + set childlist $vchildlist($n) + set commitlisted $vcmitlisted($n) + set rowidlist [lindex $v 1] + set rowoffsets [lindex $v 2] + set rowrangelist [lindex $v 3] if {$phase eq {}} { set numcommits [llength $displayorder] catch {unset idrowranges} - catch {unset children} } else { - unflatten children [lindex $v 8] - unflatten idrowranges [lindex $v 9] - unflatten idinlist [lindex $v 10] - set commitidx [lindex $v 11] - set rowlaidout [lindex $v 12] - set rowoptim [lindex $v 13] - set numcommits [lindex $v 14] - set linesegends [lindex $v 15] - set leftover [lindex $v 16] - set commfd [lindex $v 17] - fileevent $commfd readable [list getcommitlines $commfd] - set nextupdate [expr {[clock clicks -milliseconds] + 100}] + unflatten idrowranges [lindex $v 4] + unflatten idinlist [lindex $v 5] + set rowlaidout [lindex $v 6] + set rowoptim [lindex $v 7] + set numcommits [lindex $v 8] + set linesegends [lindex $v 9] } catch {unset colormap} catch {unset rowtextx} - catch {unset commitrow} + set nextcolor 0 + set canvxmax [$canv cget -width] set curview $n set row 0 - foreach id $displayorder { - set commitrow($id) $row - incr row - } setcanvscroll set yf 0 set row 0 - if {$selid ne {} && [info exists commitrow($selid)]} { - set row $commitrow($selid) + if {$selid ne {} && [info exists commitrow($n,$selid)]} { + set row $commitrow($n,$selid) # try to get the selected row in the same position on the screen set ymax [lindex [$canv cget -scrollregion] 3] set ytop [expr {[yc $row] - $yscreen}] @@ -1413,21 +1525,98 @@ proc showview {n} { allcanvs yview moveto $yf drawvisible selectline $row 0 - if {$phase eq {}} { - global maincursor textcursor - . config -cursor $maincursor - settextcursor $textcursor - } else { - . config -cursor watch - settextcursor watch + if {$phase ne {}} { if {$phase eq "getcommits"} { - global mainfont - $canv create text 3 3 -anchor nw -text "Reading commits..." \ - -font $mainfont -tags textitems + show_status "Reading commits..." + } + if {[info exists commfd($n)]} { + layoutmore + } else { + finishcommits + } + } elseif {$numcommits == 0} { + show_status "No commits selected" + } +} + +proc addhighlight {n} { + global hlview curview viewdata highlighted highlightedrows + global selectedhlview + + if {[info exists hlview]} { + delhighlight + } + set hlview $n + set selectedhlview $n + .bar.view.hl entryconf 1 -state normal + set highlighted($n) 0 + set highlightedrows {} + if {$n != $curview && ![info exists viewdata($n)]} { + set viewdata($n) [list getcommits {{}} {{}} {} {} {} 0 0 0 {}] + set vparentlist($n) {} + set vchildlist($n) {} + set vdisporder($n) {} + set vcmitlisted($n) {} + start_rev_list $n + } else { + highlightmore + } +} + +proc delhighlight {} { + global hlview highlightedrows canv linehtag mainfont + global selectedhlview selectedline + + if {![info exists hlview]} return + unset hlview + set selectedhlview {} + .bar.view.hl entryconf 1 -state disabled + foreach l $highlightedrows { + $canv itemconf $linehtag($l) -font $mainfont + if {$l == $selectedline} { + $canv delete secsel + set t [eval $canv create rect [$canv bbox $linehtag($l)] \ + -outline {{}} -tags secsel \ + -fill [$canv cget -selectbackground]] + $canv lower $t } } } +proc highlightmore {} { + global hlview highlighted commitidx highlightedrows linehtag mainfont + global displayorder vdisporder curview canv commitrow selectedline + + set font [concat $mainfont bold] + set max $commitidx($hlview) + if {$hlview == $curview} { + set disp $displayorder + } else { + set disp $vdisporder($hlview) + } + for {set i $highlighted($hlview)} {$i < $max} {incr i} { + set id [lindex $disp $i] + if {[info exists commitrow($curview,$id)]} { + set row $commitrow($curview,$id) + if {[info exists linehtag($row)]} { + $canv itemconf $linehtag($row) -font $font + lappend highlightedrows $row + if {$row == $selectedline} { + $canv delete secsel + set t [eval $canv create rect \ + [$canv bbox $linehtag($row)] \ + -outline {{}} -tags secsel \ + -fill [$canv cget -selectbackground]] + $canv lower $t + } + } + } + } + set highlighted($hlview) $max +} + +# Graph layout functions + proc shortids {ids} { set res {} foreach id $ids { @@ -1463,19 +1652,19 @@ proc ntimes {n o} { } proc usedinrange {id l1 l2} { - global children commitrow childlist + global children commitrow childlist curview - if {[info exists commitrow($id)]} { - set r $commitrow($id) + if {[info exists commitrow($curview,$id)]} { + set r $commitrow($curview,$id) if {$l1 <= $r && $r <= $l2} { return [expr {$r - $l1 + 1}] } set kids [lindex $childlist $r] } else { - set kids $children($id) + set kids $children($curview,$id) } foreach c $kids { - set r $commitrow($c) + set r $commitrow($curview,$c) if {$l1 <= $r && $r <= $l2} { return [expr {$r - $l1 + 1}] } @@ -1546,20 +1735,18 @@ proc initlayout {} { global rowidlist rowoffsets displayorder commitlisted global rowlaidout rowoptim global idinlist rowchk rowrangelist idrowranges - global commitidx numcommits canvxmax canv + global numcommits canvxmax canv global nextcolor global parentlist childlist children - global colormap rowtextx commitrow + global colormap rowtextx global linesegends - set commitidx 0 set numcommits 0 set displayorder {} set commitlisted {} set parentlist {} set childlist {} set rowrangelist {} - catch {unset children} set nextcolor 0 set rowidlist {{}} set rowoffsets {{}} @@ -1570,7 +1757,6 @@ proc initlayout {} { set canvxmax [$canv cget -width] catch {unset colormap} catch {unset rowtextx} - catch {unset commitrow} catch {unset idrowranges} set linesegends {} } @@ -1605,10 +1791,10 @@ proc visiblerows {} { proc layoutmore {} { global rowlaidout rowoptim commitidx numcommits optim_delay - global uparrowlen + global uparrowlen curview set row $rowlaidout - set rowlaidout [layoutrows $row $commitidx 0] + set rowlaidout [layoutrows $row $commitidx($curview) 0] set orow [expr {$rowlaidout - $uparrowlen - 1}] if {$orow > $rowoptim} { optimize_rows $rowoptim 0 $orow @@ -1622,7 +1808,7 @@ proc layoutmore {} { proc showstuff {canshow} { global numcommits commitrow pending_select selectedline - global linesegends idrowranges idrangedrawn + global linesegends idrowranges idrangedrawn curview if {$numcommits == 0} { global phase @@ -1657,9 +1843,9 @@ proc showstuff {canshow} { incr row } if {[info exists pending_select] && - [info exists commitrow($pending_select)] && - $commitrow($pending_select) < $numcommits} { - selectline $commitrow($pending_select) 1 + [info exists commitrow($curview,$pending_select)] && + $commitrow($curview,$pending_select) < $numcommits} { + selectline $commitrow($curview,$pending_select) 1 } if {![info exists selectedline] && ![info exists pending_select]} { selectline 0 1 @@ -1671,7 +1857,7 @@ proc layoutrows {row endrow last} { global uparrowlen downarrowlen maxwidth mingaplen global childlist parentlist global idrowranges linesegends - global commitidx + global commitidx curview global idinlist rowchk rowrangelist set idlist [lindex $rowidlist $row] @@ -1691,7 +1877,8 @@ proc layoutrows {row endrow last} { set nev [expr {[llength $idlist] + [llength $newolds] + [llength $oldolds] - $maxwidth + 1}] if {$nev > 0} { - if {!$last && $row + $uparrowlen + $mingaplen >= $commitidx} break + if {!$last && + $row + $uparrowlen + $mingaplen >= $commitidx($curview)} break for {set x [llength $idlist]} {[incr x -1] >= 0} {} { set i [lindex $idlist $x] if {![info exists rowchk($i)] || $row >= $rowchk($i)} { @@ -1780,30 +1967,28 @@ proc layoutrows {row endrow last} { proc addextraid {id row} { global displayorder commitrow commitinfo global commitidx commitlisted - global parentlist childlist children + global parentlist childlist children curview - incr commitidx + incr commitidx($curview) lappend displayorder $id lappend commitlisted 0 lappend parentlist {} - set commitrow($id) $row + set commitrow($curview,$id) $row readcommit $id if {![info exists commitinfo($id)]} { set commitinfo($id) {"No commit information available"} } - if {[info exists children($id)]} { - lappend childlist $children($id) - unset children($id) - } else { - lappend childlist {} + if {![info exists children($curview,$id)]} { + set children($curview,$id) {} } + lappend childlist $children($curview,$id) } proc layouttail {} { - global rowidlist rowoffsets idinlist commitidx + global rowidlist rowoffsets idinlist commitidx curview global idrowranges rowrangelist - set row $commitidx + set row $commitidx($curview) set idlist [lindex $rowidlist $row] while {$idlist ne {}} { set col [expr {[llength $idlist] - 1}] @@ -1978,12 +2163,13 @@ proc linewidth {id} { } proc rowranges {id} { - global phase idrowranges commitrow rowlaidout rowrangelist + global phase idrowranges commitrow rowlaidout rowrangelist curview set ranges {} if {$phase eq {} || - ([info exists commitrow($id)] && $commitrow($id) < $rowlaidout)} { - set ranges [lindex $rowrangelist $commitrow($id)] + ([info exists commitrow($curview,$id)] + && $commitrow($curview,$id) < $rowlaidout)} { + set ranges [lindex $rowrangelist $commitrow($curview,$id)] } elseif {[info exists idrowranges($id)]} { set ranges $idrowranges($id) } @@ -1994,11 +2180,12 @@ proc drawlineseg {id i} { global rowoffsets rowidlist global displayorder global canv colormap linespc - global numcommits commitrow + global numcommits commitrow curview set ranges [rowranges $id] set downarrow 1 - if {[info exists commitrow($id)] && $commitrow($id) < $numcommits} { + if {[info exists commitrow($curview,$id)] + && $commitrow($curview,$id) < $numcommits} { set downarrow [expr {$i < [llength $ranges] / 2 - 1}] } else { set downarrow 1 @@ -2122,7 +2309,7 @@ proc drawparentlinks {id row col olds} { proc drawlines {id} { global colormap canv global idrangedrawn - global childlist iddrawn commitrow rowidlist + global children iddrawn commitrow rowidlist curview $canv delete lines.$id set nr [expr {[llength [rowranges $id]] / 2}] @@ -2131,9 +2318,9 @@ proc drawlines {id} { drawlineseg $id $i } } - foreach child [lindex $childlist $commitrow($id)] { + foreach child $children($curview,$id) { if {[info exists iddrawn($child)]} { - set row $commitrow($child) + set row $commitrow($curview,$child) set col [lsearch -exact [lindex $rowidlist $row] $child] if {$col >= 0} { drawparentlinks $child $row $col [list $id] @@ -2147,7 +2334,8 @@ proc drawcmittext {id row col rmx} { global commitlisted commitinfo rowidlist global rowtextx idpos idtags idheads idotherrefs global linehtag linentag linedtag - global mainfont namefont canvxmax + global mainfont canvxmax + global hlview commitrow highlightedrows set ofill [expr {[lindex $commitlisted $row]? "blue": "white"}] set x [xc $row $col] @@ -2172,11 +2360,16 @@ proc drawcmittext {id row col rmx} { set name [lindex $commitinfo($id) 1] set date [lindex $commitinfo($id) 2] set date [formatdate $date] + set font $mainfont + if {[info exists hlview] && [info exists commitrow($hlview,$id)]} { + lappend font bold + lappend highlightedrows $row + } set linehtag($row) [$canv create text $xt $y -anchor w \ - -text $headline -font $mainfont ] + -text $headline -font $font] $canv bind $linehtag($row) "rowmenu %X %Y $id" set linentag($row) [$canv2 create text 3 $y -anchor w \ - -text $name -font $namefont] + -text $name -font $mainfont] set linedtag($row) [$canv3 create text 3 $y -anchor w \ -text $date -font $mainfont] set xr [expr {$xt + [font measure $mainfont $headline]}] @@ -2307,21 +2500,19 @@ proc findcrossings {id} { proc assigncolor {id} { global colormap colors nextcolor - global commitrow parentlist children childlist + global commitrow parentlist children children curview if {[info exists colormap($id)]} return set ncolors [llength $colors] - if {[info exists commitrow($id)]} { - set kids [lindex $childlist $commitrow($id)] - } elseif {[info exists children($id)]} { - set kids $children($id) + if {[info exists children($curview,$id)]} { + set kids $children($curview,$id) } else { set kids {} } if {[llength $kids] == 1} { set child [lindex $kids 0] if {[info exists colormap($child)] - && [llength [lindex $parentlist $commitrow($child)]] == 1} { + && [llength [lindex $parentlist $commitrow($curview,$child)]] == 1} { set colormap($id) $colormap($child) return } @@ -2349,7 +2540,7 @@ proc assigncolor {id} { && [lsearch -exact $badcolors $colormap($child)] < 0} { lappend badcolors $colormap($child) } - foreach p [lindex $parentlist $commitrow($child)] { + foreach p [lindex $parentlist $commitrow($curview,$child)] { if {[info exists colormap($p)] && [lsearch -exact $badcolors $colormap($p)] < 0} { lappend badcolors $colormap($p) @@ -2382,7 +2573,7 @@ proc bindline {t id} { proc drawtags {id x xt y1} { global idtags idheads idotherrefs global linespc lthickness - global canv mainfont commitrow rowtextx + global canv mainfont commitrow rowtextx curview set marks {} set ntags 0 @@ -2425,7 +2616,7 @@ proc drawtags {id x xt y1} { $xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \ -width 1 -outline black -fill yellow -tags tag.$id] $canv bind $t <1> [list showtag $tag 1] - set rowtextx($commitrow($id)) [expr {$xr + $linespc}] + set rowtextx($commitrow($curview,$id)) [expr {$xr + $linespc}] } else { # draw a head or other ref if {[incr nheads -1] >= 0} { @@ -2466,21 +2657,22 @@ proc xcoord {i level ln} { return $x } +proc show_status {msg} { + global canv mainfont + + clear_display + $canv create text 3 3 -anchor nw -text $msg -font $mainfont -tags textitems +} + proc finishcommits {} { - global commitidx phase + global commitidx phase curview global canv mainfont ctext maincursor textcursor global findinprogress pending_select - if {$commitidx > 0} { + if {$commitidx($curview) > 0} { drawrest } else { - $canv delete all - $canv create text 3 3 -anchor nw -text "No commits selected" \ - -font $mainfont -tags textitems - } - if {![info exists findinprogress]} { - . config -cursor $maincursor - settextcursor $textcursor + show_status "No commits selected" } set phase {} catch {unset pending_select} @@ -2497,18 +2689,38 @@ proc settextcursor {c} { set curtextcursor $c } +proc nowbusy {what} { + global isbusy + + if {[array names isbusy] eq {}} { + . config -cursor watch + settextcursor watch + } + set isbusy($what) 1 +} + +proc notbusy {what} { + global isbusy maincursor textcursor + + catch {unset isbusy($what)} + if {[array names isbusy] eq {}} { + . config -cursor $maincursor + settextcursor $textcursor + } +} + proc drawrest {} { global numcommits global startmsecs global canvy0 numcommits linespc - global rowlaidout commitidx + global rowlaidout commitidx curview global pending_select set row $rowlaidout - layoutrows $rowlaidout $commitidx 1 + layoutrows $rowlaidout $commitidx($curview) 1 layouttail - optimize_rows $row 0 $commitidx - showstuff $commitidx + optimize_rows $row 0 $commitidx($curview) + showstuff $commitidx($curview) if {[info exists pending_select]} { selectline 0 1 } @@ -2540,7 +2752,7 @@ proc findmatches {f} { proc dofind {} { global findtype findloc findstring markedmatches commitinfo global numcommits displayorder linehtag linentag linedtag - global mainfont namefont canv canv2 canv3 selectedline + global mainfont canv canv2 canv3 selectedline global matchinglines foundstring foundstrlen matchstring global commitdata @@ -2601,7 +2813,7 @@ proc dofind {} { markmatches $canv $l $f $linehtag($l) $matches $mainfont } elseif {$ty == "Author"} { drawcmitrow $l - markmatches $canv2 $l $f $linentag($l) $matches $namefont + markmatches $canv2 $l $f $linentag($l) $matches $mainfont } elseif {$ty == "Date"} { drawcmitrow $l markmatches $canv3 $l $f $linedtag($l) $matches $mainfont @@ -2699,13 +2911,8 @@ proc stopfindproc {{done 0}} { catch {close $findprocfile} unset findprocpid } - if {[info exists findinprogress]} { - unset findinprogress - if {$phase eq {}} { - . config -cursor $maincursor - settextcursor $textcursor - } - } + catch {unset findinprogress} + notbusy find } proc findpatches {} { @@ -2745,14 +2952,13 @@ proc findpatches {} { fconfigure $f -blocking 0 fileevent $f readable readfindproc set finddidsel 0 - . config -cursor watch - settextcursor watch + nowbusy find set findinprogress 1 } proc readfindproc {} { global findprocfile finddidsel - global commitrow matchinglines findinsertpos + global commitrow matchinglines findinsertpos curview set n [gets $findprocfile line] if {$n < 0} { @@ -2769,11 +2975,11 @@ proc readfindproc {} { stopfindproc return } - if {![info exists commitrow($id)]} { + if {![info exists commitrow($curview,$id)]} { puts stderr "spurious id: $id" return } - set l $commitrow($id) + set l $commitrow($curview,$id) insertmatch $l $id } @@ -2847,8 +3053,7 @@ proc findfiles {} { set finddidsel 0 set findinsertpos end set id [lindex $displayorder $l] - . config -cursor watch - settextcursor watch + nowbusy find set findinprogress 1 findcont update @@ -3018,7 +3223,7 @@ proc commit_descriptor {p} { # append some text to the ctext widget, and make any SHA1 ID # that we know about be a clickable link. proc appendwithlinks {text} { - global ctext commitrow linknum + global ctext commitrow linknum curview set start [$ctext index "end - 1c"] $ctext insert end $text @@ -3028,11 +3233,12 @@ proc appendwithlinks {text} { set s [lindex $l 0] set e [lindex $l 1] set linkid [string range $text $s $e] - if {![info exists commitrow($linkid)]} continue + if {![info exists commitrow($curview,$linkid)]} continue incr e $ctext tag add link "$start + $s c" "$start + $e c" $ctext tag add link$linknum "$start + $s c" "$start + $e c" - $ctext tag bind link$linknum <1> [list selectline $commitrow($linkid) 1] + $ctext tag bind link$linknum <1> \ + [list selectline $commitrow($curview,$linkid) 1] incr linknum } $ctext tag conf link -foreground blue -underline 1 @@ -3437,8 +3643,6 @@ proc getmergediffline {mdf id np} { # start of a new file $ctext insert end "\n" set here [$ctext index "end - 1c"] - $ctext mark set f:$fname $here - $ctext mark gravity f:$fname left lappend difffilestart $here add_flist [list $fname] set l [expr {(78 - [string length $fname]) / 2}] @@ -3569,6 +3773,19 @@ proc getblobdiffs {ids} { set nextupdate [expr {[clock clicks -milliseconds] + 100}] } +proc setinlist {var i val} { + global $var + + while {[llength [set $var]] < $i} { + lappend $var {} + } + if {[llength [set $var]] == $i} { + lappend $var $val + } else { + lset $var $i $val + } +} + proc getblobdiffline {bdf ids} { global diffids blobdifffd ctext curdifftag curtagstart global diffnexthead diffnextnote difffilestart @@ -3595,12 +3812,15 @@ proc getblobdiffline {bdf ids} { set here [$ctext index "end - 1c"] set curtagstart $here set header $newname - lappend difffilestart $here - $ctext mark set f:$fname $here - $ctext mark gravity f:$fname left - if {$newname != $fname} { - $ctext mark set f:$newfname $here - $ctext mark gravity f:$newfname left + set i [lsearch -exact $treediffs($ids) $fname] + if {$i >= 0} { + setinlist difffilestart $i $here + } + if {$newname ne $fname} { + set i [lsearch -exact $treediffs($ids) $newname] + if {$i >= 0} { + setinlist difffilestart $i $here + } } set curdifftag "f:$fname" $ctext tag delete $curdifftag @@ -3686,11 +3906,10 @@ proc redisplay {} { } proc incrfont {inc} { - global mainfont namefont textfont ctext canv phase + global mainfont textfont ctext canv phase global stopped entries unmarkmatches set mainfont [lreplace $mainfont 1 1 [expr {[lindex $mainfont 1] + $inc}]] - set namefont [lreplace $namefont 1 1 [expr {[lindex $namefont 1] + $inc}]] set textfont [lreplace $textfont 1 1 [expr {[lindex $textfont 1] + $inc}]] setcoords $ctext conf -font $textfont @@ -3729,7 +3948,7 @@ proc sha1change {n1 n2 op} { proc gotocommit {} { global sha1string currentid commitrow tagids headids - global displayorder numcommits + global displayorder numcommits curview if {$sha1string == {} || ([info exists currentid] && $sha1string == $currentid)} return @@ -3755,8 +3974,8 @@ proc gotocommit {} { } } } - if {[info exists commitrow($id)]} { - selectline $commitrow($id) 1 + if {[info exists commitrow($curview,$id)]} { + selectline $commitrow($curview,$id) 1 return } if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} { @@ -3864,7 +4083,7 @@ proc arrowjump {id n y} { } proc lineclick {x y id isnew} { - global ctext commitinfo childlist commitrow canv thickerline + global ctext commitinfo children canv thickerline curview if {![info exists commitinfo($id)] && ![getcommit $id]} return unmarkmatches @@ -3903,7 +4122,7 @@ proc lineclick {x y id isnew} { $ctext insert end "\tAuthor:\t[lindex $info 1]\n" set date [formatdate [lindex $info 2]] $ctext insert end "\tDate:\t$date\n" - set kids [lindex $childlist $commitrow($id)] + set kids $children($curview,$id) if {$kids ne {}} { $ctext insert end "\nChildren:" set i 0 @@ -3934,9 +4153,9 @@ proc normalline {} { } proc selbyid {id} { - global commitrow - if {[info exists commitrow($id)]} { - selectline $commitrow($id) 1 + global commitrow curview + if {[info exists commitrow($curview,$id)]} { + selectline $commitrow($curview,$id) 1 } } @@ -3949,9 +4168,10 @@ proc mstime {} { } proc rowmenu {x y id} { - global rowctxmenu commitrow selectedline rowmenuid + global rowctxmenu commitrow selectedline rowmenuid curview - if {![info exists selectedline] || $commitrow($id) eq $selectedline} { + if {![info exists selectedline] + || $commitrow($curview,$id) eq $selectedline} { set state disabled } else { set state normal @@ -4151,14 +4371,15 @@ proc domktag {} { } proc redrawtags {id} { - global canv linehtag commitrow idpos selectedline + global canv linehtag commitrow idpos selectedline curview - if {![info exists commitrow($id)]} return - drawcmitrow $commitrow($id) + if {![info exists commitrow($curview,$id)]} return + drawcmitrow $commitrow($curview,$id) $canv delete tag.$id set xt [eval drawtags $id $idpos($id)] - $canv coords $linehtag($commitrow($id)) $xt [lindex $idpos($id) 2] - if {[info exists selectedline] && $selectedline == $commitrow($id)} { + $canv coords $linehtag($commitrow($curview,$id)) $xt [lindex $idpos($id) 2] + if {[info exists selectedline] + && $selectedline == $commitrow($curview,$id)} { selectline $selectedline 0 } } @@ -4674,8 +4895,6 @@ set colors {green red blue magenta darkgrey brown orange} catch {source ~/.gitk} -set namefont $mainfont - font create optionfont -family sans-serif -size -12 set revtreeargs {} @@ -4692,10 +4911,33 @@ foreach arg $argv { # check that we can find a .git directory somewhere... set gitdir [gitdir] if {![file isdirectory $gitdir]} { - error_popup "Cannot find the git directory \"$gitdir\"." + show_error . "Cannot find the git directory \"$gitdir\"." exit 1 } +set cmdline_files {} +set i [lsearch -exact $revtreeargs "--"] +if {$i >= 0} { + set cmdline_files [lrange $revtreeargs [expr {$i + 1}] end] + set revtreeargs [lrange $revtreeargs 0 [expr {$i - 1}]] +} elseif {$revtreeargs ne {}} { + if {[catch { + set f [eval exec git-rev-parse --no-revs --no-flags $revtreeargs] + set cmdline_files [split $f "\n"] + set n [llength $cmdline_files] + set revtreeargs [lrange $revtreeargs 0 end-$n] + } err]} { + # unfortunately we get both stdout and stderr in $err, + # so look for "fatal:". + set i [string first "fatal:" $err] + if {$i > 0} { + set err [string range [expr {$i + 6}] end] + } + show_error . "Bad arguments to gitk:\n$err" + exit 1 + } +} + set history {} set historyindex 0 @@ -4704,9 +4946,12 @@ set optim_delay 16 set nextviewnum 1 set curview 0 set selectedview 0 +set selectedhlview {} set viewfiles(0) {} set viewperm(0) 0 +set viewargs(0) {} +set cmdlineok 0 set stopped 0 set stuffsaved 0 set patchnum 0 @@ -4714,27 +4959,16 @@ setcoords makewindow readrefs -set cmdline_files {} -catch { - set fileargs [eval exec git-rev-parse --no-revs --no-flags $revtreeargs] - set cmdline_files [split $fileargs "\n"] - set n [llength $cmdline_files] - set revtreeargs [lrange $revtreeargs 0 end-$n] -} -if {[lindex $revtreeargs end] eq "--"} { - set revtreeargs [lrange $revtreeargs 0 end-1] -} - -if {$cmdline_files ne {}} { +if {$cmdline_files ne {} || $revtreeargs ne {}} { # create a view for the files/dirs specified on the command line set curview 1 set selectedview 1 set nextviewnum 2 set viewname(1) "Command line" set viewfiles(1) $cmdline_files + set viewargs(1) $revtreeargs set viewperm(1) 0 - .bar.view add radiobutton -label $viewname(1) -command {showview 1} \ - -variable selectedview -value 1 + addviewmenu 1 .bar.view entryconf 2 -state normal .bar.view entryconf 3 -state normal } @@ -4745,9 +4979,9 @@ if {[info exists permviews]} { incr nextviewnum set viewname($n) [lindex $v 0] set viewfiles($n) [lindex $v 1] + set viewargs($n) [lindex $v 2] set viewperm($n) 1 - .bar.view add radiobutton -label $viewname($n) \ - -command [list showview $n] -variable selectedview -value $n + addviewmenu $n } } getcommits