Skip to content

Commit e68d8ca

Browse files
author
Ken Odegard
committed
Counter formatter
Counter that pads itself based on the total value.
1 parent a014eed commit e68d8ca

File tree

1 file changed

+69
-10
lines changed

1 file changed

+69
-10
lines changed

prompt_toolkit/shortcuts/progress_bar/formatters.py

Lines changed: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
Each progress bar consists of a list of these formatters.
44
"""
55
import datetime
6+
import math
67
import time
78
from abc import ABCMeta, abstractmethod
89
from typing import TYPE_CHECKING, List, Tuple
@@ -12,9 +13,10 @@
1213
AnyFormattedText,
1314
StyleAndTextTuples,
1415
to_formatted_text,
16+
merge_formatted_text,
1517
)
1618
from 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
1820
from prompt_toolkit.layout.utils import explode_text_fragments
1921
from prompt_toolkit.utils import get_cwidth
2022

@@ -27,6 +29,8 @@
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

240299
def _format_timedelta(timedelta: datetime.timedelta) -> str:

0 commit comments

Comments
 (0)