##// END OF EJS Templates
progress: provide an explicit disable method for developers...
Steve Borho -
r10540:dd9d0574 stable
parent child Browse files
Show More
@@ -1,183 +1,187 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 logged by hg commands
22 22 to draw progress 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
37 37 item. item defaults to the last 20 characters of the item, but this
38 38 can be changed by adding either ``-<num>`` which would take the last
39 39 num characters, or ``+<num>`` for the first num characters.
40 40 """
41 41
42 42 import sys
43 43 import time
44 44
45 45 from mercurial import extensions
46 46 from mercurial import util
47 47
48 48 def spacejoin(*args):
49 49 return ' '.join(s for s in args if s)
50 50
51 51 class progbar(object):
52 52 def __init__(self, ui):
53 53 self.ui = ui
54 54 self.resetstate()
55 55
56 56 def resetstate(self):
57 57 self.topics = []
58 58 self.printed = False
59 59 self.lastprint = time.time() + float(self.ui.config(
60 60 'progress', 'delay', default=3))
61 61 self.indetcount = 0
62 62 self.refresh = float(self.ui.config(
63 63 'progress', 'refresh', default=0.1))
64 64 self.order = self.ui.configlist(
65 65 'progress', 'format',
66 66 default=['topic', 'bar', 'number'])
67 67
68 68 def show(self, topic, pos, item, unit, total):
69 69 termwidth = self.width()
70 70 self.printed = True
71 71 head = ''
72 72 needprogress = False
73 73 tail = ''
74 74 for indicator in self.order:
75 75 add = ''
76 76 if indicator == 'topic':
77 77 add = topic
78 78 elif indicator == 'number':
79 79 if total:
80 80 add = ('% ' + str(len(str(total))) +
81 81 's/%s') % (pos, total)
82 82 else:
83 83 add = str(pos)
84 84 elif indicator.startswith('item') and item:
85 85 slice = 'end'
86 86 if '-' in indicator:
87 87 wid = int(indicator.split('-')[1])
88 88 elif '+' in indicator:
89 89 slice = 'beginning'
90 90 wid = int(indicator.split('+')[1])
91 91 else:
92 92 wid = 20
93 93 if slice == 'end':
94 94 add = item[-wid:]
95 95 else:
96 96 add = item[:wid]
97 97 add += (wid - len(add)) * ' '
98 98 elif indicator == 'bar':
99 99 add = ''
100 100 needprogress = True
101 101 elif indicator == 'unit' and unit:
102 102 add = unit
103 103 if not needprogress:
104 104 head = spacejoin(head, add)
105 105 else:
106 106 tail = spacejoin(add, tail)
107 107 if needprogress:
108 108 used = 0
109 109 if head:
110 110 used += len(head) + 1
111 111 if tail:
112 112 used += len(tail) + 1
113 113 progwidth = termwidth - used - 3
114 114 if total:
115 115 amt = pos * progwidth // total
116 116 bar = '=' * (amt - 1)
117 117 if amt > 0:
118 118 bar += '>'
119 119 bar += ' ' * (progwidth - amt)
120 120 else:
121 121 progwidth -= 3
122 122 self.indetcount += 1
123 123 # mod the count by twice the width so we can make the
124 124 # cursor bounce between the right and left sides
125 125 amt = self.indetcount % (2 * progwidth)
126 126 amt -= progwidth
127 127 bar = (' ' * int(progwidth - abs(amt)) + '<=>' +
128 128 ' ' * int(abs(amt)))
129 129 prog = ''.join(('[', bar , ']'))
130 130 out = spacejoin(head, prog, tail)
131 131 else:
132 132 out = spacejoin(head, tail)
133 133 sys.stdout.write('\r' + out[:termwidth])
134 134 sys.stdout.flush()
135 135
136 136 def clear(self):
137 137 sys.stdout.write('\r%s\r' % (' ' * self.width()))
138 138
139 139 def complete(self):
140 140 if self.ui.configbool('progress', 'clear-complete', default=True):
141 141 self.clear()
142 142 else:
143 143 sys.stdout.write('\n')
144 144 sys.stdout.flush()
145 145
146 146 def width(self):
147 147 tw = util.termwidth()
148 148 return min(int(self.ui.config('progress', 'width', default=tw)), tw)
149 149
150 150 def progress(self, orig, topic, pos, item='', unit='', total=None):
151 151 if pos is None:
152 152 if self.topics and self.topics[-1] == topic and self.printed:
153 153 self.complete()
154 154 self.resetstate()
155 155 else:
156 156 if topic not in self.topics:
157 157 self.topics.append(topic)
158 158 now = time.time()
159 159 if (now - self.lastprint >= self.refresh
160 160 and topic == self.topics[-1]):
161 161 self.lastprint = now
162 162 self.show(topic, pos, item, unit, total)
163 163 return orig(topic, pos, item=item, unit=unit, total=total)
164 164
165 165 def write(self, orig, *args):
166 166 if self.printed:
167 167 self.clear()
168 168 return orig(*args)
169 169
170 170 sharedprog = None
171 171
172 172 def uisetup(ui):
173 # Apps that derive a class from ui.ui() can use
174 # setconfig('progress', 'disable', 'True') to disable this extension
175 if ui.configbool('progress', 'disable'):
176 return
173 177 if ui.interactive() and not ui.debugflag and not ui.quiet:
174 178 # we instantiate one globally shared progress bar to avoid
175 179 # competing progress bars when multiple UI objects get created
176 180 global sharedprog
177 181 if not sharedprog:
178 182 sharedprog = progbar(ui)
179 183 extensions.wrapfunction(ui, 'progress', sharedprog.progress)
180 184 extensions.wrapfunction(ui, 'write', sharedprog.write)
181 185
182 186 def reposetup(ui, repo):
183 187 uisetup(repo.ui)
General Comments 0
You need to be logged in to leave comments. Login now