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