1
1
"""
2
- TerminalLogger(stream=stderr, min_level=Info ; meta_formatter=default_metafmt,
2
+ TerminalLogger(stream=stderr, min_level=$ProgressLevel ; meta_formatter=default_metafmt,
3
3
show_limited=true, right_justify=0)
4
4
5
5
Logger with formatting optimized for readability in a text console, for example
@@ -28,12 +28,13 @@ struct TerminalLogger <: AbstractLogger
28
28
right_justify:: Int
29
29
message_limits:: Dict{Any,Int}
30
30
sticky_messages:: StickyMessages
31
+ bars:: Dict{Any,Progress}
31
32
end
32
- function TerminalLogger (stream:: IO = stderr , min_level= Info ;
33
+ function TerminalLogger (stream:: IO = stderr , min_level= ProgressLevel ;
33
34
meta_formatter= default_metafmt, show_limited= true ,
34
35
right_justify= 0 )
35
36
TerminalLogger (stream, min_level, meta_formatter,
36
- show_limited, right_justify, Dict {Any,Int} (), StickyMessages (stream))
37
+ show_limited, right_justify, Dict {Any,Int} (), StickyMessages (stream), Dict {Any,Progress} () )
37
38
end
38
39
39
40
shouldlog (logger:: TerminalLogger , level, _module, group, id) =
@@ -94,6 +95,71 @@ function termlength(str)
94
95
return N
95
96
end
96
97
98
+ # Since `ProgressMeter.Progress` requires an integer to update its state,
99
+ # we convert `progress` to `fakecount` by `_progress_count * progress`.
100
+ const _progress_count = 1000
101
+
102
+ function handle_progress (logger, message, id, progress)
103
+ # Don't do anything when it's already done:
104
+ if (progress == " done" || progress >= 1 ) && ! haskey (logger. bars, id)
105
+ return
106
+ end
107
+
108
+ try
109
+ bar = get! (logger. bars, id) do
110
+ Progress (
111
+ _progress_count;
112
+ dt = - 1.0 , # bypass time-based throttling
113
+ output = IOContext (
114
+ IOBuffer (),
115
+ :displaysize => displaysize (logger. stream),
116
+ :color => get (logger. stream, :color , false ),
117
+ ),
118
+ )
119
+ end
120
+ if message != " "
121
+ message = string (message)
122
+ if ! endswith (message, " " )
123
+ message *= " "
124
+ end
125
+ bar. desc = message
126
+ end
127
+
128
+ # Do what `ProgressMeter.tty_width` does:
129
+ # ...length of percentage and ETA string with days is 29 characters
130
+ bar. barlen = max (0 , displaysize (logger. stream)[2 ] - (length (bar. desc) + 29 ))
131
+
132
+ fakecount = if progress == " done" || progress >= 1
133
+ _progress_count
134
+ elseif progress >= 0
135
+ floor (Int, _progress_count * progress)
136
+ else
137
+ 0
138
+ end
139
+ update! (bar, fakecount)
140
+
141
+ # Using `stripg` to get rid of `\r` etc.:
142
+ msg = lstrip (String (take! (bar. output. io)), ' \r ' )
143
+ # Strip off control characters:
144
+ i = findlast (" \e " , msg)
145
+ if i != = nothing
146
+ msg = msg[1 : first (i)- 1 ]
147
+ end
148
+
149
+ if progress == " done" || progress >= 1
150
+ pop! (logger. sticky_messages, id)
151
+ println (logger. stream, msg)
152
+ else
153
+ push! (logger. sticky_messages, id => msg)
154
+ end
155
+ finally
156
+ if progress == " done" || progress >= 1
157
+ pop! (logger. sticky_messages, id) # redundant (but safe) if no error
158
+ pop! (logger. bars, id, nothing )
159
+ end
160
+ end
161
+ end
162
+
97
163
function handle_message (logger:: TerminalLogger , level, message, _module, group, id,
98
164
filepath, line; maxlog= nothing , progress= nothing ,
99
165
sticky= nothing , kwargs... )
@@ -103,6 +169,11 @@ function handle_message(logger::TerminalLogger, level, message, _module, group,
103
169
remaining > 0 || return
104
170
end
105
171
172
+ if progress == " done" || progress isa Real
173
+ handle_progress (logger, message, id, progress)
174
+ return
175
+ end
176
+
106
177
substr (s) = SubString (s, 1 , length (s)) # julia 0.6 compat
107
178
108
179
# Generate a text representation of the message and all key value pairs,
@@ -129,14 +200,6 @@ function handle_message(logger::TerminalLogger, level, message, _module, group,
129
200
end
130
201
end
131
202
132
- if progress != = nothing
133
- if (progress isa Symbol && progress == :done ) || progress == 1
134
- sticky = :done
135
- else
136
- sticky = true
137
- end
138
- end
139
-
140
203
# Format lines as text with appropriate indentation and with a box
141
204
# decoration on the left.
142
205
color,prefix,suffix = logger. meta_formatter (level, _module, group, id, filepath, line)
@@ -162,12 +225,6 @@ function handle_message(logger::TerminalLogger, level, message, _module, group,
162
225
printstyled (iob, prefix, " " , bold= true , color= color)
163
226
end
164
227
print (iob, " " ^ indent, msg)
165
- if i == 1 && progress != = nothing
166
- progress = clamp (convert (Float64, progress), 0.0 , 1.0 )
167
- barfulllen = dsize[2 ] - length (boxstr) - length (prefix) - indent - length (msg) - 2
168
- barlen = round (Int, barfulllen* progress)
169
- print (iob, ' ' , ' =' ^ barlen, ' ' ^ (barfulllen- barlen))
170
- end
171
228
if i == length (msglines) && ! isempty (suffix)
172
229
npad = max (0 , justify_width - nonpadwidth) + minsuffixpad
173
230
print (iob, " " ^ npad)
0 commit comments