File: debug.tcl

package info (click to toggle)
tkabber-plugins 1.1.2%2B20170328-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 5,392 kB
  • sloc: tcl: 27,289; xml: 2,313; makefile: 83; sh: 21
file content (384 lines) | stat: -rw-r--r-- 11,607 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
# debug.tcl --
#
#       This file implements Debug plugin for the Tkabber XMPP client.
#       It allows one to log Tkabber debug messages into a file or a
#       log window.
#
# Author: Marshall T. Rose
# Modifications: Badlop
# Modifications: Sergei Golovan

package require msgcat
catch {package require Tclx}

namespace eval debug {
    ::msgcat::mcload [file join [file dirname [info script]] msgs]

    if {![::plugins::is_registered debug]} {
        ::plugins::register debug \
                            -namespace [namespace current] \
                            -source [info script] \
                            -description [::msgcat::mc "Whether the Debug live\
                                                        plugin is loaded."] \
                            -loadcommand [namespace code load] \
                            -unloadcommand [namespace code unload]
        return
    }

    custom::defgroup Plugins [::msgcat::mc "Plugins options."] \
        -group Tkabber

    custom::defgroup Debug [::msgcat::mc "Debug live plugin options."] \
        -group Plugins

    custom::defvar options(log_to_file) 0 \
        [::msgcat::mc "Log debug messages to file %s." \
                      [file join $::configdir tkabber.log]] \
        -group Debug \
        -type boolean

    custom::defvar options(log_to_window) 0 \
        [::msgcat::mc "Log debug messages to a separate tab/window."] \
        -group Debug \
        -type boolean

    variable modules   {attline
                        avatar
                        browser
                        browseurl
                        caps
                        chat
                        conference
                        custom
                        disco
                        emoticons
                        filetransfer
                        filters
                        georoster
                        gpg
                        headlines
                        hook
                        http
                        iface
                        iq
                        jidlink
                        logger
                        login
                        message
                        mucignore
                        negotiate
                        nick
                        otr
                        pconnect::https
                        pconnect::socks4
                        pconnect::socks5
                        pep
                        plugins
                        popupmenu
                        presence
                        privacy
                        pubsub
                        register
                        richtext
                        roster
                        search
                        si
                        ssj
                        sw
                        tclchat
                        tkabber
                        userinfo
                        utils
                        warning
                        xmpp
                        xmpp::transport::bosh
                        xmpp::transport::poll
                        zerobot}

    foreach module $modules {
        custom::defvar debug($module) 0 \
            [::msgcat::mc "Log debug messages for module %s to a tab/window." \
                          $module] \
            -group Debug -type boolean
    }
}

proc debug::load {} {
    if {[llength [info procs ::debugmsg:debug]] == 0} {
        rename ::debugmsg ::debugmsg:debug
        proc ::debugmsg {module msg} \
             "[namespace current]::debugmsg \$module \$msg"
    }

    foreach ns {otr
                pconnect::https
                pconnect::socks4
                pconnect::socks5
                xmpp
                xmpp::transport::bosh
                xmpp::transport::poll} {
        if {[llength [info procs ::${ns}::Debug]] > 0 && \
                [llength [info procs ::${ns}::Debug:debug]] == 0} {
            rename ::${ns}::Debug ::${ns}::Debug:debug
            proc ::${ns}::Debug {xlib level str} \
                 "[namespace current]::debugmsg $ns \"\$xlib \$str\""
        }
    }

    foreach ns {gpg} {
        if {[llength [info procs ::${ns}::Debug]] > 0 && \
                [llength [info procs ::${ns}::Debug:debug]] == 0} {
            rename ::${ns}::Debug ::${ns}::Debug:debug
            proc ::${ns}::Debug {level str} \
                 "[namespace current]::debugmsg $ns \"\$str\""
        }
    }

    if {[llength [info procs ::otr::smp::Debug]] > 0 && \
            [llength [info procs ::otr::smp::Debug:debug]] == 0} {
        rename ::otr::smp::Debug ::otr::smp::Debug:debug
        proc ::otr::smp::Debug {level str} \
             "[namespace current]::debugmsg otr \$str"
    }

    hook::add finload_hook [namespace current]::setup_menu

    if {![catch {.mainframe getmenu debug}]} {
        setup_menu
    }
}

proc debug::unload {} {
    variable debug_fd

    if {![catch {.mainframe getmenu debug}]} {
        destroy_menu
    }

    if {[info exists debug_fd]} {
        close $debug_fd
        unset debug_fd
    }

    if {[winfo exists .debug]} {
        destroy_win .debug
    }

    hook::remove finload_hook [namespace current]::setup_menu

    foreach ns {gpg
                otr
                pconnect::https
                pconnect::socks4
                pconnect::socks5
                xmpp
                xmpp::transport::bosh
                xmpp::transport::poll} {
        if {[llength [info procs ::${ns}::Debug:debug]] > 0} {
            rename ::${ns}::Debug ""
            rename ::${ns}::Debug:debug ::${ns}::Debug
        }
    }

    if {[llength [info procs ::otr::smp::Debug:debug]] > 0} {
        rename ::otr::smp::Debug ""
        rename ::otr::smp::Debug:debug ::otr::smp::Debug
    }

    if {[llength [info procs ::debugmsg:debug]] > 0} {
        rename ::debugmsg ""
        rename ::debugmsg:debug ::debugmsg
    }

    namespace delete [namespace current]::search
}

proc debug::destroy_menu {} {
    set m [.mainframe getmenu debug]

    if {![catch {$m index [::msgcat::mc "Debug"]} idx] && \
            ![string equal $idx none]} {
        set mm [$m entrycget $idx -menu]
        $m delete $idx
        destroy $mm
    }

    if {![catch {$m index [::msgcat::mc "Profile on"]} idx] && \
            ![string equal $idx none]} {
        $m delete $idx
    }

    if {![catch {$m index [::msgcat::mc "Profile report"]} idx] && \
            ![string equal $idx none]} {
        $m delete $idx
    }
}

proc debug::setup_menu {} {
    variable options
    variable modules
    variable debug

    set m [.mainframe getmenu debug]

    if {![catch {$m index [::msgcat::mc "Debug"]} idx] && \
            ![string equal $idx none]} {
        return
    }

    set buttons [menu $m.devel -tearoff $ifacetk::options(show_tearoffs)]

    $buttons add checkbutton -label [::msgcat::mc "Log to file"] \
        -variable [namespace current]::options(log_to_file)
    $buttons add checkbutton -label [::msgcat::mc "Log to window"] \
        -variable [namespace current]::options(log_to_window)

    $buttons add separator

    set n 0
    foreach module $modules {
        if {$n == 0} {
            set submodules [list $module]
        } else {
            lappend submodules $module
        }
        incr n
        if {$n == 8 || $module == [lindex $modules end]} {
            set n 0
            set me [menu $buttons.[string map {:: #} [lindex $submodules 0]] \
                         -tearoff $::ifacetk::options(show_tearoffs)]
            $buttons add cascade \
                     -label [lindex $submodules 0]-[lindex $submodules end] \
                     -menu $me
            foreach mod $submodules {
                $me add checkbutton -label $mod \
                    -variable [namespace current]::debug($mod)
            }
        }
    }

    $m add cascade -label [::msgcat::mc "Debug"] -menu $buttons

    if {[llength [info commands profile]] > 0} {
        $m add command -label [::msgcat::mc "Profile on"] \
           -command {
                profile -commands -eval on
            }
        $m add command -label [::msgcat::mc "Profile report"] \
           -command {
                profile off profil
                profrep profil real profresults
            }
    }
}

proc debug::debugmsg {module msg} {
    variable options
    variable debug
    variable debug_fd

    if {$options(log_to_file)} {
        if {![info exists debug_fd]} {
            catch { file rename -force -- $::configdir/tkabber.log \
                                          $::configdir/tkabber0.log }
            set debug_fd [open $::configdir/tkabber.log w]
            fconfigure $debug_fd -buffering line
        }

        puts $debug_fd [format "%s %-12.12s %s %s" \
                            [clock format [clock seconds] -format "%m/%d %T"] \
                            $module [lindex [info level -2] 0] $msg]
    }

    if {!$options(log_to_window) || ![info exists debug($module)] || \
            !$debug($module)} {
        return
    }

    set dw .debug

    if {![winfo exists $dw]} {
        if {[catch {
                add_win $dw \
                    -title [::msgcat::mc Debug] \
                    -tabtitle [::msgcat::mc Debug] \
                    -class Chat \
                    -raisecmd [list [namespace current]::focus_body $dw]
            }]} {
            # Main window isn't created yet
            return
        }

        [ScrolledWindow $dw.sw] setwidget \
            [Text $dw.body -yscrollcommand [list $dw.scroll set] \
                 -state disabled -takefocus 1]
        bind [Wrapped $dw.body] <1> [list [namespace current]::focus_body \
                                          [double% $dw]]

        pack $dw.sw -side bottom -fill both -expand yes

        $dw.body tag configure module \
            -foreground [option get $dw theyforeground Chat]
        $dw.body tag configure proc   \
            -foreground [option get $dw meforeground Chat]
        $dw.body tag configure error  \
            -foreground [option get $dw errforeground Chat]

        search::setup_panel $dw
    }

    $dw.body configure -state normal

    set scroll [expr {[lindex [$dw.body yview] 1] == 1}]

    $dw.body insert end \
             [format "%s: %-12.12s" \
                     [clock format [clock seconds] -format "%m/%d %T"] \
                     $module] module " "
    set tag normal

    $dw.body insert end [lindex [info level -2] 0] proc " "

    $dw.body insert end [string trimright $msg] $tag
    $dw.body insert end "\n\n"

    if {$scroll} {
        $dw.body see end
    }

    $dw.body configure -state disabled
}

proc debug::focus_body {w} {
    focus [Wrapped $w.body]
}

namespace eval debug::search {}

proc debug::search::open_panel {w sf} {
    pack $sf -side bottom -anchor w -fill x -before $w.sw
    update idletasks
    $w.body see end
}

proc debug::search::close_panel {w sf} {
    $w.body tag remove search_highlight 0.0 end
    pack forget $sf
    [namespace parent]::focus_body $w
}

proc debug::search::setup_panel {w} {
    set body $w.body

    $body mark set sel_start end
    $body mark set sel_end 0.0

    set sf [plugins::search::spanel [winfo parent $body].search \
                -searchcommand [list ::plugins::search::do_text_search $body] \
                -closecommand [list [namespace current]::close_panel $w]]

    bind [Wrapped $body] <<OpenSearchPanel>> \
         [double% [list [namespace current]::open_panel $w $sf]]
}

# vim:ts=8:sw=4:sts=4:et