From nobody Tue May 13 19:35:29 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 66.187.233.73 as permitted sender) smtp.mailfrom=famz@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from mx1.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by mx.zohomail.com with SMTPS id 1519700439363728.486887669898; Mon, 26 Feb 2018 19:00:39 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 17A0C4036114 for ; Tue, 27 Feb 2018 03:00:38 +0000 (UTC) Received: from localhost (ovpn-12-53.pek2.redhat.com [10.72.12.53]) by smtp.corp.redhat.com (Postfix) with ESMTP id 697E210B0F22 for ; Tue, 27 Feb 2018 03:00:37 +0000 (UTC) Received: by 10.80.147.22 with SMTP id m22csp3573048eda; Mon, 26 Feb 2018 03:29:38 -0800 (PST) Received: from mx1.redhat.com (mx3-rdu2.redhat.com. [66.187.233.73]) by mx.google.com with ESMTPS id a3si8182683qta.104.2018.02.26.03.27.27 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 26 Feb 2018 03:27:28 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C8C678182D06 for ; Mon, 26 Feb 2018 11:27:27 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id C489E2026E04; Mon, 26 Feb 2018 11:27:27 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-126.ams2.redhat.com [10.36.117.126]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2E4AF2026DFD; Mon, 26 Feb 2018 11:27:27 +0000 (UTC) Resent-From: Fam Zheng Resent-Date: Tue, 27 Feb 2018 11:00:35 +0800 Resent-Message-ID: <20180227030035.GG21035@lemon.usersys.redhat.com> Resent-To: importer@patchew.org X-Google-Smtp-Source: AG47ELu6DQNz63AhKnOE/3DDakxXHoLTUpooMhTBiY+3b/ehiJG4el0LfsDoFQE+ebAOMWlCthS+ X-Received: by 10.200.40.44 with SMTP id 41mr16253092qtq.111.1519644448079; Mon, 26 Feb 2018 03:27:28 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519644448; cv=none; d=google.com; s=arc-20160816; b=SeUzXZ0Bb3LbGNCWxyet8f93U1ssYp2g96qdKYx+WdjHNMQWV8a27VOquI1N4yNH9t BUiHeuzSr5eX1Ig8Pq2IKDVD2KbUesn/2YLleyS3sxMXoiR2nAzP0GAiB9+ci/FGH3Wg KNmrnmCo2/MgGd+Vk+DtneLJ/6NK95AKGt/Y7Uhk2Ni/M0ETcMRpkcdF0lAMn+WyGD8Q Tl7tpIqF2YlHVSVfMSE1iEKk1OX90TQSblEMq8wQOgnc6n2XmgZaSX/E/fhw+aQZ1w3+ /NoWCBnf8zCtJuLj4GSqTiJMC+FcflxJynJlPOrDnxkpSjTVgHu2o4q5oH3eko9vf0MY /+iQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :delivered-to:arc-authentication-results; bh=fduptjOHX6XdYELtXyd5pSpVVf/bDcodDtjs5pLhBs0=; b=JZN/0HfdjgCAA8dBceZtCGQlvE1HJ6hxhwzb2iumrz91M/COoE4UgA1kpPYxD7BeIP /7hqweoWFFWefvxFpHAisjoXhwsm6IgjnGMN+BlCIBUCuqmO/Q8y7O9c6rzoOG95QZR7 KjtaKQvKxuIrMszcEXkvV0AQWTa08Ezvm43TPWzAp+DlK7rpi0iLKVlX5nNwJdCW5VRi IDtf6/6llzFJA+ilqkVDiIXbfw1rt6CD29PcNqyh70zFKW4hcVjIUxiLM+UqMYKaLIqR It55GdBeAYlEVMbLTJ54E4w2R+sgOH32kxJOul++l7vXs2RtyWu+JucRoIS+GeypN+/F cIqQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain gapps.redhat.com configured 66.187.233.73 as internal address) smtp.mailfrom=pbonzini@redhat.com Received-SPF: pass (zoho.com: domain of redhat.com designates 66.187.233.73 as permitted sender) client-ip=66.187.233.73; envelope-from=famz@redhat.com; helo=mx1.redhat.com; Received-SPF: pass (google.com: domain gapps.redhat.com configured 66.187.233.73 as internal address) Authentication-Results: mx.google.com; spf=pass (google.com: domain gapps.redhat.com configured 66.187.233.73 as internal address) smtp.mailfrom=pbonzini@redhat.com From: Paolo Bonzini To: patchew-devel@freelists.org Cc: famz@redhat.com Subject: [PATCH 5/9] ansi2html: add support for CSIs other than ESC[m Date: Mon, 26 Feb 2018 12:27:18 +0100 Message-Id: <20180226112722.19488-6-pbonzini@redhat.com> In-Reply-To: <20180226112722.19488-1-pbonzini@redhat.com> References: <20180226112722.19488-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 26 Feb 2018 11:27:27 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 26 Feb 2018 11:27:27 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'pbonzini@redhat.com' RCPT:'' X-TUID: XFsqSLeDXWms X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Tue, 27 Feb 2018 03:00:38 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Tue, 27 Feb 2018 03:00:38 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'famz@redhat.com' RCPT:'' X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" These include cursor movement, line clearing, and screen clearing. For screen clearing, all of them are treated like ESC[2J, which is the most commonly used screen clearing CSI. Signed-off-by: Paolo Bonzini --- patchew/logviewer.py | 50 +++++++++++++++++++++++++++++++++++++++++++++= ++++ tests/test_ansi2html.py | 30 +++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/patchew/logviewer.py b/patchew/logviewer.py index fd53d14..b5627fa 100644 --- a/patchew/logviewer.py +++ b/patchew/logviewer.py @@ -96,6 +96,54 @@ class ANSI2HTMLConverter(object): yield suffix self._reset() =20 + def _do_csi_C(self, it): + arg =3D next(it) + if arg =3D=3D 0: + arg =3D 1 + self._set_pos(self.pos + arg) + + def _do_csi_D(self, it): + arg =3D next(it) + if arg =3D=3D 0: + arg =3D 1 + self._set_pos(max(0, self.pos - arg)) + + def _do_csi_K(self, it): + arg =3D next(it) + if arg =3D=3D 0 or arg =3D=3D 2: + assert not self.lazy_accumulate or self.lazy_contents =3D=3D '' + if self.pos < len(self.line): + assert not self.lazy_accumulate + del self.line[self.pos:] + if arg =3D=3D 1 or arg =3D=3D 2: + save_pos =3D self.pos + if save_pos > 0: + self.pos =3D 0 + self._write(' ' * save_pos) + + def _parse_csi_with_args(self, csi, func): + if (len(csi) <=3D 3): + func(iter([0])) + else: + # thanks to the regular expression, we know arg is a number + # and there cannot be a ValueError + func((int(arg) for arg in csi[2:-1].split(";"))) + + def _parse_csi(self, csi): + if csi[1] !=3D '[': + return + + if csi[-1] =3D=3D 'J': + save_pos =3D self.pos + yield from self._write_line('
') + self._set_pos(save_pos) + elif csi[-1] =3D=3D 'K': + self._parse_csi_with_args(csi, self._do_csi_K) + elif csi[-1] =3D=3D 'C': + self._parse_csi_with_args(csi, self._do_csi_C) + elif csi[-1] =3D=3D 'D': + self._parse_csi_with_args(csi, self._do_csi_D) + def convert(self, input): yield from self._write_prefix() for m in self.RE.finditer(input): @@ -127,6 +175,8 @@ class ANSI2HTMLConverter(object): self._set_pos(self.pos + (8 - self.pos % 8)) elif seq =3D=3D '\r': self.pos =3D 0 + elif len(seq) > 1: + yield from self._parse_csi(seq) =20 def finish(self): yield from self._write_prefix() diff --git a/tests/test_ansi2html.py b/tests/test_ansi2html.py index 731f243..ffbc98e 100644 --- a/tests/test_ansi2html.py +++ b/tests/test_ansi2html.py @@ -56,6 +56,36 @@ class ANSI2HTMLTest(unittest.TestCase): self.assertBlackBg('{\x1b]test\x1b[0m\x07}', '{}') self.assertBlackBg('{\x1b]test\x1b[7m\x07}', '{}') =20 + # ESC [2J + def test_clear_screen(self): + self.assertBlackBg('a\n\x1b[2Jb', 'a\n
b') + self.assertBlackBg('a\x1b[2J', 'a
') + self.assertBlackBg('a\x1b[2Jb', 'a
b') + + # ESC [C and ESC [D + def test_horiz_movement(self): + self.assertBlackBg('abc\x1b[2DB', 'aBc') + self.assertBlackBg('abc\x1b[3CD', 'abc D') + self.assertBlackBg('abcd\x1b[3DB\x1b[1CD', 'aBcD') + self.assertBlackBg('abc\x1b[0CD', 'abc D') + self.assertBlackBg('abc\x1b[CD', 'abc D') + + # ESC [K + def test_clear_line(self): + self.assertBlackBg('\x1b[Kabcd', 'abcd') + self.assertBlackBg('abcd\r\x1b[K', '') + self.assertBlackBg('abcd\b\x1b[K', 'abc') + self.assertBlackBg('abcd\r\x1b[KDef', 'Def') + self.assertBlackBg('abcd\b\x1b[KDef', 'abcDef') + self.assertBlackBg('abcd\r\x1b[0K', '') + self.assertBlackBg('abcd\b\x1b[0K', 'abc') + self.assertBlackBg('abcd\r\x1b[1K', 'abcd') + self.assertBlackBg('abcd\b\x1b[1K', ' d') + self.assertBlackBg('abcd\r\x1b[2K', '') + self.assertBlackBg('abcd\b\x1b[2K', ' ') + self.assertBlackBg('abcd\r\x1b[2KDef', 'Def') + self.assertBlackBg('abcd\b\x1b[2KDef', ' Def') + =20 if __name__ =3D=3D '__main__': unittest.main() --=20 2.14.3