diff --git a/src/borg/helpers/progress.py b/src/borg/helpers/progress.py index 312ff2585..9784f80e1 100644 --- a/src/borg/helpers/progress.py +++ b/src/borg/helpers/progress.py @@ -147,10 +147,12 @@ class ProgressIndicatorPercent(ProgressIndicatorBase): # truncate the last argument, if no space is available if info is not None: if not self.json: + from ..platform import swidth # avoid circular import + # no need to truncate if we're not outputting to a terminal terminal_space = get_terminal_size(fallback=(-1, -1))[0] if terminal_space != -1: - space = terminal_space - len(self.msg % tuple([pct] + info[:-1] + [''])) + space = terminal_space - swidth(self.msg % tuple([pct] + info[:-1] + [''])) info[-1] = ellipsis_truncate(info[-1], space) return self.output(self.msg % tuple([pct] + info), justify=False, info=info) diff --git a/src/borg/testsuite/helpers.py b/src/borg/testsuite/helpers.py index 0785a82c4..99057a3d2 100644 --- a/src/borg/testsuite/helpers.py +++ b/src/borg/testsuite/helpers.py @@ -30,6 +30,7 @@ from ..helpers import popen_with_error_handling from ..helpers import dash_open from ..helpers import iter_separated from ..helpers import eval_escapes +from ..platform import is_win32, swidth from . import BaseTestCase, FakeInputs @@ -896,6 +897,29 @@ def test_progress_percentage_sameline(capfd, monkeypatch): assert err == ' ' * 4 + '\r' +@pytest.mark.skipif(is_win32, reason='no working swidth() implementation on this platform') +def test_progress_percentage_widechars(capfd, monkeypatch): + st = 'スター・トレック' # 'startrek' :-) + assert swidth(st) == 16 + path = '/カーク船長です。' # 'Captain Kirk' + assert swidth(path) == 17 + spaces = ' ' * 4 # to avoid usage of '...' + width = len('100%') + 1 + swidth(st) + 1 + swidth(path) + swidth(spaces) + monkeypatch.setenv('COLUMNS', str(width)) + monkeypatch.setenv('LINES', '1') + pi = ProgressIndicatorPercent(100, step=5, start=0, msg=f'%3.0f%% {st} %s') + pi.logger.setLevel('INFO') + pi.show(0, info=[path]) + out, err = capfd.readouterr() + assert err == f' 0% {st} {path}{spaces}\r' + pi.show(100, info=[path]) + out, err = capfd.readouterr() + assert err == f'100% {st} {path}{spaces}\r' + pi.finish() + out, err = capfd.readouterr() + assert err == ' ' * width + '\r' + + def test_progress_percentage_step(capfd, monkeypatch): # run the test as if it was in a 4x1 terminal monkeypatch.setenv('COLUMNS', '4')