1# git-gui console support 2# Copyright (C) 2006, 2007 Shawn Pearce 3 4class console { 5 6field t_short 7field t_long 8field w 9field w_t 10field console_cr 11field is_toplevel 1; # are we our own window? 12 13constructor new {short_title long_title} { 14 set t_short $short_title 15 set t_long $long_title 16 _init $this 17 return $this 18} 19 20constructor embed {path title} { 21 set t_short {} 22 set t_long $title 23 set w $path 24 set is_toplevel 0 25 _init $this 26 return $this 27} 28 29method _init {} { 30 global M1B use_ttk NS 31 32 if {$is_toplevel} { 33 make_dialog top w -autodelete 0 34 wm title $top "[appname] ([reponame]): $t_short" 35 } else { 36 ${NS}::frame $w 37 } 38 39 set console_cr 1.0 40 set w_t $w.m.t 41 42 ${NS}::frame $w.m 43 ${NS}::label $w.m.l1 \ 44 -textvariable @t_long \ 45 -anchor w \ 46 -justify left \ 47 -font font_uibold 48 text $w_t \ 49 -background white \ 50 -foreground black \ 51 -borderwidth 1 \ 52 -relief sunken \ 53 -width 80 -height 10 \ 54 -wrap none \ 55 -font font_diff \ 56 -state disabled \ 57 -xscrollcommand [cb _sb_set $w.m.sbx h] \ 58 -yscrollcommand [cb _sb_set $w.m.sby v] 59 label $w.m.s -text [mc "Working... please wait..."] \ 60 -anchor w \ 61 -justify left \ 62 -font font_uibold 63 pack $w.m.l1 -side top -fill x 64 pack $w.m.s -side bottom -fill x 65 pack $w_t -side left -fill both -expand 1 66 pack $w.m -side top -fill both -expand 1 -padx 5 -pady 10 67 68 menu $w.ctxm -tearoff 0 69 $w.ctxm add command -label [mc "Copy"] \ 70 -command "tk_textCopy $w_t" 71 $w.ctxm add command -label [mc "Select All"] \ 72 -command "focus $w_t;$w_t tag add sel 0.0 end" 73 $w.ctxm add command -label [mc "Copy All"] \ 74 -command " 75 $w_t tag add sel 0.0 end 76 tk_textCopy $w_t 77 $w_t tag remove sel 0.0 end 78 " 79 80 if {$is_toplevel} { 81 ${NS}::button $w.ok -text [mc "Close"] \ 82 -state disabled \ 83 -command [list destroy $w] 84 pack $w.ok -side bottom -anchor e -pady 10 -padx 10 85 bind $w <Visibility> [list focus $w] 86 } 87 88 bind_button3 $w_t "tk_popup $w.ctxm %X %Y" 89 bind $w_t <$M1B-Key-a> "$w_t tag add sel 0.0 end;break" 90 bind $w_t <$M1B-Key-A> "$w_t tag add sel 0.0 end;break" 91} 92 93method exec {cmd {after {}}} { 94 if {[lindex $cmd 0] eq {git}} { 95 set fd_f [eval git_read --stderr [lrange $cmd 1 end]] 96 } else { 97 lappend cmd 2>@1 98 set fd_f [_open_stdout_stderr $cmd] 99 } 100 fconfigure $fd_f -blocking 0 -translation binary 101 fileevent $fd_f readable [cb _read $fd_f $after] 102} 103 104method _read {fd after} { 105 set buf [read $fd] 106 if {$buf ne {}} { 107 if {![winfo exists $w_t]} {_init $this} 108 $w_t conf -state normal 109 set c 0 110 set n [string length $buf] 111 while {$c < $n} { 112 set cr [string first "\r" $buf $c] 113 set lf [string first "\n" $buf $c] 114 if {$cr < 0} {set cr [expr {$n + 1}]} 115 if {$lf < 0} {set lf [expr {$n + 1}]} 116 117 if {$lf < $cr} { 118 $w_t insert end [string range $buf $c $lf] 119 set console_cr [$w_t index {end -1c}] 120 set c $lf 121 incr c 122 } else { 123 $w_t delete $console_cr end 124 $w_t insert end "\n" 125 $w_t insert end [string range $buf $c [expr {$cr - 1}]] 126 set c $cr 127 incr c 128 } 129 } 130 $w_t conf -state disabled 131 $w_t see end 132 } 133 134 fconfigure $fd -blocking 1 135 if {[eof $fd]} { 136 if {[catch {close $fd}]} { 137 set ok 0 138 } else { 139 set ok 1 140 } 141 if {$after ne {}} { 142 uplevel #0 $after $ok 143 } else { 144 done $this $ok 145 } 146 return 147 } 148 fconfigure $fd -blocking 0 149} 150 151method chain {cmdlist {ok 1}} { 152 if {$ok} { 153 if {[llength $cmdlist] == 0} { 154 done $this $ok 155 return 156 } 157 158 set cmd [lindex $cmdlist 0] 159 set cmdlist [lrange $cmdlist 1 end] 160 161 if {[lindex $cmd 0] eq {exec}} { 162 exec $this \ 163 [lrange $cmd 1 end] \ 164 [cb chain $cmdlist] 165 } else { 166 uplevel #0 $cmd [cb chain $cmdlist] 167 } 168 } else { 169 done $this $ok 170 } 171} 172 173method insert {txt} { 174 if {![winfo exists $w_t]} {_init $this} 175 $w_t conf -state normal 176 $w_t insert end "$txt\n" 177 set console_cr [$w_t index {end -1c}] 178 $w_t conf -state disabled 179} 180 181method done {ok} { 182 if {$ok} { 183 if {[winfo exists $w.m.s]} { 184 bind $w.m.s <Destroy> [list delete_this $this] 185 $w.m.s conf -background green -foreground black \ 186 -text [mc "Success"] 187 if {$is_toplevel} { 188 $w.ok conf -state normal 189 focus $w.ok 190 } 191 } else { 192 delete_this 193 } 194 } else { 195 if {![winfo exists $w.m.s]} { 196 _init $this 197 } 198 bind $w.m.s <Destroy> [list delete_this $this] 199 $w.m.s conf -background red -foreground black \ 200 -text [mc "Error: Command Failed"] 201 if {$is_toplevel} { 202 $w.ok conf -state normal 203 focus $w.ok 204 } 205 } 206 207 bind $w <Key-Escape> "destroy $w;break" 208} 209 210method _sb_set {sb orient first last} { 211 global NS 212 if {![winfo exists $sb]} { 213 if {$first == $last || ($first == 0 && $last == 1)} return 214 if {$orient eq {h}} { 215 ${NS}::scrollbar $sb -orient h -command [list $w_t xview] 216 pack $sb -fill x -side bottom -before $w_t 217 } else { 218 ${NS}::scrollbar $sb -orient v -command [list $w_t yview] 219 pack $sb -fill y -side right -before $w_t 220 } 221 } 222 $sb set $first $last 223} 224 225} 226