@@ -29,7 +29,7 @@ struct TerminalLogger <: AbstractLogger
29
29
right_justify:: Int
30
30
message_limits:: Dict{Any,Int}
31
31
sticky_messages:: StickyMessages
32
- bars :: Dict{Any, ProgressBar}
32
+ bartrees :: Vector{Node{ ProgressBar} }
33
33
end
34
34
function TerminalLogger (stream:: IO = stderr , min_level= ProgressLevel;
35
35
meta_formatter= default_metafmt, show_limited= true ,
@@ -42,7 +42,7 @@ function TerminalLogger(stream::IO=stderr, min_level=ProgressLevel;
42
42
right_justify,
43
43
Dict {Any,Int} (),
44
44
StickyMessages (stream),
45
- Dict {Any,ProgressBar} () ,
45
+ Union{}[] ,
46
46
)
47
47
end
48
48
@@ -104,61 +104,105 @@ function termlength(str)
104
104
return N
105
105
end
106
106
107
- function handle_progress (logger, message, id, progress)
108
- # Don't do anything when it's already done:
109
- if (progress == " done" || progress >= 1 ) && ! haskey (logger. bars, id)
110
- return
107
+ function findbar (bartree, id)
108
+ if ! (bartree isa AbstractArray)
109
+ bartree. data. id === id && return bartree
110
+ end
111
+ for node in bartree
112
+ found = findbar (node, id)
113
+ found === nothing || return found
111
114
end
115
+ return nothing
116
+ end
112
117
113
- try
114
- bar = get! (ProgressBar, logger. bars, id)
118
+ function foldtree (op, acc, tree)
119
+ for node in tree
120
+ acc = foldtree (op, acc, node)
121
+ end
122
+ if ! (tree isa AbstractArray)
123
+ acc = op (acc, tree)
124
+ end
125
+ return acc
126
+ end
115
127
116
- if message == " "
117
- message = " Progress: "
118
- else
119
- message = string (message)
120
- if ! endswith (message, " " )
121
- message *= " "
122
- end
123
- end
128
+ const BAR_MESSAGE_ID = gensym (:BAR_MESSAGE_ID )
124
129
125
- bartxt = sprint (
126
- printprogress,
127
- bar,
128
- message,
129
- progress == " done" ? 1.0 : progress;
130
- context = :displaysize => displaysize (logger. stream),
131
- )
130
+ function handle_progress (logger, progress)
131
+ node = findbar (logger. bartrees, progress. id)
132
+ if node === nothing
133
+ # Don't do anything when it's already done:
134
+ (progress. done || something (progress. fraction, 0.0 ) >= 1 ) && return
132
135
133
- if progress == " done" || progress >= 1
134
- pop! (logger. sticky_messages, id)
135
- printstyled (logger. stream, bartxt; color= :light_black )
136
- println (logger. stream)
136
+ parentnode = findbar (logger. bartrees, progress. parentid)
137
+ bar = ProgressBar (
138
+ fraction = progress. fraction,
139
+ name = progress. name,
140
+ id = progress. id,
141
+ parentid = progress. parentid,
142
+ )
143
+ if parentnode === nothing
144
+ node = Node (bar)
145
+ pushfirst! (logger. bartrees, node)
137
146
else
138
- bartxt = sprint (context = logger. stream) do io
139
- printstyled (io, bartxt; color= :green )
140
- end
141
- push! (logger. sticky_messages, id => bartxt)
147
+ bar. level = parentnode. data. level + 1
148
+ node = addchild (parentnode, bar)
142
149
end
143
- finally
144
- if progress == " done" || progress >= 1
145
- pop! (logger. sticky_messages, id) # redundant (but safe) if no error
146
- pop! (logger. bars, id, nothing )
150
+ else
151
+ bar = node. data
152
+ set_fraction! (bar, progress. fraction)
153
+ if progress. name != " "
154
+ bar. name = progress. name
155
+ end
156
+ node. data = bar
157
+ end
158
+ if progress. done
159
+ if isroot (node)
160
+ deleteat! (logger. bartrees, findfirst (x -> x === node, logger. bartrees))
161
+ else
162
+ prunebranch! (node)
163
+ end
164
+ end
165
+
166
+ bartxt = sprint (context = :displaysize => displaysize (logger. stream)) do io
167
+ foldtree (true , logger. bartrees) do isfirst, node
168
+ isfirst || println (io)
169
+ printprogress (io, node. data)
170
+ false # next `isfirst`
171
+ end
172
+ end
173
+ if isempty (bartxt)
174
+ pop! (logger. sticky_messages, BAR_MESSAGE_ID)
175
+ else
176
+ bartxt = sprint (context = logger. stream) do io
177
+ printstyled (io, bartxt; color= :green )
178
+ end
179
+ push! (logger. sticky_messages, BAR_MESSAGE_ID => bartxt)
180
+ end
181
+
182
+ # "Flushing" non-sticky message should be done after the sticky
183
+ # message is re-drawn:
184
+ if progress. done
185
+ ensure_done! (bar)
186
+ donetxt = sprint (context = :displaysize => displaysize (logger. stream)) do io
187
+ printprogress (io, bar)
147
188
end
189
+ printstyled (logger. stream, donetxt; color= :light_black )
190
+ println (logger. stream)
148
191
end
149
192
end
150
193
151
194
function handle_message (logger:: TerminalLogger , level, message, _module, group, id,
152
- filepath, line; maxlog= nothing , progress = nothing ,
195
+ filepath, line; maxlog= nothing ,
153
196
sticky= nothing , kwargs... )
154
197
if maxlog != = nothing && maxlog isa Integer
155
198
remaining = get! (logger. message_limits, id, maxlog)
156
199
logger. message_limits[id] = remaining - 1
157
200
remaining > 0 || return
158
201
end
159
202
160
- if progress == " done" || progress isa Real
161
- handle_progress (logger, message, id, progress)
203
+ progress = asprogress (level, message, _module, group, id, filepath, line; kwargs... )
204
+ if progress != = nothing
205
+ handle_progress (logger, progress)
162
206
return
163
207
end
164
208
0 commit comments