##// END OF EJS Templates
progress: only reset state if finishing progress for the current topic...
Augie Fackler -
r10441:dc0d1ca2 default
parent child Browse files
Show More
@@ -1,186 +1,186 b''
1 1 # progress.py show progress bars for some actions
2 2 #
3 3 # Copyright (C) 2010 Augie Fackler <durin42@gmail.com>
4 4 #
5 5 # This program is free software; you can redistribute it and/or modify it
6 6 # under the terms of the GNU General Public License as published by the
7 7 # Free Software Foundation; either version 2 of the License, or (at your
8 8 # option) any later version.
9 9 #
10 10 # This program is distributed in the hope that it will be useful, but
11 11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 13 # Public License for more details.
14 14 #
15 15 # You should have received a copy of the GNU General Public License along
16 16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 18
19 19 """show progress bars for some actions
20 20
21 21 This extension uses the progress information commands can log with hg
22 22 to draw progres bars that are as informative as possible. Some progress
23 23 bars only offer indeterminate information, while others have a definite
24 24 end point.
25 25
26 26 The following settings are available::
27 27
28 28 [progress]
29 29 delay = 3 # number of seconds (float) before showing the progress bar
30 30 refresh = 0.1 # time in seconds between refreshes of the progress bar
31 31 format = topic bar number # format of the progress bar
32 32 width = <none> # if set, the maximum width of the progress information
33 33 # (that is, min(width, term width) will be used)
34 34 clear-complete = True # clear the progress bar after it's done
35 35
36 36 Valid entries for the format field are topic, bar, number, unit, and item.
37 37 item defaults to the last 20 characters of the item, but this can be
38 38 changed by adding either -<num> which would take the last num characters,
39 39 or +<num> for the first num characters.
40 40 """
41 41
42 42 import math
43 43 import sys
44 44 import time
45 45
46 46 from mercurial import extensions
47 47 from mercurial import util
48 48
49 49 def spacejoin(*args):
50 50 ret = ''
51 51 for s in args:
52 52 if s:
53 53 if ret:
54 54 ret += ' '
55 55 ret += s
56 56 return ret
57 57
58 58 class progbar(object):
59 59 def __init__(self, ui):
60 60 self.ui = ui
61 61 self.resetstate()
62 62
63 63 def resetstate(self):
64 64 self.topics = []
65 65 self.printed = False
66 66 self.lastprint = time.time() + float(self.ui.config(
67 67 'progress', 'delay', default=3))
68 68 self.indetcount = 0
69 69 self.refresh = float(self.ui.config(
70 70 'progress', 'refresh', default=0.1))
71 71 self.order = self.ui.configlist(
72 72 'progress', 'format',
73 73 default=['topic', 'bar', 'number'])
74 74
75 75 def show(self, topic, pos, item, unit, total):
76 76 termwidth = self.width()
77 77 self.printed = True
78 78 head = ''
79 79 needprogress = False
80 80 tail = ''
81 81 for indicator in self.order:
82 82 add = ''
83 83 if indicator == 'topic':
84 84 add = topic
85 85 elif indicator == 'number':
86 86 if total:
87 87 add = ('% ' + str(len(str(total))) +
88 88 's/%s') % (pos, total)
89 89 else:
90 90 add = str(pos)
91 91 elif indicator.startswith('item') and item:
92 92 slice = 'end'
93 93 if '-' in indicator:
94 94 wid = int(indicator.split('-')[1])
95 95 elif '+' in indicator:
96 96 slice = 'beginning'
97 97 wid = int(indicator.split('+')[1])
98 98 else:
99 99 wid = 20
100 100 if slice == 'end':
101 101 add = item[-wid:]
102 102 else:
103 103 add = item[:wid]
104 104 add += (wid - len(add)) * ' '
105 105 elif indicator == 'bar':
106 106 add = ''
107 107 needprogress = True
108 108 elif indicator == 'unit' and unit:
109 109 add = unit
110 110 if not needprogress:
111 111 head = spacejoin(head, add)
112 112 else:
113 113 tail = spacejoin(add, tail)
114 114 if needprogress:
115 115 used = 0
116 116 if head:
117 117 used += len(head) + 1
118 118 if tail:
119 119 used += len(tail) + 1
120 120 progwidth = termwidth - used - 3
121 121 if total:
122 122 amt = pos * progwidth // total
123 123 bar = '=' * (amt) + ' ' * (progwidth - amt)
124 124 else:
125 125 progwidth -= 3
126 126 self.indetcount += 1
127 127 # mod the count by twice the width so we can make the
128 128 # cursor bounce between the right and left sides
129 129 amt = self.indetcount % (2 * progwidth)
130 130 amt -= progwidth
131 131 bar = (' ' * int(progwidth - abs(amt)) + '<=>' +
132 132 ' ' * int(abs(amt)))
133 133 prog = ''.join(('[', bar , ']'))
134 134 out = spacejoin(head, prog, tail)
135 135 else:
136 136 out = spacejoin(head, tail)
137 137 sys.stdout.write('\r' + out[:termwidth])
138 138 sys.stdout.flush()
139 139
140 140 def clear(self):
141 141 sys.stdout.write('\r%s\r' % (' ' * self.width()))
142 142
143 143 def complete(self):
144 144 if self.ui.configbool('progress', 'clear-complete', default=True):
145 145 self.clear()
146 146 else:
147 147 sys.stdout.write('\n')
148 148 sys.stdout.flush()
149 149
150 150 def width(self):
151 151 tw = util.termwidth()
152 152 return min(int(self.ui.config('progress', 'width', default=tw)), tw)
153 153
154 154 def progress(self, orig, topic, pos, item='', unit='', total=None):
155 155 if pos is None:
156 156 if self.topics and self.topics[-1] == topic and self.printed:
157 157 self.complete()
158 self.resetstate()
158 self.resetstate()
159 159 else:
160 160 if topic not in self.topics:
161 161 self.topics.append(topic)
162 162 now = time.time()
163 163 if now - self.lastprint > 0.1 and topic == self.topics[-1]:
164 164 self.lastprint = now
165 165 self.show(topic, pos, item, unit, total)
166 166 return orig(topic, pos, item=item, unit=unit, total=total)
167 167
168 168 def write(self, orig, *args):
169 169 if self.printed:
170 170 self.clear()
171 171 return orig(*args)
172 172
173 173 sharedprog = None
174 174
175 175 def uisetup(ui):
176 176 if ui.interactive() and not ui.debugflag:
177 177 # we instantiate one globally shared progress bar to avoid
178 178 # competing progress bars when multiple UI objects get created
179 179 global sharedprog
180 180 if not sharedprog:
181 181 sharedprog = progbar(ui)
182 182 extensions.wrapfunction(ui, 'progress', sharedprog.progress)
183 183 extensions.wrapfunction(ui, 'write', sharedprog.write)
184 184
185 185 def reposetup(ui, repo):
186 186 uisetup(repo.ui)
General Comments 0
You need to be logged in to leave comments. Login now