##// END OF EJS Templates
progress: use 'encoding.colwidth' to get column width of output line correctly...
FUJIWARA Katsunori -
r21860:e382cf9e default
parent child Browse files
Show More
@@ -1,305 +1,305 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 software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 """show progress bars for some actions
8 """show progress bars for some actions
9
9
10 This extension uses the progress information logged by hg commands
10 This extension uses the progress information logged by hg commands
11 to draw progress bars that are as informative as possible. Some progress
11 to draw progress bars that are as informative as possible. Some progress
12 bars only offer indeterminate information, while others have a definite
12 bars only offer indeterminate information, while others have a definite
13 end point.
13 end point.
14
14
15 The following settings are available::
15 The following settings are available::
16
16
17 [progress]
17 [progress]
18 delay = 3 # number of seconds (float) before showing the progress bar
18 delay = 3 # number of seconds (float) before showing the progress bar
19 changedelay = 1 # changedelay: minimum delay before showing a new topic.
19 changedelay = 1 # changedelay: minimum delay before showing a new topic.
20 # If set to less than 3 * refresh, that value will
20 # If set to less than 3 * refresh, that value will
21 # be used instead.
21 # be used instead.
22 refresh = 0.1 # time in seconds between refreshes of the progress bar
22 refresh = 0.1 # time in seconds between refreshes of the progress bar
23 format = topic bar number estimate # format of the progress bar
23 format = topic bar number estimate # format of the progress bar
24 width = <none> # if set, the maximum width of the progress information
24 width = <none> # if set, the maximum width of the progress information
25 # (that is, min(width, term width) will be used)
25 # (that is, min(width, term width) will be used)
26 clear-complete = True # clear the progress bar after it's done
26 clear-complete = True # clear the progress bar after it's done
27 disable = False # if true, don't show a progress bar
27 disable = False # if true, don't show a progress bar
28 assume-tty = False # if true, ALWAYS show a progress bar, unless
28 assume-tty = False # if true, ALWAYS show a progress bar, unless
29 # disable is given
29 # disable is given
30
30
31 Valid entries for the format field are topic, bar, number, unit,
31 Valid entries for the format field are topic, bar, number, unit,
32 estimate, speed, and item. item defaults to the last 20 characters of
32 estimate, speed, and item. item defaults to the last 20 characters of
33 the item, but this can be changed by adding either ``-<num>`` which
33 the item, but this can be changed by adding either ``-<num>`` which
34 would take the last num characters, or ``+<num>`` for the first num
34 would take the last num characters, or ``+<num>`` for the first num
35 characters.
35 characters.
36 """
36 """
37
37
38 import sys
38 import sys
39 import time
39 import time
40
40
41 from mercurial.i18n import _
41 from mercurial.i18n import _
42 testedwith = 'internal'
42 testedwith = 'internal'
43
43
44 from mercurial import encoding
44 from mercurial import encoding
45
45
46 def spacejoin(*args):
46 def spacejoin(*args):
47 return ' '.join(s for s in args if s)
47 return ' '.join(s for s in args if s)
48
48
49 def shouldprint(ui):
49 def shouldprint(ui):
50 return not ui.plain() and (ui._isatty(sys.stderr) or
50 return not ui.plain() and (ui._isatty(sys.stderr) or
51 ui.configbool('progress', 'assume-tty'))
51 ui.configbool('progress', 'assume-tty'))
52
52
53 def fmtremaining(seconds):
53 def fmtremaining(seconds):
54 if seconds < 60:
54 if seconds < 60:
55 # i18n: format XX seconds as "XXs"
55 # i18n: format XX seconds as "XXs"
56 return _("%02ds") % (seconds)
56 return _("%02ds") % (seconds)
57 minutes = seconds // 60
57 minutes = seconds // 60
58 if minutes < 60:
58 if minutes < 60:
59 seconds -= minutes * 60
59 seconds -= minutes * 60
60 # i18n: format X minutes and YY seconds as "XmYYs"
60 # i18n: format X minutes and YY seconds as "XmYYs"
61 return _("%dm%02ds") % (minutes, seconds)
61 return _("%dm%02ds") % (minutes, seconds)
62 # we're going to ignore seconds in this case
62 # we're going to ignore seconds in this case
63 minutes += 1
63 minutes += 1
64 hours = minutes // 60
64 hours = minutes // 60
65 minutes -= hours * 60
65 minutes -= hours * 60
66 if hours < 30:
66 if hours < 30:
67 # i18n: format X hours and YY minutes as "XhYYm"
67 # i18n: format X hours and YY minutes as "XhYYm"
68 return _("%dh%02dm") % (hours, minutes)
68 return _("%dh%02dm") % (hours, minutes)
69 # we're going to ignore minutes in this case
69 # we're going to ignore minutes in this case
70 hours += 1
70 hours += 1
71 days = hours // 24
71 days = hours // 24
72 hours -= days * 24
72 hours -= days * 24
73 if days < 15:
73 if days < 15:
74 # i18n: format X days and YY hours as "XdYYh"
74 # i18n: format X days and YY hours as "XdYYh"
75 return _("%dd%02dh") % (days, hours)
75 return _("%dd%02dh") % (days, hours)
76 # we're going to ignore hours in this case
76 # we're going to ignore hours in this case
77 days += 1
77 days += 1
78 weeks = days // 7
78 weeks = days // 7
79 days -= weeks * 7
79 days -= weeks * 7
80 if weeks < 55:
80 if weeks < 55:
81 # i18n: format X weeks and YY days as "XwYYd"
81 # i18n: format X weeks and YY days as "XwYYd"
82 return _("%dw%02dd") % (weeks, days)
82 return _("%dw%02dd") % (weeks, days)
83 # we're going to ignore days and treat a year as 52 weeks
83 # we're going to ignore days and treat a year as 52 weeks
84 weeks += 1
84 weeks += 1
85 years = weeks // 52
85 years = weeks // 52
86 weeks -= years * 52
86 weeks -= years * 52
87 # i18n: format X years and YY weeks as "XyYYw"
87 # i18n: format X years and YY weeks as "XyYYw"
88 return _("%dy%02dw") % (years, weeks)
88 return _("%dy%02dw") % (years, weeks)
89
89
90 class progbar(object):
90 class progbar(object):
91 def __init__(self, ui):
91 def __init__(self, ui):
92 self.ui = ui
92 self.ui = ui
93 self.resetstate()
93 self.resetstate()
94
94
95 def resetstate(self):
95 def resetstate(self):
96 self.topics = []
96 self.topics = []
97 self.topicstates = {}
97 self.topicstates = {}
98 self.starttimes = {}
98 self.starttimes = {}
99 self.startvals = {}
99 self.startvals = {}
100 self.printed = False
100 self.printed = False
101 self.lastprint = time.time() + float(self.ui.config(
101 self.lastprint = time.time() + float(self.ui.config(
102 'progress', 'delay', default=3))
102 'progress', 'delay', default=3))
103 self.lasttopic = None
103 self.lasttopic = None
104 self.indetcount = 0
104 self.indetcount = 0
105 self.refresh = float(self.ui.config(
105 self.refresh = float(self.ui.config(
106 'progress', 'refresh', default=0.1))
106 'progress', 'refresh', default=0.1))
107 self.changedelay = max(3 * self.refresh,
107 self.changedelay = max(3 * self.refresh,
108 float(self.ui.config(
108 float(self.ui.config(
109 'progress', 'changedelay', default=1)))
109 'progress', 'changedelay', default=1)))
110 self.order = self.ui.configlist(
110 self.order = self.ui.configlist(
111 'progress', 'format',
111 'progress', 'format',
112 default=['topic', 'bar', 'number', 'estimate'])
112 default=['topic', 'bar', 'number', 'estimate'])
113
113
114 def show(self, now, topic, pos, item, unit, total):
114 def show(self, now, topic, pos, item, unit, total):
115 if not shouldprint(self.ui):
115 if not shouldprint(self.ui):
116 return
116 return
117 termwidth = self.width()
117 termwidth = self.width()
118 self.printed = True
118 self.printed = True
119 head = ''
119 head = ''
120 needprogress = False
120 needprogress = False
121 tail = ''
121 tail = ''
122 for indicator in self.order:
122 for indicator in self.order:
123 add = ''
123 add = ''
124 if indicator == 'topic':
124 if indicator == 'topic':
125 add = topic
125 add = topic
126 elif indicator == 'number':
126 elif indicator == 'number':
127 if total:
127 if total:
128 add = ('% ' + str(len(str(total))) +
128 add = ('% ' + str(len(str(total))) +
129 's/%s') % (pos, total)
129 's/%s') % (pos, total)
130 else:
130 else:
131 add = str(pos)
131 add = str(pos)
132 elif indicator.startswith('item') and item:
132 elif indicator.startswith('item') and item:
133 slice = 'end'
133 slice = 'end'
134 if '-' in indicator:
134 if '-' in indicator:
135 wid = int(indicator.split('-')[1])
135 wid = int(indicator.split('-')[1])
136 elif '+' in indicator:
136 elif '+' in indicator:
137 slice = 'beginning'
137 slice = 'beginning'
138 wid = int(indicator.split('+')[1])
138 wid = int(indicator.split('+')[1])
139 else:
139 else:
140 wid = 20
140 wid = 20
141 if slice == 'end':
141 if slice == 'end':
142 add = item[-wid:]
142 add = item[-wid:]
143 else:
143 else:
144 add = item[:wid]
144 add = item[:wid]
145 add += (wid - len(add)) * ' '
145 add += (wid - len(add)) * ' '
146 elif indicator == 'bar':
146 elif indicator == 'bar':
147 add = ''
147 add = ''
148 needprogress = True
148 needprogress = True
149 elif indicator == 'unit' and unit:
149 elif indicator == 'unit' and unit:
150 add = unit
150 add = unit
151 elif indicator == 'estimate':
151 elif indicator == 'estimate':
152 add = self.estimate(topic, pos, total, now)
152 add = self.estimate(topic, pos, total, now)
153 elif indicator == 'speed':
153 elif indicator == 'speed':
154 add = self.speed(topic, pos, unit, now)
154 add = self.speed(topic, pos, unit, now)
155 if not needprogress:
155 if not needprogress:
156 head = spacejoin(head, add)
156 head = spacejoin(head, add)
157 else:
157 else:
158 tail = spacejoin(tail, add)
158 tail = spacejoin(tail, add)
159 if needprogress:
159 if needprogress:
160 used = 0
160 used = 0
161 if head:
161 if head:
162 used += len(head) + 1
162 used += encoding.colwidth(head) + 1
163 if tail:
163 if tail:
164 used += len(tail) + 1
164 used += encoding.colwidth(tail) + 1
165 progwidth = termwidth - used - 3
165 progwidth = termwidth - used - 3
166 if total and pos <= total:
166 if total and pos <= total:
167 amt = pos * progwidth // total
167 amt = pos * progwidth // total
168 bar = '=' * (amt - 1)
168 bar = '=' * (amt - 1)
169 if amt > 0:
169 if amt > 0:
170 bar += '>'
170 bar += '>'
171 bar += ' ' * (progwidth - amt)
171 bar += ' ' * (progwidth - amt)
172 else:
172 else:
173 progwidth -= 3
173 progwidth -= 3
174 self.indetcount += 1
174 self.indetcount += 1
175 # mod the count by twice the width so we can make the
175 # mod the count by twice the width so we can make the
176 # cursor bounce between the right and left sides
176 # cursor bounce between the right and left sides
177 amt = self.indetcount % (2 * progwidth)
177 amt = self.indetcount % (2 * progwidth)
178 amt -= progwidth
178 amt -= progwidth
179 bar = (' ' * int(progwidth - abs(amt)) + '<=>' +
179 bar = (' ' * int(progwidth - abs(amt)) + '<=>' +
180 ' ' * int(abs(amt)))
180 ' ' * int(abs(amt)))
181 prog = ''.join(('[', bar , ']'))
181 prog = ''.join(('[', bar , ']'))
182 out = spacejoin(head, prog, tail)
182 out = spacejoin(head, prog, tail)
183 else:
183 else:
184 out = spacejoin(head, tail)
184 out = spacejoin(head, tail)
185 sys.stderr.write('\r' + encoding.trim(out, termwidth))
185 sys.stderr.write('\r' + encoding.trim(out, termwidth))
186 self.lasttopic = topic
186 self.lasttopic = topic
187 sys.stderr.flush()
187 sys.stderr.flush()
188
188
189 def clear(self):
189 def clear(self):
190 if not shouldprint(self.ui):
190 if not shouldprint(self.ui):
191 return
191 return
192 sys.stderr.write('\r%s\r' % (' ' * self.width()))
192 sys.stderr.write('\r%s\r' % (' ' * self.width()))
193
193
194 def complete(self):
194 def complete(self):
195 if not shouldprint(self.ui):
195 if not shouldprint(self.ui):
196 return
196 return
197 if self.ui.configbool('progress', 'clear-complete', default=True):
197 if self.ui.configbool('progress', 'clear-complete', default=True):
198 self.clear()
198 self.clear()
199 else:
199 else:
200 sys.stderr.write('\n')
200 sys.stderr.write('\n')
201 sys.stderr.flush()
201 sys.stderr.flush()
202
202
203 def width(self):
203 def width(self):
204 tw = self.ui.termwidth()
204 tw = self.ui.termwidth()
205 return min(int(self.ui.config('progress', 'width', default=tw)), tw)
205 return min(int(self.ui.config('progress', 'width', default=tw)), tw)
206
206
207 def estimate(self, topic, pos, total, now):
207 def estimate(self, topic, pos, total, now):
208 if total is None:
208 if total is None:
209 return ''
209 return ''
210 initialpos = self.startvals[topic]
210 initialpos = self.startvals[topic]
211 target = total - initialpos
211 target = total - initialpos
212 delta = pos - initialpos
212 delta = pos - initialpos
213 if delta > 0:
213 if delta > 0:
214 elapsed = now - self.starttimes[topic]
214 elapsed = now - self.starttimes[topic]
215 if elapsed > float(
215 if elapsed > float(
216 self.ui.config('progress', 'estimate', default=2)):
216 self.ui.config('progress', 'estimate', default=2)):
217 seconds = (elapsed * (target - delta)) // delta + 1
217 seconds = (elapsed * (target - delta)) // delta + 1
218 return fmtremaining(seconds)
218 return fmtremaining(seconds)
219 return ''
219 return ''
220
220
221 def speed(self, topic, pos, unit, now):
221 def speed(self, topic, pos, unit, now):
222 initialpos = self.startvals[topic]
222 initialpos = self.startvals[topic]
223 delta = pos - initialpos
223 delta = pos - initialpos
224 elapsed = now - self.starttimes[topic]
224 elapsed = now - self.starttimes[topic]
225 if elapsed > float(
225 if elapsed > float(
226 self.ui.config('progress', 'estimate', default=2)):
226 self.ui.config('progress', 'estimate', default=2)):
227 return _('%d %s/sec') % (delta / elapsed, unit)
227 return _('%d %s/sec') % (delta / elapsed, unit)
228 return ''
228 return ''
229
229
230 def progress(self, topic, pos, item='', unit='', total=None):
230 def progress(self, topic, pos, item='', unit='', total=None):
231 now = time.time()
231 now = time.time()
232 if pos is None:
232 if pos is None:
233 self.starttimes.pop(topic, None)
233 self.starttimes.pop(topic, None)
234 self.startvals.pop(topic, None)
234 self.startvals.pop(topic, None)
235 self.topicstates.pop(topic, None)
235 self.topicstates.pop(topic, None)
236 # reset the progress bar if this is the outermost topic
236 # reset the progress bar if this is the outermost topic
237 if self.topics and self.topics[0] == topic and self.printed:
237 if self.topics and self.topics[0] == topic and self.printed:
238 self.complete()
238 self.complete()
239 self.resetstate()
239 self.resetstate()
240 # truncate the list of topics assuming all topics within
240 # truncate the list of topics assuming all topics within
241 # this one are also closed
241 # this one are also closed
242 if topic in self.topics:
242 if topic in self.topics:
243 self.topics = self.topics[:self.topics.index(topic)]
243 self.topics = self.topics[:self.topics.index(topic)]
244 # reset the last topic to the one we just unwound to,
244 # reset the last topic to the one we just unwound to,
245 # so that higher-level topics will be stickier than
245 # so that higher-level topics will be stickier than
246 # lower-level topics
246 # lower-level topics
247 if self.topics:
247 if self.topics:
248 self.lasttopic = self.topics[-1]
248 self.lasttopic = self.topics[-1]
249 else:
249 else:
250 self.lasttopic = None
250 self.lasttopic = None
251 else:
251 else:
252 if topic not in self.topics:
252 if topic not in self.topics:
253 self.starttimes[topic] = now
253 self.starttimes[topic] = now
254 self.startvals[topic] = pos
254 self.startvals[topic] = pos
255 self.topics.append(topic)
255 self.topics.append(topic)
256 self.topicstates[topic] = pos, item, unit, total
256 self.topicstates[topic] = pos, item, unit, total
257 if now - self.lastprint >= self.refresh and self.topics:
257 if now - self.lastprint >= self.refresh and self.topics:
258 if (self.lasttopic is None # first time we printed
258 if (self.lasttopic is None # first time we printed
259 # not a topic change
259 # not a topic change
260 or topic == self.lasttopic
260 or topic == self.lasttopic
261 # it's been long enough we should print anyway
261 # it's been long enough we should print anyway
262 or now - self.lastprint >= self.changedelay):
262 or now - self.lastprint >= self.changedelay):
263 self.lastprint = now
263 self.lastprint = now
264 self.show(now, topic, *self.topicstates[topic])
264 self.show(now, topic, *self.topicstates[topic])
265
265
266 _singleton = None
266 _singleton = None
267
267
268 def uisetup(ui):
268 def uisetup(ui):
269 global _singleton
269 global _singleton
270 class progressui(ui.__class__):
270 class progressui(ui.__class__):
271 _progbar = None
271 _progbar = None
272
272
273 def _quiet(self):
273 def _quiet(self):
274 return self.debugflag or self.quiet
274 return self.debugflag or self.quiet
275
275
276 def progress(self, *args, **opts):
276 def progress(self, *args, **opts):
277 if not self._quiet():
277 if not self._quiet():
278 self._progbar.progress(*args, **opts)
278 self._progbar.progress(*args, **opts)
279 return super(progressui, self).progress(*args, **opts)
279 return super(progressui, self).progress(*args, **opts)
280
280
281 def write(self, *args, **opts):
281 def write(self, *args, **opts):
282 if not self._quiet() and self._progbar.printed:
282 if not self._quiet() and self._progbar.printed:
283 self._progbar.clear()
283 self._progbar.clear()
284 return super(progressui, self).write(*args, **opts)
284 return super(progressui, self).write(*args, **opts)
285
285
286 def write_err(self, *args, **opts):
286 def write_err(self, *args, **opts):
287 if not self._quiet() and self._progbar.printed:
287 if not self._quiet() and self._progbar.printed:
288 self._progbar.clear()
288 self._progbar.clear()
289 return super(progressui, self).write_err(*args, **opts)
289 return super(progressui, self).write_err(*args, **opts)
290
290
291 # Apps that derive a class from ui.ui() can use
291 # Apps that derive a class from ui.ui() can use
292 # setconfig('progress', 'disable', 'True') to disable this extension
292 # setconfig('progress', 'disable', 'True') to disable this extension
293 if ui.configbool('progress', 'disable'):
293 if ui.configbool('progress', 'disable'):
294 return
294 return
295 if shouldprint(ui) and not ui.debugflag and not ui.quiet:
295 if shouldprint(ui) and not ui.debugflag and not ui.quiet:
296 ui.__class__ = progressui
296 ui.__class__ = progressui
297 # we instantiate one globally shared progress bar to avoid
297 # we instantiate one globally shared progress bar to avoid
298 # competing progress bars when multiple UI objects get created
298 # competing progress bars when multiple UI objects get created
299 if not progressui._progbar:
299 if not progressui._progbar:
300 if _singleton is None:
300 if _singleton is None:
301 _singleton = progbar(ui)
301 _singleton = progbar(ui)
302 progressui._progbar = _singleton
302 progressui._progbar = _singleton
303
303
304 def reposetup(ui, repo):
304 def reposetup(ui, repo):
305 uisetup(repo.ui)
305 uisetup(repo.ui)
@@ -1,277 +1,295 b''
1
1
2 $ cat > loop.py <<EOF
2 $ cat > loop.py <<EOF
3 > from mercurial import cmdutil, commands
3 > from mercurial import cmdutil, commands
4 > import time
4 > import time
5 >
5 >
6 > cmdtable = {}
6 > cmdtable = {}
7 > command = cmdutil.command(cmdtable)
7 > command = cmdutil.command(cmdtable)
8 >
8 >
9 > class incrementingtime(object):
9 > class incrementingtime(object):
10 > def __init__(self):
10 > def __init__(self):
11 > self._time = 0.0
11 > self._time = 0.0
12 > def __call__(self):
12 > def __call__(self):
13 > self._time += 0.25
13 > self._time += 0.25
14 > return self._time
14 > return self._time
15 > time.time = incrementingtime()
15 > time.time = incrementingtime()
16 >
16 >
17 > @command('loop',
17 > @command('loop',
18 > [('', 'total', '', 'override for total'),
18 > [('', 'total', '', 'override for total'),
19 > ('', 'nested', False, 'show nested results'),
19 > ('', 'nested', False, 'show nested results'),
20 > ('', 'parallel', False, 'show parallel sets of results')],
20 > ('', 'parallel', False, 'show parallel sets of results')],
21 > 'hg loop LOOPS',
21 > 'hg loop LOOPS',
22 > norepo=True)
22 > norepo=True)
23 > def loop(ui, loops, **opts):
23 > def loop(ui, loops, **opts):
24 > loops = int(loops)
24 > loops = int(loops)
25 > total = None
25 > total = None
26 > if loops >= 0:
26 > if loops >= 0:
27 > total = loops
27 > total = loops
28 > if opts.get('total', None):
28 > if opts.get('total', None):
29 > total = int(opts.get('total'))
29 > total = int(opts.get('total'))
30 > nested = False
30 > nested = False
31 > if opts.get('nested', None):
31 > if opts.get('nested', None):
32 > nested = True
32 > nested = True
33 > loops = abs(loops)
33 > loops = abs(loops)
34 >
34 >
35 > for i in range(loops):
35 > for i in range(loops):
36 > ui.progress(topiclabel, i, 'loop.%d' % i, 'loopnum', total)
36 > ui.progress(topiclabel, i, 'loop.%d' % i, 'loopnum', total)
37 > if opts.get('parallel'):
37 > if opts.get('parallel'):
38 > ui.progress('other', i, 'other.%d' % i, 'othernum', total)
38 > ui.progress('other', i, 'other.%d' % i, 'othernum', total)
39 > if nested:
39 > if nested:
40 > nested_steps = 2
40 > nested_steps = 2
41 > if i and i % 4 == 0:
41 > if i and i % 4 == 0:
42 > nested_steps = 5
42 > nested_steps = 5
43 > for j in range(nested_steps):
43 > for j in range(nested_steps):
44 > ui.progress(
44 > ui.progress(
45 > 'nested', j, 'nested.%d' % j, 'nestnum', nested_steps)
45 > 'nested', j, 'nested.%d' % j, 'nestnum', nested_steps)
46 > ui.progress(
46 > ui.progress(
47 > 'nested', None, 'nested.done', 'nestnum', nested_steps)
47 > 'nested', None, 'nested.done', 'nestnum', nested_steps)
48 > ui.progress(topiclabel, None, 'loop.done', 'loopnum', total)
48 > ui.progress(topiclabel, None, 'loop.done', 'loopnum', total)
49 >
49 >
50 > topiclabel = 'loop'
50 > topiclabel = 'loop'
51 >
51 >
52 > EOF
52 > EOF
53
53
54 $ cp $HGRCPATH $HGRCPATH.orig
54 $ cp $HGRCPATH $HGRCPATH.orig
55 $ echo "[extensions]" >> $HGRCPATH
55 $ echo "[extensions]" >> $HGRCPATH
56 $ echo "progress=" >> $HGRCPATH
56 $ echo "progress=" >> $HGRCPATH
57 $ echo "loop=`pwd`/loop.py" >> $HGRCPATH
57 $ echo "loop=`pwd`/loop.py" >> $HGRCPATH
58 $ echo "[progress]" >> $HGRCPATH
58 $ echo "[progress]" >> $HGRCPATH
59 $ echo "format = topic bar number" >> $HGRCPATH
59 $ echo "format = topic bar number" >> $HGRCPATH
60 $ echo "assume-tty=1" >> $HGRCPATH
60 $ echo "assume-tty=1" >> $HGRCPATH
61 $ echo "width=60" >> $HGRCPATH
61 $ echo "width=60" >> $HGRCPATH
62
62
63 test default params, display nothing because of delay
63 test default params, display nothing because of delay
64
64
65 $ hg -y loop 3
65 $ hg -y loop 3
66 $ echo "delay=0" >> $HGRCPATH
66 $ echo "delay=0" >> $HGRCPATH
67 $ echo "refresh=0" >> $HGRCPATH
67 $ echo "refresh=0" >> $HGRCPATH
68
68
69 test with delay=0, refresh=0
69 test with delay=0, refresh=0
70
70
71 $ hg -y loop 3
71 $ hg -y loop 3
72 \r (no-eol) (esc)
72 \r (no-eol) (esc)
73 loop [ ] 0/3\r (no-eol) (esc)
73 loop [ ] 0/3\r (no-eol) (esc)
74 loop [===============> ] 1/3\r (no-eol) (esc)
74 loop [===============> ] 1/3\r (no-eol) (esc)
75 loop [===============================> ] 2/3\r (no-eol) (esc)
75 loop [===============================> ] 2/3\r (no-eol) (esc)
76 \r (no-eol) (esc)
76 \r (no-eol) (esc)
77
77
78
78
79 test nested short-lived topics (which shouldn't display with nestdelay):
79 test nested short-lived topics (which shouldn't display with nestdelay):
80
80
81 $ hg -y loop 3 --nested
81 $ hg -y loop 3 --nested
82 \r (no-eol) (esc)
82 \r (no-eol) (esc)
83 loop [ ] 0/3\r (no-eol) (esc)
83 loop [ ] 0/3\r (no-eol) (esc)
84 loop [===============> ] 1/3\r (no-eol) (esc)
84 loop [===============> ] 1/3\r (no-eol) (esc)
85 loop [===============================> ] 2/3\r (no-eol) (esc)
85 loop [===============================> ] 2/3\r (no-eol) (esc)
86 \r (no-eol) (esc)
86 \r (no-eol) (esc)
87
87
88 Test nested long-lived topic which has the same name as a short-lived
88 Test nested long-lived topic which has the same name as a short-lived
89 peer. We shouldn't get stuck showing the short-lived inner steps, and
89 peer. We shouldn't get stuck showing the short-lived inner steps, and
90 should go back to skipping the inner steps when the slow nested step
90 should go back to skipping the inner steps when the slow nested step
91 finishes.
91 finishes.
92
92
93 $ hg -y loop 7 --nested
93 $ hg -y loop 7 --nested
94 \r (no-eol) (esc)
94 \r (no-eol) (esc)
95 loop [ ] 0/7\r (no-eol) (esc)
95 loop [ ] 0/7\r (no-eol) (esc)
96 loop [=====> ] 1/7\r (no-eol) (esc)
96 loop [=====> ] 1/7\r (no-eol) (esc)
97 loop [============> ] 2/7\r (no-eol) (esc)
97 loop [============> ] 2/7\r (no-eol) (esc)
98 loop [===================> ] 3/7\r (no-eol) (esc)
98 loop [===================> ] 3/7\r (no-eol) (esc)
99 loop [==========================> ] 4/7\r (no-eol) (esc)
99 loop [==========================> ] 4/7\r (no-eol) (esc)
100 nested [==========================> ] 3/5\r (no-eol) (esc)
100 nested [==========================> ] 3/5\r (no-eol) (esc)
101 nested [===================================> ] 4/5\r (no-eol) (esc)
101 nested [===================================> ] 4/5\r (no-eol) (esc)
102 loop [=================================> ] 5/7\r (no-eol) (esc)
102 loop [=================================> ] 5/7\r (no-eol) (esc)
103 loop [========================================> ] 6/7\r (no-eol) (esc)
103 loop [========================================> ] 6/7\r (no-eol) (esc)
104 \r (no-eol) (esc)
104 \r (no-eol) (esc)
105
105
106
106
107 $ hg --config progress.changedelay=0 -y loop 3 --nested
107 $ hg --config progress.changedelay=0 -y loop 3 --nested
108 \r (no-eol) (esc)
108 \r (no-eol) (esc)
109 loop [ ] 0/3\r (no-eol) (esc)
109 loop [ ] 0/3\r (no-eol) (esc)
110 nested [ ] 0/2\r (no-eol) (esc)
110 nested [ ] 0/2\r (no-eol) (esc)
111 nested [======================> ] 1/2\r (no-eol) (esc)
111 nested [======================> ] 1/2\r (no-eol) (esc)
112 loop [===============> ] 1/3\r (no-eol) (esc)
112 loop [===============> ] 1/3\r (no-eol) (esc)
113 nested [ ] 0/2\r (no-eol) (esc)
113 nested [ ] 0/2\r (no-eol) (esc)
114 nested [======================> ] 1/2\r (no-eol) (esc)
114 nested [======================> ] 1/2\r (no-eol) (esc)
115 loop [===============================> ] 2/3\r (no-eol) (esc)
115 loop [===============================> ] 2/3\r (no-eol) (esc)
116 nested [ ] 0/2\r (no-eol) (esc)
116 nested [ ] 0/2\r (no-eol) (esc)
117 nested [======================> ] 1/2\r (no-eol) (esc)
117 nested [======================> ] 1/2\r (no-eol) (esc)
118 \r (no-eol) (esc)
118 \r (no-eol) (esc)
119
119
120
120
121 test two topics being printed in parallel (as when we're doing a local
121 test two topics being printed in parallel (as when we're doing a local
122 --pull clone, where you get the unbundle and bundle progress at the
122 --pull clone, where you get the unbundle and bundle progress at the
123 same time):
123 same time):
124 $ hg loop 3 --parallel
124 $ hg loop 3 --parallel
125 \r (no-eol) (esc)
125 \r (no-eol) (esc)
126 loop [ ] 0/3\r (no-eol) (esc)
126 loop [ ] 0/3\r (no-eol) (esc)
127 loop [===============> ] 1/3\r (no-eol) (esc)
127 loop [===============> ] 1/3\r (no-eol) (esc)
128 loop [===============================> ] 2/3\r (no-eol) (esc)
128 loop [===============================> ] 2/3\r (no-eol) (esc)
129 \r (no-eol) (esc)
129 \r (no-eol) (esc)
130 test refresh is taken in account
130 test refresh is taken in account
131
131
132 $ hg -y --config progress.refresh=100 loop 3
132 $ hg -y --config progress.refresh=100 loop 3
133
133
134 test format options 1
134 test format options 1
135
135
136 $ hg -y --config 'progress.format=number topic item+2' loop 2
136 $ hg -y --config 'progress.format=number topic item+2' loop 2
137 \r (no-eol) (esc)
137 \r (no-eol) (esc)
138 0/2 loop lo\r (no-eol) (esc)
138 0/2 loop lo\r (no-eol) (esc)
139 1/2 loop lo\r (no-eol) (esc)
139 1/2 loop lo\r (no-eol) (esc)
140 \r (no-eol) (esc)
140 \r (no-eol) (esc)
141
141
142 test format options 2
142 test format options 2
143
143
144 $ hg -y --config 'progress.format=number item-3 bar' loop 2
144 $ hg -y --config 'progress.format=number item-3 bar' loop 2
145 \r (no-eol) (esc)
145 \r (no-eol) (esc)
146 0/2 p.0 [ ]\r (no-eol) (esc)
146 0/2 p.0 [ ]\r (no-eol) (esc)
147 1/2 p.1 [=======================> ]\r (no-eol) (esc)
147 1/2 p.1 [=======================> ]\r (no-eol) (esc)
148 \r (no-eol) (esc)
148 \r (no-eol) (esc)
149
149
150 test format options and indeterminate progress
150 test format options and indeterminate progress
151
151
152 $ hg -y --config 'progress.format=number item bar' loop -- -2
152 $ hg -y --config 'progress.format=number item bar' loop -- -2
153 \r (no-eol) (esc)
153 \r (no-eol) (esc)
154 0 loop.0 [ <=> ]\r (no-eol) (esc)
154 0 loop.0 [ <=> ]\r (no-eol) (esc)
155 1 loop.1 [ <=> ]\r (no-eol) (esc)
155 1 loop.1 [ <=> ]\r (no-eol) (esc)
156 \r (no-eol) (esc)
156 \r (no-eol) (esc)
157
157
158 make sure things don't fall over if count > total
158 make sure things don't fall over if count > total
159
159
160 $ hg -y loop --total 4 6
160 $ hg -y loop --total 4 6
161 \r (no-eol) (esc)
161 \r (no-eol) (esc)
162 loop [ ] 0/4\r (no-eol) (esc)
162 loop [ ] 0/4\r (no-eol) (esc)
163 loop [===========> ] 1/4\r (no-eol) (esc)
163 loop [===========> ] 1/4\r (no-eol) (esc)
164 loop [=======================> ] 2/4\r (no-eol) (esc)
164 loop [=======================> ] 2/4\r (no-eol) (esc)
165 loop [===================================> ] 3/4\r (no-eol) (esc)
165 loop [===================================> ] 3/4\r (no-eol) (esc)
166 loop [===============================================>] 4/4\r (no-eol) (esc)
166 loop [===============================================>] 4/4\r (no-eol) (esc)
167 loop [ <=> ] 5/4\r (no-eol) (esc)
167 loop [ <=> ] 5/4\r (no-eol) (esc)
168 \r (no-eol) (esc)
168 \r (no-eol) (esc)
169
169
170 test immediate progress completion
170 test immediate progress completion
171
171
172 $ hg -y loop 0
172 $ hg -y loop 0
173
173
174 test delay time estimates
174 test delay time estimates
175
175
176 $ cat > mocktime.py <<EOF
176 $ cat > mocktime.py <<EOF
177 > import os
177 > import os
178 > import time
178 > import time
179 >
179 >
180 > class mocktime(object):
180 > class mocktime(object):
181 > def __init__(self, increment):
181 > def __init__(self, increment):
182 > self.time = 0
182 > self.time = 0
183 > self.increment = increment
183 > self.increment = increment
184 > def __call__(self):
184 > def __call__(self):
185 > self.time += self.increment
185 > self.time += self.increment
186 > return self.time
186 > return self.time
187 >
187 >
188 > def uisetup(ui):
188 > def uisetup(ui):
189 > time.time = mocktime(int(os.environ.get('MOCKTIME', '11')))
189 > time.time = mocktime(int(os.environ.get('MOCKTIME', '11')))
190 > EOF
190 > EOF
191
191
192 $ cp $HGRCPATH.orig $HGRCPATH
192 $ cp $HGRCPATH.orig $HGRCPATH
193 $ echo "[extensions]" >> $HGRCPATH
193 $ echo "[extensions]" >> $HGRCPATH
194 $ echo "mocktime=`pwd`/mocktime.py" >> $HGRCPATH
194 $ echo "mocktime=`pwd`/mocktime.py" >> $HGRCPATH
195 $ echo "progress=" >> $HGRCPATH
195 $ echo "progress=" >> $HGRCPATH
196 $ echo "loop=`pwd`/loop.py" >> $HGRCPATH
196 $ echo "loop=`pwd`/loop.py" >> $HGRCPATH
197 $ echo "[progress]" >> $HGRCPATH
197 $ echo "[progress]" >> $HGRCPATH
198 $ echo "assume-tty=1" >> $HGRCPATH
198 $ echo "assume-tty=1" >> $HGRCPATH
199 $ echo "delay=25" >> $HGRCPATH
199 $ echo "delay=25" >> $HGRCPATH
200 $ echo "width=60" >> $HGRCPATH
200 $ echo "width=60" >> $HGRCPATH
201
201
202 $ hg -y loop 8
202 $ hg -y loop 8
203 \r (no-eol) (esc)
203 \r (no-eol) (esc)
204 loop [=========> ] 2/8 1m07s\r (no-eol) (esc)
204 loop [=========> ] 2/8 1m07s\r (no-eol) (esc)
205 loop [===============> ] 3/8 56s\r (no-eol) (esc)
205 loop [===============> ] 3/8 56s\r (no-eol) (esc)
206 loop [=====================> ] 4/8 45s\r (no-eol) (esc)
206 loop [=====================> ] 4/8 45s\r (no-eol) (esc)
207 loop [==========================> ] 5/8 34s\r (no-eol) (esc)
207 loop [==========================> ] 5/8 34s\r (no-eol) (esc)
208 loop [================================> ] 6/8 23s\r (no-eol) (esc)
208 loop [================================> ] 6/8 23s\r (no-eol) (esc)
209 loop [=====================================> ] 7/8 12s\r (no-eol) (esc)
209 loop [=====================================> ] 7/8 12s\r (no-eol) (esc)
210 \r (no-eol) (esc)
210 \r (no-eol) (esc)
211
211
212 $ MOCKTIME=10000 hg -y loop 4
212 $ MOCKTIME=10000 hg -y loop 4
213 \r (no-eol) (esc)
213 \r (no-eol) (esc)
214 loop [ ] 0/4\r (no-eol) (esc)
214 loop [ ] 0/4\r (no-eol) (esc)
215 loop [=========> ] 1/4 8h21m\r (no-eol) (esc)
215 loop [=========> ] 1/4 8h21m\r (no-eol) (esc)
216 loop [====================> ] 2/4 5h34m\r (no-eol) (esc)
216 loop [====================> ] 2/4 5h34m\r (no-eol) (esc)
217 loop [==============================> ] 3/4 2h47m\r (no-eol) (esc)
217 loop [==============================> ] 3/4 2h47m\r (no-eol) (esc)
218 \r (no-eol) (esc)
218 \r (no-eol) (esc)
219
219
220 $ MOCKTIME=1000000 hg -y loop 4
220 $ MOCKTIME=1000000 hg -y loop 4
221 \r (no-eol) (esc)
221 \r (no-eol) (esc)
222 loop [ ] 0/4\r (no-eol) (esc)
222 loop [ ] 0/4\r (no-eol) (esc)
223 loop [=========> ] 1/4 5w00d\r (no-eol) (esc)
223 loop [=========> ] 1/4 5w00d\r (no-eol) (esc)
224 loop [====================> ] 2/4 3w03d\r (no-eol) (esc)
224 loop [====================> ] 2/4 3w03d\r (no-eol) (esc)
225 loop [=============================> ] 3/4 11d14h\r (no-eol) (esc)
225 loop [=============================> ] 3/4 11d14h\r (no-eol) (esc)
226 \r (no-eol) (esc)
226 \r (no-eol) (esc)
227
227
228
228
229 $ MOCKTIME=14000000 hg -y loop 4
229 $ MOCKTIME=14000000 hg -y loop 4
230 \r (no-eol) (esc)
230 \r (no-eol) (esc)
231 loop [ ] 0/4\r (no-eol) (esc)
231 loop [ ] 0/4\r (no-eol) (esc)
232 loop [=========> ] 1/4 1y18w\r (no-eol) (esc)
232 loop [=========> ] 1/4 1y18w\r (no-eol) (esc)
233 loop [===================> ] 2/4 46w03d\r (no-eol) (esc)
233 loop [===================> ] 2/4 46w03d\r (no-eol) (esc)
234 loop [=============================> ] 3/4 23w02d\r (no-eol) (esc)
234 loop [=============================> ] 3/4 23w02d\r (no-eol) (esc)
235 \r (no-eol) (esc)
235 \r (no-eol) (esc)
236
236
237 Time estimates should not fail when there's no end point:
237 Time estimates should not fail when there's no end point:
238 $ hg -y loop -- -4
238 $ hg -y loop -- -4
239 \r (no-eol) (esc)
239 \r (no-eol) (esc)
240 loop [ <=> ] 2\r (no-eol) (esc)
240 loop [ <=> ] 2\r (no-eol) (esc)
241 loop [ <=> ] 3\r (no-eol) (esc)
241 loop [ <=> ] 3\r (no-eol) (esc)
242 \r (no-eol) (esc)
242 \r (no-eol) (esc)
243
243
244 test line trimming by '[progress] width', when progress topic contains
244 test line trimming by '[progress] width', when progress topic contains
245 multi-byte characters, of which length of byte sequence and columns in
245 multi-byte characters, of which length of byte sequence and columns in
246 display are different from each other.
246 display are different from each other.
247
247
248 $ cp $HGRCPATH.orig $HGRCPATH
248 $ cp $HGRCPATH.orig $HGRCPATH
249 $ cat >> $HGRCPATH <<EOF
249 $ cat >> $HGRCPATH <<EOF
250 > [extensions]
250 > [extensions]
251 > progress=
251 > progress=
252 > loop=`pwd`/loop.py
252 > loop=`pwd`/loop.py
253 > [progress]
253 > [progress]
254 > assume-tty = 1
254 > assume-tty = 1
255 > delay = 0
255 > delay = 0
256 > refresh = 0
256 > refresh = 0
257 > EOF
257 > EOF
258
258
259 $ rm -f loop.pyc
259 $ rm -f loop.pyc
260 $ cat >> loop.py <<EOF
260 $ cat >> loop.py <<EOF
261 > # use non-ascii characters as topic label of progress
261 > # use non-ascii characters as topic label of progress
262 > # 2 x 4 = 8 columns, but 3 x 4 = 12 bytes
262 > # 2 x 4 = 8 columns, but 3 x 4 = 12 bytes
263 > topiclabel = u'\u3042\u3044\u3046\u3048'.encode('utf-8')
263 > topiclabel = u'\u3042\u3044\u3046\u3048'.encode('utf-8')
264 > EOF
264 > EOF
265
265
266 $ cat >> $HGRCPATH <<EOF
266 $ cat >> $HGRCPATH <<EOF
267 > [progress]
267 > [progress]
268 > format = topic number
268 > format = topic number
269 > width= 12
269 > width= 12
270 > EOF
270 > EOF
271
271
272 $ hg --encoding utf-8 -y loop --total 3 3
272 $ hg --encoding utf-8 -y loop --total 3 3
273 \r (no-eol) (esc)
273 \r (no-eol) (esc)
274 \xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88 0/3\r (no-eol) (esc)
274 \xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88 0/3\r (no-eol) (esc)
275 \xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88 1/3\r (no-eol) (esc)
275 \xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88 1/3\r (no-eol) (esc)
276 \xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88 2/3\r (no-eol) (esc)
276 \xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88 2/3\r (no-eol) (esc)
277 \r (no-eol) (esc)
277 \r (no-eol) (esc)
278
279 test calculation of bar width, when progress topic contains multi-byte
280 characters, of which length of byte sequence and columns in display
281 are different from each other.
282
283 $ cat >> $HGRCPATH <<EOF
284 > [progress]
285 > format = topic bar
286 > width= 21
287 > # progwidth should be 9 (= 21 - (8+1) - 3)
288 > EOF
289
290 $ hg --encoding utf-8 -y loop --total 3 3
291 \r (no-eol) (esc)
292 \xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88 [ ]\r (no-eol) (esc)
293 \xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88 [==> ]\r (no-eol) (esc)
294 \xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88 [=====> ]\r (no-eol) (esc)
295 \r (no-eol) (esc)
General Comments 0
You need to be logged in to leave comments. Login now