summaryrefslogtreecommitdiffstats
path: root/tcllib/support/devel/sak/util/feedback.tcl
blob: 557ea502405adbac02d5b278509ac50fbcab5e74 (plain)
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
# -*- tcl -*-
# (C) 2008 Andreas Kupries <andreas_kupries@users.sourceforge.net>
##
# ###

# Feedback modes
#
# [short]   Animated short feedback on stdout, no logging
# [log]     Animated short feedback on stdout, logging to multiple files.
# [verbose] Logging to stdout
#
# Output commands for various destinations:
#
# <v> Verbose Log
# <s> Short Log
#
# Handling of the destinations per mode
#
#           <s>        <v>
# [short]   stdout,    /dev/null
# [log]     stdout,    file
# [verbose] /dev/null, stdout

# Log files for different things are opened on demand, i.e. on the
# first write to them. We can configure (per possible log) a string to
# be written before the first write. Reconfiguring that string for a
# log clears the flag for that log and causes the string to be
# rewritten on the next write.

package require sak::animate

namespace eval ::sak::feedback {
    namespace import ::sak::animate::next ; rename next aNext
    namespace import ::sak::animate::last ; rename last aLast
}

# ###

proc ::sak::feedback::init {mode stem} {
    variable  prefix  ""
    variable  short   [expr {$mode ne "verbose"}]
    variable  verbose [expr {$mode ne "short"}]
    variable  tofile  [expr {$mode eq "log"}]
    variable  lstem   $stem
    variable  dst     ""
    variable  lfirst
    unset     lfirst
    array set lfirst {}
    # Note: lchan is _not_ reset. We keep channels, allowing us to
    #       merge output from different modules, if they are run as
    #       one unit (Example: validate and its various parts, which
    #       can be run separately, and together).
    return
}

proc ::sak::feedback::first {dst string} {
    variable lfirst
    set lfirst($dst) $string
    return
}

###

proc ::sak::feedback::summary {text} {
    #=|  $text
    #log $text

    variable short
    variable verbose
    if {$short}   { puts                $text }
    if {$verbose} { puts [_channel log] $text }
    return
}


proc ::sak::feedback::log {text {ext log}} {
    variable verbose
    if {!$verbose} return
    set    c [_channel $ext]
    puts  $c $text
    flush $c
    return
}

###

proc ::sak::feedback::! {} {
    variable short
    if {!$short} return
    variable prefix ""
    sak::animate::init
    return
}

proc ::sak::feedback::+= {string} {
    variable short
    if {!$short} return
    variable prefix
    append   prefix " " $string
    aNext               $prefix
    return
}

proc ::sak::feedback::= {string} {
    variable short
    if {!$short} return
    variable prefix
    aNext  "$prefix $string"
    return
}

proc ::sak::feedback::=| {string} {
    variable short
    if {!$short} return

    variable prefix
    aLast  "$prefix $string"

    variable verbose
    if {$verbose} {
	variable dst
	if {[string length $dst]} {
	    # inlined 'log'
	    set    c [_channel $dst]
	    puts  $c "$prefix $string"
	    flush $c
	    set dst ""
	}
    }

    set prefix ""
    return
}

proc ::sak::feedback::>> {string} {
    variable dst $string
    return
}

# ###

proc ::sak::feedback::_channel {dst} {
    variable tofile
    if {!$tofile} { return stdout }
    variable lchan
    if {[info exists lchan($dst)]} {
	set c $lchan($dst)
    } else {
	variable lstem
	set c [open ${lstem}.$dst w]
	set lchan($dst) $c
    }
    variable lfirst
    if {[info exists lfirst($dst)]} {
	puts $c $lfirst($dst)
	unset lfirst($dst)
    }
    return $c
}

# ###

namespace eval ::sak::feedback {
    namespace export >> ! += = =| init log summary

    variable  dst      ""
    variable  prefix   ""
    variable  short    ""
    variable  verbose  ""
    variable  tofile   ""
    variable  lstem    ""
    variable  lchan
    array set lchan {}

    variable  lfirst
    array set lfirst {}
}

##
# ###

package provide sak::feedback 1.0