git-gui: Add a Tools menu for arbitrary commands.
[git] / lib / tools_dlg.tcl
1 # git-gui Tools menu dialogs
2
3 class tools_add {
4
5 field w              ; # widget path
6 field w_name         ; # new remote name widget
7 field w_cmd          ; # new remote location widget
8
9 field name         {}; # name of the tool
10 field command      {}; # command to execute
11 field add_global    0; # add to the --global config
12 field no_console    0; # disable using the console
13 field needs_file    0; # ensure filename is set
14 field confirm       0; # ask for confirmation
15
16 constructor dialog {} {
17         global repo_config
18
19         make_toplevel top w
20         wm title $top [append "[appname] ([reponame]): " [mc "Add Tool"]]
21         if {$top ne {.}} {
22                 wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
23                 wm transient $top .
24         }
25
26         label $w.header -text [mc "Add New Tool Command"] -font font_uibold
27         pack $w.header -side top -fill x
28
29         frame $w.buttons
30         checkbutton $w.buttons.global \
31                 -text [mc "Add globally"] \
32                 -variable @add_global
33         pack $w.buttons.global -side left -padx 5
34         button $w.buttons.create -text [mc Add] \
35                 -default active \
36                 -command [cb _add]
37         pack $w.buttons.create -side right
38         button $w.buttons.cancel -text [mc Cancel] \
39                 -command [list destroy $w]
40         pack $w.buttons.cancel -side right -padx 5
41         pack $w.buttons -side bottom -fill x -pady 10 -padx 10
42
43         labelframe $w.desc -text [mc "Tool Details"]
44
45         label $w.desc.name_cmnt -anchor w\
46                 -text [mc "Use '/' separators to create a submenu tree:"]
47         grid x $w.desc.name_cmnt -sticky we -padx {0 5} -pady {0 2}
48         label $w.desc.name_l -text [mc "Name:"]
49         set w_name $w.desc.name_t
50         entry $w_name \
51                 -borderwidth 1 \
52                 -relief sunken \
53                 -width 40 \
54                 -textvariable @name \
55                 -validate key \
56                 -validatecommand [cb _validate_name %d %S]
57         grid $w.desc.name_l $w_name -sticky we -padx {0 5}
58
59         label $w.desc.cmd_l -text [mc "Command:"]
60         set w_cmd $w.desc.cmd_t
61         entry $w_cmd \
62                 -borderwidth 1 \
63                 -relief sunken \
64                 -width 40 \
65                 -textvariable @command
66         grid $w.desc.cmd_l $w_cmd -sticky we -padx {0 5} -pady {0 3}
67
68         grid columnconfigure $w.desc 1 -weight 1
69         pack $w.desc -anchor nw -fill x -pady 5 -padx 5
70
71         checkbutton $w.confirm \
72                 -text [mc "Ask for confirmation before running"] \
73                 -variable @confirm
74         pack $w.confirm -anchor w -pady {5 0} -padx 5
75
76         checkbutton $w.noconsole \
77                 -text [mc "Don't show the command output window"] \
78                 -variable @no_console
79         pack $w.noconsole -anchor w -padx 5
80
81         checkbutton $w.needsfile \
82                 -text [mc "Run only if a diff is selected (\$FILENAME not empty)"] \
83                 -variable @needs_file
84         pack $w.needsfile -anchor w -padx 5
85
86         bind $w <Visibility> [cb _visible]
87         bind $w <Key-Escape> [list destroy $w]
88         bind $w <Key-Return> [cb _add]\;break
89         tkwait window $w
90 }
91
92 method _add {} {
93         global repo_config
94
95         if {$name eq {}} {
96                 error_popup [mc "Please supply a name for the tool."]
97                 focus $w_name
98                 return
99         }
100
101         set item "guitool.$name.cmd"
102
103         if {[info exists repo_config($item)]} {
104                 error_popup [mc "Tool '%s' already exists." $name]
105                 focus $w_name
106                 return
107         }
108
109         set cmd [list git config]
110         if {$add_global} { lappend cmd --global }
111         set items {}
112         if {$no_console} { lappend items "guitool.$name.noconsole" }
113         if {$confirm}    { lappend items "guitool.$name.confirm" }
114         if {$needs_file} { lappend items "guitool.$name.needsfile" }
115
116         if {[catch {
117                 eval $cmd [list $item $command]
118                 foreach citem $items { eval $cmd [list $citem yes] }
119             } err]} {
120                 error_popup [mc "Could not add tool:\n%s" $err]
121         } else {
122                 set repo_config($item) $command
123                 foreach citem $items { set repo_config($citem) yes }
124
125                 tools_populate_all
126         }
127
128         destroy $w
129 }
130
131 method _validate_name {d S} {
132         if {$d == 1} {
133                 if {[regexp {[~?*&\[\0\"\\\{]} $S]} {
134                         return 0
135                 }
136         }
137         return 1
138 }
139
140 method _visible {} {
141         grab $w
142         $w_name icursor end
143         focus $w_name
144 }
145
146 }
147
148 class tools_remove {
149
150 field w              ; # widget path
151 field w_names        ; # name list
152
153 constructor dialog {} {
154         global repo_config global_config system_config
155
156         load_config 1
157
158         make_toplevel top w
159         wm title $top [append "[appname] ([reponame]): " [mc "Remove Tool"]]
160         if {$top ne {.}} {
161                 wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
162                 wm transient $top .
163         }
164
165         label $w.header -text [mc "Remove Tool Commands"] -font font_uibold
166         pack $w.header -side top -fill x
167
168         frame $w.buttons
169         button $w.buttons.create -text [mc Remove] \
170                 -default active \
171                 -command [cb _remove]
172         pack $w.buttons.create -side right
173         button $w.buttons.cancel -text [mc Cancel] \
174                 -command [list destroy $w]
175         pack $w.buttons.cancel -side right -padx 5
176         pack $w.buttons -side bottom -fill x -pady 10 -padx 10
177
178         frame $w.list
179         set w_names $w.list.l
180         listbox $w_names \
181                 -height 10 \
182                 -width 30 \
183                 -selectmode extended \
184                 -exportselection false \
185                 -yscrollcommand [list $w.list.sby set]
186         scrollbar $w.list.sby -command [list $w.list.l yview]
187         pack $w.list.sby -side right -fill y
188         pack $w.list.l -side left -fill both -expand 1
189         pack $w.list -fill both -expand 1 -pady 5 -padx 5
190
191         set local_cnt 0
192         foreach fullname [tools_list] {
193                 # Cannot delete system tools
194                 if {[info exists system_config(guitool.$fullname.cmd)]} continue
195
196                 $w_names insert end $fullname
197                 if {![info exists global_config(guitool.$fullname.cmd)]} {
198                         $w_names itemconfigure end -foreground blue
199                         incr local_cnt
200                 }
201         }
202
203         if {$local_cnt > 0} {
204                 label $w.colorlbl -foreground blue \
205                         -text [mc "(Blue denotes repository-local tools)"]
206                 pack $w.colorlbl -fill x -pady 5 -padx 5
207         }
208
209         bind $w <Visibility> [cb _visible]
210         bind $w <Key-Escape> [list destroy $w]
211         bind $w <Key-Return> [cb _remove]\;break
212         tkwait window $w
213 }
214
215 method _remove {} {
216         foreach i [$w_names curselection] {
217                 set name [$w_names get $i]
218
219                 catch { git config --remove-section guitool.$name }
220                 catch { git config --global --remove-section guitool.$name }
221         }
222
223         load_config 0
224         tools_populate_all
225
226         destroy $w
227 }
228
229 method _visible {} {
230         grab $w
231         focus $w_names
232 }
233
234 }