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