[PATCH] guix: Show better progress bars.

  • Open
  • quality assurance status badge
Details
3 participants
  • Julien Lepiller
  • Ludovic Courtès
  • Simon Tournier
Owner
unassigned
Submitted by
Julien Lepiller
Severity
normal
J
J
Julien Lepiller wrote on 11 Dec 2022 19:00
(address . guix-patches@gnu.org)
20221211190059.51c44520@sybil.lepiller.eu
Hi Guix!

The attached patch is a small improvement on our progress bars. Instead
of our cute ASCII art:

1.2MiB/s 00:04 [### ] 18.5%

We get something a little more smooth:

1.1MiB/s 00:04 ▕███ ▏ 17.1%
1.2MiB/s 00:05 ▕███▋ ▏ 20.7%

Using unicode characters that can represent 1/8 of a character width.

I used port-encoding to detect when the output supports unicode, but
maybe there's something more dedicated to figuring that out? When the
port encoding is not UTF-8, we fall back to the ASCII version.

Thoughts?
From c428c80fd628797ae80029a0a22678ef55c68d6c Mon Sep 17 00:00:00 2001
From: Julien Lepiller <julien@lepiller.eu>
Date: Sun, 11 Dec 2022 18:51:13 +0100
Subject: [PATCH] guix: Show better progress bars.

* guix/progress.scm (progress-bar): When supported, use unicode variant.
---
guix/progress.scm | 43 ++++++++++++++++++++++++++++++++++++-------
1 file changed, 36 insertions(+), 7 deletions(-)

Toggle diff (59 lines)
diff --git a/guix/progress.scm b/guix/progress.scm
index 4f8e98edc0..527bf72839 100644
--- a/guix/progress.scm
+++ b/guix/progress.scm
@@ -166,16 +166,45 @@ (define current-terminal-columns
;; Number of columns of the terminal.
(make-parameter 80))
+(define-record-type* <progress-bar-style>
+ progress-bar-style make-progress-bar-style progress-bar-style?
+ (start progress-bar-style-start
+ (default #\x2595))
+ (stop progress-bar-style-stop
+ (default #\x258f))
+ (filled progress-bar-style-filled
+ (default #\x2588))
+ (steps progress-bar-style-steps
+ (default '(#\x258F #\x258E #\x258D #\x258C #\x258B #\x258A #\x2589))))
+
+(define unicode-bar-style (progress-bar-style))
+(define ascii-bar-style
+ (progress-bar-style
+ (start #\[)
+ (stop #\])
+ (filled #\#)
+ (steps '())))
+
(define* (progress-bar % #:optional (bar-width 20))
"Return % as a string representing an ASCII-art progress bar. The total
width of the bar is BAR-WIDTH."
- (let* ((bar-width (max 3 (- bar-width 2)))
- (fraction (/ % 100))
- (filled (inexact->exact (floor (* fraction bar-width))))
- (empty (- bar-width filled)))
- (format #f "[~a~a]"
- (make-string filled #\#)
- (make-string empty #\space))))
+ (let* ((bar-style (if (equal? (port-encoding (current-output-port)) "UTF-8")
+ unicode-bar-style
+ ascii-bar-style))
+ (bar-width (max 3 (- bar-width 2)))
+ (intermediates (+ (length (progress-bar-style-steps bar-style)) 1))
+ (step (inexact->exact (floor (/ (* % bar-width intermediates) 100))))
+ (filled (quotient step intermediates))
+ (intermediate
+ (list-ref (cons #f (progress-bar-style-steps bar-style))
+ (modulo step intermediates)))
+ (empty (- bar-width filled (if intermediate 1 0))))
+ (format #f "~a~a~a~a~a"
+ (string (progress-bar-style-start bar-style))
+ (make-string filled (progress-bar-style-filled bar-style))
+ (if intermediate (string intermediate) "")
+ (make-string empty #\space)
+ (string (progress-bar-style-stop bar-style)))))
(define (erase-current-line port)
"Write an ANSI erase-current-line sequence to PORT to erase the whole line and
--
2.38.1
J
J
Julien Lepiller wrote on 21 Dec 2022 17:20
07A3E592-FE42-48AA-B5D4-16D72C3881FC@lepiller.eu
Hi Guix!

The patch is pretty simple, but I'm surprised nobody bikeshedded yet :)

Thoughts?

Le 11 décembre 2022 19:00:59 GMT+01:00, Julien Lepiller <julien@lepiller.eu> a écrit :
Toggle quote (19 lines)
>Hi Guix!
>
>The attached patch is a small improvement on our progress bars. Instead
>of our cute ASCII art:
>
>1.2MiB/s 00:04 [### ] 18.5%
>
>We get something a little more smooth:
>
>1.1MiB/s 00:04 ▕███ ▏ 17.1%
>1.2MiB/s 00:05 ▕███▋ ▏ 20.7%
>
>Using unicode characters that can represent 1/8 of a character width.
>
>I used port-encoding to detect when the output supports unicode, but
>maybe there's something more dedicated to figuring that out? When the
>port encoding is not UTF-8, we fall back to the ASCII version.
>
>Thoughts?
Attachment: file
S
S
Simon Tournier wrote on 6 Jan 18:45 +0100
87358nh7zn.fsf@gmail.com
Hi Julien,

Toggle quote (5 lines)
> Le 11 décembre 2022 19:00:59 GMT+01:00, Julien Lepiller <julien@lepiller.eu> a écrit :

>>1.1MiB/s 00:04 ▕███ ▏ 17.1%
>>1.2MiB/s 00:05 ▕███▋ ▏ 20.7%

On Wed, 21 Dec 2022 at 17:20, Julien Lepiller <julien@lepiller.eu> wrote:

Toggle quote (2 lines)
> The patch is pretty simple, but I'm surprised nobody bikeshedded yet :)

Personally, I am not fan of fancy Unicode. :-) But the patch LGTM.

Well, if there is no strong objection and since it is more than 25 days,
maybe you could apply it after waiting a couple more of days. :-)

Cheers,
simon
L
L
Ludovic Courtès wrote on 13 Jan 18:07 +0100
Re: bug#59975: [PATCH] guix: Show better progress bars.
(name . Julien Lepiller)(address . julien@lepiller.eu)(address . 59975@debbugs.gnu.org)
877cxqbbxd.fsf@gnu.org
Hello!

Julien Lepiller <julien@lepiller.eu> skribis:

Toggle quote (14 lines)
> Hi Guix!
>
> The attached patch is a small improvement on our progress bars. Instead
> of our cute ASCII art:
>
> 1.2MiB/s 00:04 [### ] 18.5%
>
> We get something a little more smooth:
>
> 1.1MiB/s 00:04 ▕███ ▏ 17.1%
> 1.2MiB/s 00:05 ▕███▋ ▏ 20.7%
>
> Using unicode characters that can represent 1/8 of a character width.

Woow, fancy! Love it!! Too bad I was too late to have it under the
Newtonmas tree. 🎄

Toggle quote (4 lines)
> I used port-encoding to detect when the output supports unicode, but
> maybe there's something more dedicated to figuring that out? When the
> port encoding is not UTF-8, we fall back to the ASCII version.

One question: how likely is it that people won’t have a font with those
glyphs to display it correctly?

It would be good to check in xterm, Linux console with some default
font, and GNOME/Xfce terminals with defaults.

(Works for me in xterm and in Emacs, FWIW.)

Toggle quote (7 lines)
>>From c428c80fd628797ae80029a0a22678ef55c68d6c Mon Sep 17 00:00:00 2001
> From: Julien Lepiller <julien@lepiller.eu>
> Date: Sun, 11 Dec 2022 18:51:13 +0100
> Subject: [PATCH] guix: Show better progress bars.
>
> * guix/progress.scm (progress-bar): When supported, use unicode variant.

Please describe all the changes.

Toggle quote (13 lines)
> +(define-record-type* <progress-bar-style>
> + progress-bar-style make-progress-bar-style progress-bar-style?
> + (start progress-bar-style-start
> + (default #\x2595))
> + (stop progress-bar-style-stop
> + (default #\x258f))
> + (filled progress-bar-style-filled
> + (default #\x2588))
> + (steps progress-bar-style-steps
> + (default '(#\x258F #\x258E #\x258D #\x258C #\x258B #\x258A #\x2589))))
> +
> +(define unicode-bar-style (progress-bar-style))

How about just dropping the ‘default’ bits and being explicit here?

Toggle quote (4 lines)
> + (let* ((bar-style (if (equal? (port-encoding (current-output-port)) "UTF-8")
> + unicode-bar-style
> + ascii-bar-style))

In theory you want to check for Unicode-capable, not UTF-8-encoded.

There are ways to do that (see ‘right-arrow’ in (guix ui)), but it’s
more expensive and trickier, so what you’re doing here is good enough
IMO (I actually did that in (guix scripts weather) too).

Toggle quote (10 lines)
> + (bar-width (max 3 (- bar-width 2)))
> + (intermediates (+ (length (progress-bar-style-steps bar-style)) 1))
> + (step (inexact->exact (floor (/ (* % bar-width intermediates) 100))))
> + (filled (quotient step intermediates))
> + (intermediate
> + (list-ref (cons #f (progress-bar-style-steps bar-style))
> + (modulo step intermediates)))
> + (empty (- bar-width filled (if intermediate 1 0))))
> + (format #f "~a~a~a~a~a"

s/format/simple-format/ for slightly better performance.

Otherwise LGTM, thanks!

Ludo’.
J
J
Julien Lepiller wrote on 15 Jan 11:12 +0100
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 59975@debbugs.gnu.org)
20230115111202.1874dc7f@sybil.lepiller.eu
Le Fri, 13 Jan 2023 18:07:42 +0100,
Ludovic Courtès <ludo@gnu.org> a écrit :

Toggle quote (34 lines)
> Hello!
>
> Julien Lepiller <julien@lepiller.eu> skribis:
>
> > Hi Guix!
> >
> > The attached patch is a small improvement on our progress bars.
> > Instead of our cute ASCII art:
> >
> > 1.2MiB/s 00:04 [### ] 18.5%
> >
> > We get something a little more smooth:
> >
> > 1.1MiB/s 00:04 ▕███ ▏ 17.1%
> > 1.2MiB/s 00:05 ▕███▋ ▏ 20.7%
> >
> > Using unicode characters that can represent 1/8 of a character
> > width.
>
> Woow, fancy! Love it!! Too bad I was too late to have it under the
> Newtonmas tree. 🎄
>
> > I used port-encoding to detect when the output supports unicode, but
> > maybe there's something more dedicated to figuring that out? When
> > the port encoding is not UTF-8, we fall back to the ASCII version.
>
> One question: how likely is it that people won’t have a font with
> those glyphs to display it correctly?
>
> It would be good to check in xterm, Linux console with some default
> font, and GNOME/Xfce terminals with defaults.
>
> (Works for me in xterm and in Emacs, FWIW.)

I think it's pretty common to have these characters, since they are
used by many other projects. However, testing on a tty, I can only see
the filled characters, but not the semi-filled ones, so I get something
like:

?███? ?

What do you think?

Attached v2.
From 7e4c8fbcc49068ce5a9a592d8daf7b0039ce6680 Mon Sep 17 00:00:00 2001
From: Julien Lepiller <julien@lepiller.eu>
Date: Sun, 11 Dec 2022 18:51:13 +0100
Subject: [PATCH] guix: Show better progress bars.

Style provides information on the characters to use before and after the
progress bar content (`[` and `]` for the ascii style), as well as the
character for filled step (`#` for ascii style). When supported, it
provides intermediate steps. This is used for unicode style, to show
better precision.

* guix/progress.scm (<progress-bar-style>): New record type.
(ascii-bar-style, unicode-bar-style): New variables.
(progress-bar): Draw progress depending on style. When supported, use
unicode style. Fall back to ascii style.
---
guix/progress.scm | 45 ++++++++++++++++++++++++++++++++++++++-------
1 file changed, 38 insertions(+), 7 deletions(-)

Toggle diff (61 lines)
diff --git a/guix/progress.scm b/guix/progress.scm
index 4f8e98edc0..33cf6f4a1a 100644
--- a/guix/progress.scm
+++ b/guix/progress.scm
@@ -166,16 +166,47 @@ (define current-terminal-columns
;; Number of columns of the terminal.
(make-parameter 80))
+(define-record-type* <progress-bar-style>
+ progress-bar-style make-progress-bar-style progress-bar-style?
+ (start progress-bar-style-start)
+ (stop progress-bar-style-stop)
+ (filled progress-bar-style-filled)
+ (steps progress-bar-style-steps))
+
+(define ascii-bar-style
+ (progress-bar-style
+ (start #\[)
+ (stop #\])
+ (filled #\#)
+ (steps '())))
+
+(define unicode-bar-style
+ (progress-bar-style
+ (start #\x2595)
+ (stop #\x258f)
+ (filled #\x2588)
+ (steps '(#\x258F #\x258E #\x258D #\x258C #\x258B #\x258A #\x2589))))
+
(define* (progress-bar % #:optional (bar-width 20))
"Return % as a string representing an ASCII-art progress bar. The total
width of the bar is BAR-WIDTH."
- (let* ((bar-width (max 3 (- bar-width 2)))
- (fraction (/ % 100))
- (filled (inexact->exact (floor (* fraction bar-width))))
- (empty (- bar-width filled)))
- (format #f "[~a~a]"
- (make-string filled #\#)
- (make-string empty #\space))))
+ (let* ((bar-style (if (equal? (port-encoding (current-output-port)) "UTF-8")
+ unicode-bar-style
+ ascii-bar-style))
+ (bar-width (max 3 (- bar-width 2)))
+ (intermediates (+ (length (progress-bar-style-steps bar-style)) 1))
+ (step (inexact->exact (floor (/ (* % bar-width intermediates) 100))))
+ (filled (quotient step intermediates))
+ (intermediate
+ (list-ref (cons #f (progress-bar-style-steps bar-style))
+ (modulo step intermediates)))
+ (empty (- bar-width filled (if intermediate 1 0))))
+ (simple-format #f "~a~a~a~a~a"
+ (string (progress-bar-style-start bar-style))
+ (make-string filled (progress-bar-style-filled bar-style))
+ (if intermediate (string intermediate) "")
+ (make-string empty #\space)
+ (string (progress-bar-style-stop bar-style)))))
(define (erase-current-line port)
"Write an ANSI erase-current-line sequence to PORT to erase the whole line and
--
2.38.1
L
L
Ludovic Courtès wrote on 17 Jan 10:06 +0100
(name . Julien Lepiller)(address . julien@lepiller.eu)(address . 59975@debbugs.gnu.org)
87ilh5jzs9.fsf@gnu.org
Hi,

Julien Lepiller <julien@lepiller.eu> skribis:

Toggle quote (3 lines)
> Le Fri, 13 Jan 2023 18:07:42 +0100,
> Ludovic Courtès <ludo@gnu.org> a écrit :

[...]

Toggle quote (14 lines)
>> It would be good to check in xterm, Linux console with some default
>> font, and GNOME/Xfce terminals with defaults.
>>
>> (Works for me in xterm and in Emacs, FWIW.)
>
> I think it's pretty common to have these characters, since they are
> used by many other projects. However, testing on a tty, I can only see
> the filled characters, but not the semi-filled ones, so I get something
> like:
>
> ?███? ?
>
> What do you think?

Maybe use ASCII when $TERM is “linux”?

Though again that probably depends on the font, not on the terminal
type, and that you cannot guess.

Toggle quote (18 lines)
> Attached v2.
>
> From 7e4c8fbcc49068ce5a9a592d8daf7b0039ce6680 Mon Sep 17 00:00:00 2001
> From: Julien Lepiller <julien@lepiller.eu>
> Date: Sun, 11 Dec 2022 18:51:13 +0100
> Subject: [PATCH] guix: Show better progress bars.
>
> Style provides information on the characters to use before and after the
> progress bar content (`[` and `]` for the ascii style), as well as the
> character for filled step (`#` for ascii style). When supported, it
> provides intermediate steps. This is used for unicode style, to show
> better precision.
>
> * guix/progress.scm (<progress-bar-style>): New record type.
> (ascii-bar-style, unicode-bar-style): New variables.
> (progress-bar): Draw progress depending on style. When supported, use
> unicode style. Fall back to ascii style.

LGTM.

Maybe send a heads-up on guix-devel to see if someone has something to
say about the ability to display those glyphs, wait a few more days, and
push if there are no objections?

Thanks,
Ludo’.
?