33Each progress bar consists of a list of these formatters. 
44""" 
55import  datetime 
6+ import  math 
67import  time 
78from  abc  import  ABCMeta , abstractmethod 
89from  typing  import  TYPE_CHECKING , List , Tuple 
1213 AnyFormattedText ,
1314 StyleAndTextTuples ,
1415 to_formatted_text ,
16+  merge_formatted_text ,
1517)
1618from  prompt_toolkit .formatted_text .utils  import  fragment_list_width 
17- from  prompt_toolkit .layout .dimension  import  AnyDimension , D 
19+ from  prompt_toolkit .layout .dimension  import  AnyDimension , D ,  to_dimension 
1820from  prompt_toolkit .layout .utils  import  explode_text_fragments 
1921from  prompt_toolkit .utils  import  get_cwidth 
2022
2729 "Label" ,
2830 "Percentage" ,
2931 "Bar" ,
32+  "Total" ,
33+  "Counter" ,
3034 "Progress" ,
3135 "TimeElapsed" ,
3236 "TimeLeft" ,
@@ -211,12 +215,65 @@ def get_width(self, progress_bar: "ProgressBar") -> AnyDimension:
211215 return  D (min = 9 )
212216
213217
214- class  Progress (Formatter ):
218+ class  Total (Formatter ):
219+  """ 
220+  Display the total items to compete as text. E.g. "20" 
221+  """ 
222+ 
223+  template  =  "<total>{{total:>{digits}}}</total>" 
224+ 
225+  def  _get_digits (self , n : int ) ->  int :
226+  return  int (math .log10 (n )) +  1 
227+ 
228+  def  format (
229+  self ,
230+  progress_bar : "ProgressBar" ,
231+  progress : "ProgressBarCounter[object]" ,
232+  width : int ,
233+  ) ->  AnyFormattedText :
234+ 
235+  return  (
236+  HTML (self .template )
237+  .format (digits = self ._get_digits (progress .total  or  0 ))
238+  .format (total = progress .total  or  "?" )
239+  )
240+ 
241+  def  get_width (self , progress_bar : "ProgressBar" ) ->  AnyDimension :
242+  biggest  =  max (c .total  or  0  for  c  in  progress_bar .counters )
243+  return  D .exact (self ._get_digits (biggest ))
244+ 
245+ 
246+ class  Counter (Total ):
247+  """ 
248+  Display the items competed as text. E.g. "8" 
249+  """ 
250+ 
251+  template  =  "<current>{{current:>{digits}}}</current>" 
252+ 
253+  def  format (
254+  self ,
255+  progress_bar : "ProgressBar" ,
256+  progress : "ProgressBarCounter[object]" ,
257+  width : int ,
258+  ) ->  AnyFormattedText :
259+ 
260+  current  =  progress .items_completed 
261+  digits  =  self ._get_digits (progress .total  or  current )
262+  return  HTML (self .template ).format (digits = digits ).format (current = current )
263+ 
264+  def  get_width (self , progress_bar : "ProgressBar" ) ->  AnyDimension :
265+  biggest  =  max (c .total  or  c .items_completed  for  c  in  progress_bar .counters )
266+  return  D .exact (self ._get_digits (biggest ))
267+ 
268+ 
269+ class  Progress (Counter ):
215270 """ 
216271 Display the progress as text. E.g. "8/20" 
217272 """ 
218273
219-  template  =  "<current>{current:>3}</current>/<total>{total:>3}</total>" 
274+  template  =  (
275+  "<current>{{current:>{digits}}}</current>/<total>{{total:>{digits}}}</total>" 
276+  )
220277
221278 def  format (
222279 self ,
@@ -225,16 +282,18 @@ def format(
225282 width : int ,
226283 ) ->  AnyFormattedText :
227284
228-  return  HTML (self .template ).format (
229-  current = progress .items_completed , total = progress .total  or  "?" 
285+  current  =  progress .items_completed 
286+  total  =  progress .total 
287+  digits  =  self ._get_digits (total  or  current )
288+  return  (
289+  HTML (self .template )
290+  .format (digits = digits )
291+  .format (current = current , total = total )
230292 )
231293
232294 def  get_width (self , progress_bar : "ProgressBar" ) ->  AnyDimension :
233-  all_lengths  =  [
234-  len ("{0:>3}" .format (c .total  or  "?" )) for  c  in  progress_bar .counters 
235-  ]
236-  all_lengths .append (1 )
237-  return  D .exact (max (all_lengths ) *  2  +  1 )
295+  biggest  =  max (c .total  or  c .items_completed  for  c  in  progress_bar .counters )
296+  return  D .exact (self ._get_digits (biggest ) *  2  +  1 )
238297
239298
240299def  _format_timedelta (timedelta : datetime .timedelta ) ->  str :
0 commit comments