@@ -167,6 +167,27 @@ def format_meter(n, total, elapsed, ncols=None, prefix='',
167167 -------
168168 out : Formatted meter and stats, ready to display.
169169 """
170+
171+ def extract_symbols (s , start_tag , end_tag ):
172+ """
173+ Extract custom symbols enclosed by tags, with the first character being the separator.
174+ Eg, extract_symbols('before{start},1,2,3,4,#{end}after', '{start}', '{end}')
175+
176+ Returns
177+ -------
178+ out, out2 : list of symbols, input string without tagged part
179+ """
180+ start = s .find (start_tag )
181+ start_content = start + len (start_tag )
182+ end_content = s .find (end_tag )
183+ end = end_content + len (end_tag )
184+
185+ sep = s [start_content :start_content + 1 ]
186+ return s [start_content + 1 :end_content ].split (sep ), s [:start ] + s [end :]
187+
188+ # Custom symbols variables
189+ c_symbols = None
190+ looping = False
170191
171192 # sanity check: total
172193 if total and n > total :
@@ -235,6 +256,22 @@ def format_meter(n, total, elapsed, ncols=None, prefix='',
235256 # 'bar': full_bar # replaced by procedure below
236257 }
237258
259+ # Custom symbols extraction
260+ for tag in ['bar_symbols' , 'bar_symbols_ascii' , 'bar_symbols_loop' , 'bar_symbols_loop_ascii' ]:
261+ start_tag = '{' + tag + '}'
262+ end_tag = '{/' + tag + '}'
263+ # Check if tag is found in the template
264+ if start_tag in bar_format and end_tag in bar_format :
265+ # Get ascii symbols if ascii env, else unicode
266+ if (ascii and 'ascii' in tag ) or (not ascii and not 'ascii' in tag ):
267+ c_symbols , bar_format = extract_symbols (bar_format , start_tag , end_tag )
268+ # Looping symbol?
269+ if 'loop' in tag :
270+ looping = True
271+ # Need to clean all tags from template
272+ else :
273+ _ , bar_format = extract_symbols (bar_format , start_tag , end_tag )
274+
238275 # Interpolate supplied bar format with the dict
239276 if '{bar}' in bar_format :
240277 # Format left/right sides of the bar, and format the bar
@@ -251,15 +288,40 @@ def format_meter(n, total, elapsed, ncols=None, prefix='',
251288 N_BARS = max (1 , ncols - len (l_bar ) - len (r_bar )) if ncols \
252289 else 10
253290
254- # format bar depending on availability of unicode/ascii chars
255- if ascii :
291+ # custom symbols format
292+ # need to provide both ascii and unicode versions of custom symbols,
293+ # eg, if ascii env but user provided only unicode symbols, then
294+ # will revert to default ascii bar.
295+ if c_symbols :
296+ # looping symbols: just update the symbol animation at each iteration
297+ if looping :
298+ # increment one step in the animation at each step
299+ bar = c_symbols [divmod (n , len (c_symbols ))[1 ]]
300+ frac_bar = ''
301+
302+ bar_length = N_BARS # avoid the filling
303+ frac_bar_length = len (frac_bar )
304+ # normal progress symbols
305+ else :
306+ bar_length , frac_bar_length = divmod (
307+ int (frac * N_BARS * len (c_symbols )), len (c_symbols ))
308+
309+ bar = c_symbols [- 1 ] * bar_length # last symbol is always the filler
310+ frac_bar = c_symbols [frac_bar_length ] if frac_bar_length \
311+ else ' '
312+
313+ # ascii format
314+ elif ascii :
315+ # get the remainder of the division of current fraction with number of symbols
316+ # this will tell us which symbol we should pick
256317 bar_length , frac_bar_length = divmod (
257318 int (frac * N_BARS * 10 ), 10 )
258319
259320 bar = '#' * bar_length
260321 frac_bar = chr (48 + frac_bar_length ) if frac_bar_length \
261322 else ' '
262323
324+ # unicode format (if available)
263325 else :
264326 bar_length , frac_bar_length = divmod (int (frac * N_BARS * 8 ), 8 )
265327
0 commit comments