Trac is being migrated to new services! Issues can be found in our new YouTrack instance and WIKI pages can be found on our website.

PurpleCommander: commander.tcl

File commander.tcl, 8.4 KB (added by elb, 16 years ago)

Purple Commander

Line 
1# ChangeLog:
2#
3# 9/13/2007:
4#  Patch from venks on irc.freenode.net to restore puts functionality
5#  in the slave which was lost in a slightly-to-naive alias.
6
7if {[info exists purple::tk_available] && !$purple::tk_available} {
8        purple::notify -error {Purple Commander} {Purple Commander cannot be loaded} \
9                {Purple Commander requires Tk support to load properly.}
10        error {Tk not available}
11}
12
13load {} Tk
14
15proc slave_init { slave pshell } {
16        interp alias $slave purple_puts {} slave_puts $pshell
17        $slave eval {
18                rename ::puts ::purple_orig_puts
19                proc ::puts { args } {
20                        set len [llength $args]
21                        if {$len == 1} {
22                                return [::purple_puts [lindex $args 0]]
23                        } elseif {$len == 2} {
24                                if {[lindex $args 0] == "-nonewline"} {
25                                        return [::purple_puts -nonewline \
26                                                [lindex $args 1]]
27                                } else {
28                                        return [::purple_orig_puts \
29                                                [lindex $args 0] \
30                                                [lindex $args 1]]
31                                }
32                        } else {
33                                return [eval ::purple_orig_puts $args]
34                        }
35                }
36                catch { load {} purple }
37                catch { source "${purple::user_dir}/commanderrc" }
38        }
39}
40
41proc slave_puts { pshell args } {
42        upvar $pshell shell
43        set nonewline 0
44
45        if {[llength $args] < 1} {
46                error "wrong # args: puts ?-nonewline? string"
47        }
48
49        if {[string match [lindex $args 0] "-nonewline"]} {
50                set nonewline 1
51        }
52
53        if {[llength $args] > [expr {1 + $nonewline}]} {
54                error "wrong # args: puts ?-nonewline string"
55        } else {
56                $shell(text) insert end [lindex $args $nonewline] puts
57                if {!$nonewline} {
58                        $shell(text) insert end "\n" puts
59                }
60        }
61}
62
63proc shell_reset { pshell } {
64        upvar $pshell shell
65
66        interp delete $shell(interp)
67        set shell(interp) [interp create]
68        set shell(current) ""
69        set shell(histindex) 1
70        set shell(tmphist) ""
71        $shell(text) delete 0.0 end
72        slave_init $shell(interp) $pshell
73        shell_prompt $pshell
74}
75
76proc shell_create { pshell root } {
77        upvar $pshell shell
78
79        set shell(prompt) "purple] "
80        set shell(continue) "+     "
81        set shell(current) ""
82        set shell(histindex) 1
83        set shell(tmphist) ""
84        set shell(interp) [interp create]
85        frame ${root}.frame
86        set shell(text) [text ${root}.frame.shell -wrap word -background white \
87                -yscrollcommand "${root}.frame.scroll set"]
88        scrollbar ${root}.frame.scroll -command "$shell(text) yview"
89
90        bindtags $shell(text) "$shell(text) Shell Text ShellAfter . all"
91        bind $shell(text) <Return> "shell_return $pshell; break"
92        bind $shell(text) <Control-p> "shell_prevcmd $pshell; break"
93        bind $shell(text) <Control-n> "shell_nextcmd $pshell; break"
94        $shell(text) tag configure error -foreground red
95        $shell(text) tag configure prompt -foreground blue
96        $shell(text) tag configure puts -foreground purple
97        $shell(text) tag configure return -foreground grey
98
99        slave_init $shell(interp) $pshell
100
101        shell_prompt $pshell
102        $shell(text) mark gravity endprompt left
103        $shell(text) mark gravity startcmd left
104
105        pack $shell(text) -fill x -fill y -side left
106        pack ${root}.frame.scroll -fill y -side right
107        pack ${root}.frame
108        focus $shell(text)
109}
110
111proc shell_new { } {
112        global shells
113
114        incr shells
115        set w ".shell$shells"
116        toplevel $w
117        wm title $w "Purple Commander $shells"
118        shell_create "::shell$shells" $w
119}
120
121proc shell_prompt { pshell } {
122        upvar $pshell shell
123
124        $shell(text) insert end $shell(prompt) prompt
125        $shell(text) mark set endprompt insert
126        $shell(text) mark set startcmd endprompt
127}
128
129proc shell_return { pshell } {
130        upvar $pshell shell
131
132        $shell(text) mark set insert end
133        $shell(text) insert end "\n"
134        set shell(current) "$shell(current)[$shell(text) get endprompt end]"
135        if {[info complete $shell(current)]} {
136                exec_command $pshell
137                $shell(text) insert end $shell(prompt) prompt
138                $shell(text) mark set endprompt insert
139                $shell(text) mark set startcmd endprompt
140                set shell(current) ""
141                set shell(histindex) 1
142                set shell(tmphist) ""
143        } else {
144                $shell(text) insert end $shell(continue) prompt
145                $shell(text) mark set endprompt insert
146        }
147        $shell(text) see end
148}
149
150proc shell_prevcmd { pshell } {
151        upvar $pshell shell
152
153        if {$shell(histindex) == 1} {
154                set curcmd [concat $shell(current) [$shell(text) get endprompt end]]
155                set shell(tmphist) $curcmd
156        }
157
158        incr shell(histindex) -1
159        set newcmd [$shell(interp) eval [list history event $shell(histindex)]]
160        if {[string length $newcmd]} {
161                set shell(current) ""
162                $shell(text) delete startcmd end
163                $shell(text) mark set prompt startcmd
164                $shell(text) insert end $newcmd
165        }
166}
167
168proc shell_nextcmd { pshell } {
169        upvar $pshell shell
170
171        if {$shell(histindex) == 1} { return }
172
173        incr shell(histindex)
174        if {$shell(histindex) == 1} {
175                set newcmd $shell(tmphist)
176                set shell(tmphist) ""
177        } else {
178                set newcmd [$shell(interp) eval [list history event $shell(histindex)]]
179        }
180
181        set shell(current) ""
182        $shell(text) delete startcmd end
183        $shell(text) mark set prompt startcmd
184        $shell(text) insert end $newcmd
185}
186
187
188proc exec_command { pshell } {
189        upvar $pshell shell
190
191        if {[string length $shell(current)]} {
192                $shell(interp) eval [list history add $shell(current)]
193                if {[catch { $shell(interp) eval $shell(current) } result]} {
194                        $shell(text) insert end "$result\n" error
195                } elseif {[string length $result]} {
196                        $shell(text) insert end "$result\n" return
197                }
198        }
199}
200
201proc acct_insert { pshell pacct } {
202        upvar $pshell shell
203        upvar $pacct acct
204
205        $shell(text) insert insert [lindex $acct(accounts) [$acct(listbox) index active]]
206}
207
208proc account_dialog { toplevel pshell } {
209        global acct_dialog
210
211        if {[expr {$acct_dialog(posted) != 0}]} {
212                destroy $acct_dialog(toplevel)
213                set acct_dialog(posted) 0
214                set acct_dialog(checkbox) 0
215                return
216        }
217
218        set acct_dialog(toplevel) $toplevel
219        set acct_dialog(accounts) [purple::account list]
220        set acct_dialog(list) {}
221
222        set d [toplevel $toplevel]
223        wm title $d "Accounts"
224        bind $d <Destroy> {
225                global acct_dialog
226                set acct_dialog(posted) 0
227                set acct_dialog(checkbox) 0
228                set acct_dialog(list) {}
229        }
230
231        frame ${d}.top
232        set l [listbox ${d}.top.listbox -foreground grey -background white \
233                -yscrollcommand "${d}.top.listscroll set" -listvar ::acct_dialog(list)]
234        scrollbar ${d}.top.listscroll -command "$l yview"
235
236        set i 0
237        foreach account $acct_dialog(accounts) {
238                set acct_dialog(list) [linsert $acct_dialog(list) $i [purple::account username $account]]
239                if {[purple::account isconnected $account]} {
240                        $l itemconfigure $i -foreground black
241                }
242                incr i
243        }
244
245        bind $l <Double-1> "acct_insert $pshell ::acct_dialog"
246
247        pack $l -side left -expand yes -fill both
248        pack ${d}.top.listscroll -side right -fill y
249        pack ${d}.top
250
251        set acct_dialog(posted) 1
252        set acct_dialog(checkbox) 1
253        set acct_dialog(listbox) $l
254}
255
256bind Shell <BackSpace> {
257        if [%W compare insert <= endprompt] {
258                break
259        }
260}
261bind Shell <Key> {
262        if [%W compare insert < endprompt] {
263                %W mark set insert end
264        }
265}
266bind Shell <Control-u> { %W delete endprompt end; break }
267bind ShellAfter <Key> {
268        if [%W compare insert < endprompt] {
269                %W mark set insert endprompt
270        }
271}
272
273set acct_dialog(posted) 0
274set shells 1
275
276menu .menu -type menubar -tearoff no -borderwidth 0
277menu .menu.commander -tearoff no
278.menu.commander add command -label New -command { shell_new }
279.menu.commander add command -label Reset -command { shell_reset ::shell }
280.menu.commander add separator
281.menu.commander add command -label Unload -command { purple::unload }
282.menu add cascade -menu .menu.commander -label Commander
283menu .menu.dialogs -tearoff no
284.menu.dialogs add check -label Accounts -command { account_dialog .acctdialog ::shell } -variable acct_dialog(checkbox)
285.menu add cascade -menu .menu.dialogs -label Dialogs
286. configure -menu .menu
287
288shell_create ::shell {}
289
290if {[info exists purple::version]} {
291        purple::signal connect [purple::connection handle] signed-on { gc } {
292                global acct_dialog
293
294                if {!$acct_dialog(posted)} { return }
295
296                set account [lsearch -exact $acct_dialog(accounts) [purple::connection account $gc]]
297                $acct_dialog(listbox) itemconfigure $account -foreground black
298        }
299        purple::signal connect [purple::connection handle] signing-off { gc } {
300                global acct_dialog
301               
302                if {!$acct_dialog(posted)} { return }
303
304                set account [lsearch -exact $acct_dialog(accounts) [purple::connection account $gc]]
305                $acct_dialog(listbox) itemconfigure $account -foreground grey
306        }
307}
308
309wm title . "Purple Commander"
310wm deiconify .
311
312proc plugin_init { } {
313        list "Purple Commander" \
314             "$purple::version" \
315             "An interactive Tcl interpreter" \
316             "Purple Commander provides an interactive command interpreter for the Purple Tcl programming interface.  Among other things, it can be used to load and debug Purple Tcl scripts on the fly." \
317             "Ethan Blanton <elb@pidgin.im>" \
318             "http://www.pidgin.im/"
319}
All information, including names and email addresses, entered onto this website or sent to mailing lists affiliated with this website will be public. Do not post confidential information, especially passwords!