]> git.phdru.name Git - m_lib.git/blob - m_lib/pbar/tty_pbar.py
Use integer division for Py3 compatibility
[m_lib.git] / m_lib / pbar / tty_pbar.py
1 """Progress bar (TTY version)"""
2
3
4 import sys, os
5
6
7 class ttyProgressBar:
8    """
9       Simple progress indicator - displays bar "graph" using standard tty
10       commands - space, backspace, etc. This method is compatible with
11       (almost) all UNIX consoles and DOS boxes.
12
13       Example:
14
15          ====------  42%
16
17       This is a "bar" (width 10 chars) for 42%
18
19       Certainly, to use it nicely, do not write anything on screen
20       (to stdout or stderr), while using it (or use erase()/redraw() methods).
21       Erase or delete it after using.
22    """
23
24    left_c = '#'     # Chars for "graphics"
25    right_c = '_'
26    space_c = ' '    # a space
27    back_c = chr(8)  # a backspace
28
29    if os.name == 'dos' or os.name == 'nt' : # Use nice chars on DOS screen
30       left_c = chr(178)
31       right_c = chr(176)
32
33
34    def __init__(self, min, max, out = sys.stderr, width1 = 10,
35          width2 = 1+3+1): # 1 space + 3 chars for "100" + 1 for "%"
36       self.min = min
37       self.current = min
38       self.max = max - min
39
40       self.width1 = width1
41       self.width2 = width2
42       self.out = out
43
44       self.redraw()
45
46
47    def __del__(self):
48       self.erase()
49
50
51    def display(self, current):
52       """
53          Draw current value on indicator.
54          Optimized to draw as little as possible.
55       """
56
57       self.current = current
58       current -= self.min
59       lng = (current * self.width1) // self.max
60
61       if current >= self.max:
62          percent = 100
63       else:
64          percent = (current * 100) // self.max
65
66       flush = False
67
68       if self.lng != lng:
69          self.lng =  lng
70          self.out.write(ttyProgressBar.back_c*(self.width1+self.width2))
71          self.out.write(ttyProgressBar.left_c*lng)
72          self.out.write(ttyProgressBar.right_c*(self.width1-lng) + ttyProgressBar.space_c)
73          self.percent = -1 # force to redraw percentage; the bug was fixed by William McVey
74          flush = True
75
76       elif self.percent != percent:
77          self.out.write(ttyProgressBar.back_c * (self.width2-1))
78          flush = True
79
80
81       if self.percent != percent:
82          self.percent =  percent
83          self.out.write(str(percent).rjust(3) + '%')
84          flush = True
85
86
87       if flush:
88          self.out.flush()
89
90       self.visible = True
91
92
93    def erase(self):
94       if self.visible: # Prevent erase() to be called twice - explicitly and from __del__()
95          self.out.write(ttyProgressBar.back_c*(self.width1+self.width2))
96          self.out.write(ttyProgressBar.space_c*(self.width1+self.width2))
97          self.out.write(ttyProgressBar.back_c*(self.width1+self.width2))
98          self.out.flush()
99          self.visible = False
100
101
102    def redraw(self):
103       self.lng = -1 # force to draw bar on the first call
104       self.percent = -1
105
106       # Clear space - just in case there was some cruft left
107       self.out.write(ttyProgressBar.space_c*(self.width1+self.width2))
108       # redraw everything
109       self.display(self.current)