Message ID | 20230826063655.2227-1-julien@lepiller.eu |
---|---|
State | New |
Headers | show |
Series | [bug#65546] guix: Properly compute progress bar width. | expand |
Hi Julien, Julien Lepiller <julien@lepiller.eu> skribis: > * guix/progress.scm (terminal-width): New procedure. > (progress-reporter/bar): Use it to compute progress bar width. > * guix/git.scm (show-progress): Use it to compute progress bar width. [...] > +(define (terminal-width str) > + "Return the width of a string as it would be printed on the terminal. This > +procedure accounts for characters that have a different width than 1, such as > +CJK double-width characters." > + (define get-wchar-ffi > + (pointer->procedure int > + (dynamic-func "mbstowcs" (dynamic-link)) > + (list '* '* size_t))) > + (define terminal-width-ffi > + (pointer->procedure int > + (dynamic-func "wcswidth" (dynamic-link)) > + (list '* size_t))) > + (define (get-wchar str) > + (let ((wchar (make-bytevector (* (+ (string-length str) 1) 4)))) > + (get-wchar-ffi (bytevector->pointer wchar) > + (string->pointer str) > + (string-length str)) > + wchar)) > + (terminal-width-ffi > + (bytevector->pointer (get-wchar str)) > + (string-length str))) Neat! However, could you move it to (guix build syscalls), next to ‘terminal-columns’ (making sure ‘pointer->procedure’ is called only once rather than once per call), and with a test or two in ‘tests/syscalls.scm’? For clarity, perhaps rename it to ‘terminal-string-width’? TIA! Ludo’.
Hi Julien, this v2 of your patch looks good to me. Please push!
This page is bookmarked here and when this patch is applied it will be a happy thing :)
please apply this patch :)
Please merge this patch :)
On 10月28日 土, chris wrote:
> Please merge this patch :)
Please apply this patch! :)
diff --git a/guix/git.scm b/guix/git.scm index dbc3b7caa7..870045cddf 100644 --- a/guix/git.scm +++ b/guix/git.scm @@ -153,7 +153,7 @@ (define % ;; TODO: Both should be handled & exposed by the PROGRESS-BAR API instead. (define width (max (- (current-terminal-columns) - (string-length label) 7) + (terminal-width label) 7) 3)) (define grain diff --git a/guix/progress.scm b/guix/progress.scm index 33cf6f4a1a..8a84bcd1b0 100644 --- a/guix/progress.scm +++ b/guix/progress.scm @@ -24,6 +24,7 @@ (define-module (guix progress) #:use-module (srfi srfi-19) #:use-module (rnrs io ports) #:use-module (rnrs bytevectors) + #:use-module (system foreign) #:use-module (ice-9 format) #:use-module (ice-9 match) #:export (<progress-reporter> @@ -47,6 +48,7 @@ (define-module (guix progress) progress-bar byte-count->string current-terminal-columns + terminal-width dump-port*)) @@ -166,6 +168,28 @@ (define current-terminal-columns ;; Number of columns of the terminal. (make-parameter 80)) +(define (terminal-width str) + "Return the width of a string as it would be printed on the terminal. This +procedure accounts for characters that have a different width than 1, such as +CJK double-width characters." + (define get-wchar-ffi + (pointer->procedure int + (dynamic-func "mbstowcs" (dynamic-link)) + (list '* '* size_t))) + (define terminal-width-ffi + (pointer->procedure int + (dynamic-func "wcswidth" (dynamic-link)) + (list '* size_t))) + (define (get-wchar str) + (let ((wchar (make-bytevector (* (+ (string-length str) 1) 4)))) + (get-wchar-ffi (bytevector->pointer wchar) + (string->pointer str) + (string-length str)) + wchar)) + (terminal-width-ffi + (bytevector->pointer (get-wchar str)) + (string-length str))) + (define-record-type* <progress-bar-style> progress-bar-style make-progress-bar-style progress-bar-style? (start progress-bar-style-start) @@ -307,7 +331,7 @@ (define (draw-bar) (if (string-null? prefix) (display (progress-bar ratio (current-terminal-columns)) port) (let ((width (- (current-terminal-columns) - (string-length prefix) 3))) + (terminal-width prefix) 3))) (display prefix port) (display " " port) (display (progress-bar ratio width) port)))