From 4c11aebeb934817407266787d58247e1ca802057 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 19 Apr 2022 02:30:09 -0400 Subject: [PATCH] progress: optimize progress bar updates a bit Rather than erase the entire line first then print out the new content, print out the new content on top of the old and then erase anything we didn't update. This should result in a lot less flashing with faster terminals. Bug: https://crbug.com/gerrit/11293 Change-Id: Ie2920b0bf3d5e6f920b8631a1c406444b23cd12d Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/335214 Reviewed-by: LaMont Jones Tested-by: Mike Frysinger --- progress.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/progress.py b/progress.py index 43c7ad21..f9ac53a1 100644 --- a/progress.py +++ b/progress.py @@ -24,6 +24,11 @@ _NOT_TTY = not os.isatty(2) # column 0. CSI_ERASE_LINE = '\x1b[2K' +# This will erase all content in the current line after the cursor. This is +# useful for partial updates & progress messages as the terminal can display +# it better. +CSI_ERASE_LINE_AFTER = '\x1b[K' + def duration_str(total): """A less noisy timedelta.__str__. @@ -85,10 +90,10 @@ class Progress(object): return if self._total <= 0: - sys.stderr.write('%s\r%s: %d,' % ( - CSI_ERASE_LINE, + sys.stderr.write('\r%s: %d,%s' % ( self._title, - self._done)) + self._done, + CSI_ERASE_LINE_AFTER)) sys.stderr.flush() else: p = (100 * self._done) / self._total @@ -96,14 +101,14 @@ class Progress(object): jobs = '[%d job%s] ' % (self._active, 's' if self._active > 1 else '') else: jobs = '' - sys.stderr.write('%s\r%s: %2d%% %s(%d%s/%d%s)%s%s%s' % ( - CSI_ERASE_LINE, + sys.stderr.write('\r%s: %2d%% %s(%d%s/%d%s)%s%s%s%s' % ( self._title, p, jobs, self._done, self._units, self._total, self._units, ' ' if msg else '', msg, + CSI_ERASE_LINE_AFTER, '\n' if self._print_newline else '')) sys.stderr.flush() @@ -113,19 +118,19 @@ class Progress(object): duration = duration_str(time() - self._start) if self._total <= 0: - sys.stderr.write('%s\r%s: %d, done in %s\n' % ( - CSI_ERASE_LINE, + sys.stderr.write('\r%s: %d, done in %s%s\n' % ( self._title, self._done, - duration)) + duration, + CSI_ERASE_LINE_AFTER)) sys.stderr.flush() else: p = (100 * self._done) / self._total - sys.stderr.write('%s\r%s: %3d%% (%d%s/%d%s), done in %s\n' % ( - CSI_ERASE_LINE, + sys.stderr.write('\r%s: %3d%% (%d%s/%d%s), done in %s%s\n' % ( self._title, p, self._done, self._units, self._total, self._units, - duration)) + duration, + CSI_ERASE_LINE_AFTER)) sys.stderr.flush()