qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: John Snow <jsnow@redhat.com>
To: "Philippe Mathieu-Daudé" <f4bug@amsat.org>,
	"Eric Blake" <eblake@redhat.com>
Cc: Eduardo Habkost <eduardo@habkost.net>,
	Kevin Wolf <kwolf@redhat.com>, Thomas Huth <thuth@redhat.com>,
	Beraldo Leal <bleal@redhat.com>,
	Qemu-block <qemu-block@nongnu.org>,
	qemu-devel <qemu-devel@nongnu.org>,
	Hanna Reitz <hreitz@redhat.com>, Cleber Rosa <crosa@redhat.com>
Subject: Re: [PATCH 1/4] python/utils: add enboxify() text decoration utility
Date: Wed, 16 Feb 2022 11:16:00 -0500	[thread overview]
Message-ID: <CAFn=p-ZEWubCO+cGL19vo3esdPHux5KT3OO1V9=TGjYX5AfFPA@mail.gmail.com> (raw)
In-Reply-To: <bb420d6b-02f1-b8b8-2f53-680bd765a323@amsat.org>

[-- Attachment #1: Type: text/plain, Size: 6180 bytes --]

On Tue, Feb 15, 2022, 6:57 PM Philippe Mathieu-Daudé <f4bug@amsat.org>
wrote:

> On 16/2/22 00:53, John Snow wrote:
> > On Tue, Feb 15, 2022 at 5:55 PM Eric Blake <eblake@redhat.com> wrote:
> >>
> >> On Tue, Feb 15, 2022 at 05:08:50PM -0500, John Snow wrote:
> >>>>>> print(enboxify(msg, width=72, name="commit message"))
> >>> ┏━ commit message
> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
> >>> ┃ enboxify() takes a chunk of text and wraps it in a text art box that
> ┃
> >>> ┃  adheres to a specified width. An optional title label may be given,
> ┃
> >>> ┃  and any of the individual glyphs used to draw the box may be
> ┃
> >>
> >> Why do these two lines have a leading space,
> >>
> >>> ┃ replaced or specified as well.
>  ┃
> >>
> >> but this one doesn't?  It must be an off-by-one corner case when your
> >> choice of space to wrap on is exactly at the wrap column.
> >>
> >
> > Right, you're probably witnessing the right-pad *and* the actual space.
> >
> >>>
> ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
> >>>
> >>> Signed-off-by: John Snow <jsnow@redhat.com>
> >>> ---
> >>>   python/qemu/utils/__init__.py | 58
> +++++++++++++++++++++++++++++++++++
> >>>   1 file changed, 58 insertions(+)
>
> >>> +    def _wrap(line: str) -> str:
> >>> +        return os.linesep.join([
> >>> +            wrapped_line.ljust(lwidth) + suffix
> >>> +            for wrapped_line in textwrap.wrap(
> >>> +                    line, width=lwidth, initial_indent=prefix,
> >>> +                    subsequent_indent=prefix,
> replace_whitespace=False,
> >>> +                    drop_whitespace=False, break_on_hyphens=False)
> >>
> >> Always nice when someone else has written the cool library function to
> >> do all the hard work for you ;)  But this is probably where you have
> the off-by-one I called out above.
> >>
> >
> > Yeah, I just didn't want it to eat multiple spaces if they were
> > present -- I wanted it to reproduce them faithfully. The tradeoff is
> > some silliness near the margins.
> >
> > Realistically, if I want something any better than what I've done
> > here, I should find a library to do it for me instead -- but for the
> > sake of highlighting some important information, this may be
> > just-enough-juice.
>
> 's/^┃  /┃ /' on top ;D
>

I have to admit that this function is actually very fragile. Last night, I
did some reading on unicode and emoji encodings and discovered that it's
*basically impossible* to predict the "visual width" of a sequence of
unicode codepoints.

So, this function as written will only really work if we stick to
single-codepoint glyphs that can be rendered 1:1 in a monospace font.

I could probably improve it to work with "some" (but certainly not all)
wide glyphs and emoji, but it's a very complex topic and far outside my
specialty. Support for multi-codepoint narrow/halfwidth glyphs is also an
issue. (This affects some Latin characters outside of ascii if they are
encoded using combining codepoints.)

(See https://hsivonen.fi/string-length/ ... It's nasty.)

So I must admit that this function has some very serious limitations to it.
I want to explain why I wrote it, though.

First: Tracebacks make people's eyes cross over. It's a very long sequence
of mumbo jumbo that most people don't read, because it's program debug
information. I don't blame them. Setting apart the error summary visually
is a helpful tool for drawing one's eyes to the most critical pieces of
information.

Second: In my AQMP library, I use the ascii vertical bar | as a left-hand
border decoration to provide a kind of visual quoting mechanism to
illustrate in the logfile which subsequent confusing lines of jargon belong
to the same log entry. I really like this formatting mechanism, but...

Third: If a line of text becomes so long that it wraps in your terminal,
the visual quote mechanism breaks, making the output messy and hard to
read. Forcibly re-wrapping the text in a virtual box is a necessary
mechanism to preserve readability in this circumstance - the lines from
qemu-img et al may be much wider than your terminal column width.

And so, I drew a box instead of just a left border, because I needed to
re-wrap the text anyway. Visually, I believed it to help explain that the
output was being re-formatted to fit in a certain dimensionality.
Unfortunately, it's inadequate.

So ... what to do.

(1) I can just remove the right margin decoration and call the function
visual_quote or something. If any of the lines get too "long" because of
emoji/日本語, it MAY break the indent line, but occasional uses of one or two
wide characters probably won't cause wrapping that breaks the "visual quote
line" on a terminal with at least 85 columns. Essentially it'd still be
broken, but without a solid right border it'd be harder to notice *small*
breakages.

(2) If there is a genuine interest in using visual highlighting techniques
to make iotest failures easier to diagnose (and making sure it is properly
multilingual), I could use the urwid helper library to estimate visual text
width to make drawing terminal boxes more resilient than what I could do on
my own power. Downside is a new third party dependency. I already use urwid
for the aqmp tui that we're working on, but it's remained an optional
dependency so far.

(3) I can take a swing at improving this text decoration utility and having
it account for the most basic cases. East Asian language support is a low
hanging fruit, though I have only rudimentary familiarity with Hangul. (And
virtually no exposure to Thai or other south-eastern Asian scripts.)

(4) Just leave it alone for now, don't you have IDE/FDC patches to work on?

Sigh. The punishment for trying to do something nice is swift.

--js

>

[-- Attachment #2: Type: text/html, Size: 8116 bytes --]

  reply	other threads:[~2022-02-16 16:17 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-15 22:08 [PATCH 0/4] iotests: add detailed tracebacks to qemu_img() failures John Snow
2022-02-15 22:08 ` [PATCH 1/4] python/utils: add enboxify() text decoration utility John Snow
2022-02-15 22:55   ` Eric Blake
2022-02-15 23:53     ` John Snow
2022-02-15 23:57       ` Philippe Mathieu-Daudé via
2022-02-16 16:16         ` John Snow [this message]
2022-02-16 16:54           ` Hanna Reitz
2022-02-15 22:08 ` [PATCH 2/4] iotests: add VerboseProcessError John Snow
2022-02-15 22:58   ` Eric Blake
2022-02-15 23:54     ` John Snow
2022-02-15 22:08 ` [PATCH 3/4] iotests: Remove explicit checks for qemu_img() == 0 John Snow
2022-02-15 23:04   ` Eric Blake
2022-02-15 23:57     ` John Snow
2022-02-15 22:08 ` [PATCH 4/4] iotests: make qemu_img raise on non-zero rc by default John Snow
2022-02-15 23:09   ` Eric Blake
2022-02-16  0:02     ` John Snow

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAFn=p-ZEWubCO+cGL19vo3esdPHux5KT3OO1V9=TGjYX5AfFPA@mail.gmail.com' \
    --to=jsnow@redhat.com \
    --cc=bleal@redhat.com \
    --cc=crosa@redhat.com \
    --cc=eblake@redhat.com \
    --cc=eduardo@habkost.net \
    --cc=f4bug@amsat.org \
    --cc=hreitz@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=thuth@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).