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