guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Colorized REPL


From: Nala Ginrut
Subject: Re: [PATCH] Colorized REPL
Date: Wed, 09 Jan 2013 18:17:34 +0800

On Fri, 2013-01-04 at 15:06 +0100, Ludovic Courtès wrote:
> Hi Nala,
> 
> Thanks for your work!
> 
> Nala Ginrut <address@hidden> skribis:
> 
> > 1. colorized-REPL feature:
> > Add two lines to your ~/.guile, to enable colorized-REPL feature: 
> > (use-modules (ice-9 colorized))
> > (activate-colorized)
> 
> I did that, and actually had to jump into a recursive REPL to see it in
> effect.  Would be nice to fix it.
> 

Well, I'm not sure what's the mean of 'recursive REPL'? 

> Once in effect, the result is pleasant.  :-)
> 

I'm glad you like it. ;-D

> > 2. custom color scheme:
> > Example:
> > (add-color-scheme! `((,(lambda (data) 
> >                         (and (number? data) (> data 10000)))
> >                         MY-LONG-NUM ,color-it (RED))))
> 
> Nice.
> 
> > Add it to your ~/.guile or in your code at you wish.
> > This feature is useful, because sometimes we need to test our program
> > and output a colorful result for some monitoring purpose.
> > PS: MY-LONG-NUM is an arbitrary name for your own color scheme, as you
> > like.
> 
> Why is that name even needed?

It's easy to debug or checkout the color-scheme info with the name.

> 
> Below is a rough review.  There are many stylistic issues IMO, such as
> the lack of proper docstrings and comments, use of conventions that are
> uncommon in Guile (like (define foo (lambda (arg) ...)),
> *variable-with-stars*, hanging parentheses, etc.), sometimes weird
> indentation, and use of tabs.
> 
> Overall it’s essentially a new implementation of write/display, so I’m a
> bit concerned about keeping it in sync with the other one.  Could you
> add test cases that compare the output of both, for instance using a
> helper procedure that dismisses ANSI escapes?
> 

OK, I added a #:test in 'colorize' and a color-it-test for it.
But I know little about the test case of Guile, anyone point me out?

> Some other comments:
> 
> > +(define-module (ice-9 colorized)
> > +  #:use-module (oop goops)
> > +  #:use-module ((rnrs) #:select (bytevector->u8-list define-record-type
> > +                           vector-for-each bytevector?))
> 
> Would be good to pull neither of these.
> 
> Could you use (srfi srfi-9) and (rnrs bytevectors) instead of the
> latter?  For GOOPS, see below.
> 

record-type in r6rs is more convenient I think.

> > +(define-record-type color-scheme
> > +  (fields str data type color control method))
> 
> Could you comment this?  I’m not clear on what each field is.
> 
> > +(define *color-list*
> > +  `((CLEAR       .   "0")
> > +    (RESET       .   "0")
> > +    (BOLD        .   "1")
> > +    (DARK        .   "2")
> > +    (UNDERLINE   .   "4")
> > +    (UNDERSCORE  .   "4")
> > +    (BLINK       .   "5")
> > +    (REVERSE     .   "6")
> > +    (CONCEALED   .   "8")
> > +    (BLACK       .  "30")
> > +    (RED         .  "31")
> > +    (GREEN       .  "32")
> > +    (YELLOW      .  "33")
> > +    (BLUE        .  "34")
> > +    (MAGENTA     .  "35")
> > +    (CYAN        .  "36")
> > +    (WHITE       .  "37")
> > +    (ON-BLACK    .  "40")
> > +    (ON-RED      .  "41")
> > +    (ON-GREEN    .  "42")
> > +    (ON-YELLOW   .  "43")
> > +    (ON-BLUE     .  "44")
> > +    (ON-MAGENTA  .  "45")
> > +    (ON-CYAN     .  "46")
> > +    (ON-WHITE    .  "47")))
> 
> Would it make sense to define a new type for colors?  Like:
> 
>   (define-record-type <color>
>     (color foreground background attribute)
>     color?
>     ...)
> 
>   (define light-cyan
>     (color x y z))
> 

Actually, I did similar things (though without record-type), but I was
suggested use the *color-list* implementation from (ansi term) from
guile-lib. hmm... ;-)
Anyway, I think that implementation is not so clear, and it mixed
'colors' and 'controls' together...

> > +(define generate-color
> > +  (lambda (colors)
> > +    (let ((color-list 
> > +      (remove not 
> > +              (map (lambda (c) (assoc-ref *color-list* c)) colors))))
> 
> Use filter-map instead.
> 

nice to know that~

> > +(define color-it
> > +  (lambda (cs)
> > +    (let* ((str (color-scheme-str cs))
> > +      (color (color-scheme-color cs))
> > +      (control (color-scheme-control cs)))
> > +      (color-it-inner color str control))))
> 
> This is somewhat confusing: I’d expect (color-it str cs), but instead
> the string to be printed is embedded in the “color scheme”.
> 

It's a convenient way to enclose string into 'color-scheme', since the
string could be used later. 

> > +(define (backspace port)
> > +  (seek port -1 SEEK_CUR))
> 
> What about non-seekable ports?  Could it be avoided altogether?
> 

But I think the 'port' parameter in 'call-with-output-string' is always
seekable, isn't it? The 'port' here is not a generic port.

> > +(define *pre-sign* 
> > +  `((LIST       .   "(") 
> > +    (PAIR       .   "(") 
> > +    (VECTOR     .   "#(")
> > +    (BYTEVECTOR .   "#vu8(")
> > +    (ARRAY      .   #f))) ;; array's sign is complecated.
> 
> It’s complicated, so what?  :-)
> 
> The comment should instead mention that arrays get special treatment in
> ‘pre-print’.
> 
> > +(define* (pre-print cs #:optional (port (current-output-port)))
> > +  (let* ((type (color-scheme-type cs))
> > +    (control (color-scheme-control cs))
> > +    (sign (assoc-ref *pre-sign* type))
> > +    (color (color-scheme-color cs))) ;; (car color) is the color, (cdr 
> > color) is the control
> 
> Is that comment necessary here?

Ah~thanks for pointing out, it's the obsolete design.

> > +    (if sign
> > +   (display (color-it-inner color sign control) port)  ;; not array
> > +   (display (color-array-inner cs) port) ;; array complecated coloring
> > +   )))
> 
> Parentheses should be at the end of the previous line.
> End-of-line comments should be introduced with a single semicolon.
> 

Fixed them all, comments convention & suspended right-paren. ;-)


> > +(define is-sign?
> > +  (lambda (ch)
> > +    (char-set-contains? char-set:punctuation ch)))
> 
> Perhaps ‘delimiter?’ would be a better name?
> 

Agreed~

> > +(define color-array-inner
> > +  (lambda (cs)
> > +    (let* ((colors (color-scheme-color cs))
> > +      (control (color-scheme-control cs))
> > +      (sign-color (car colors))
> > +      (attr-color (cadr colors))
> > +      (str (color-scheme-str cs))
> > +      (attrs (string->list 
> > +              (call-with-input-string str (lambda (p) (read-delimited "(" 
> > p))))))
> > +      (call-with-output-string
> > +       (lambda (port)
> > +    (for-each (lambda (ch)
> > +                (let ((color (if (is-sign? ch) sign-color attr-color)))
> > +                  (display (color-it-inner color (string ch) control) 
> > port)))
> > +              attrs)
> > +    (display (color-it-inner sign-color "(" control) port) ;; output 
> > right-parent
> > +    )))))
> 
> Wow, this is hairy and heavyweight.
> 

Yes, but the aim of colorized-REPL is to show more friendly UI to the
users, it dropped up some efficiency designs.
I do considered a more efficient way to print simpler colorized-array,
but I decide to print it like this finally. I believe a more clear
array-print-result make users hate arrays less, since it's too
complicated in Guile, though we don't have to use it in complicated way
all the time.


> > +;; I believe all end-sign is ")"      
> > +(define* (post-print cs #:optional (port (current-output-port)))
> > +  (let* ((c (color-scheme-color cs))
> > +    (control (color-scheme-control cs))
> > +    (color (if (list? (car c)) (car c) c))) ;; array has a color-list
> > +    (display (color-it-inner color ")" control) port)))
> 
> Instead of the comment above, add a docstring that says “Write a closing
> parenthesis...”.
> 

> > +(define *custom-colorized-list* (make-fluid '()))
> 
> It’s better to use SRFI-39 parameters (which are in core now).
> 

Well, fluid is easier. ;-P

> > +(define (class? obj)
> > +  (is-a? obj <class>))
> 
> It’s enough to use ‘struct?’ since objects are structs.  This way you
> get rid of the dependency on GOOPS.
> 
> > +(define (arbiter? obj)
> > +  (is-a? obj <arbiter>))
> 
> Who care about arbiters?  :-)
> 
> > +(define (unknown? obj)
> > +  (is-a? obj <unknown>))
> 
> This one isn’t needed: it’s just the ‘else’ case.
> 

Agreed~

> > +(define *colorize-list*
> > +  `((,integer? INTEGER ,color-integer (BLUE BOLD))
> > +    (,char? CHAR ,color-char (YELLOW))
> 
> Instead of a list, can you instead define a record for each token color
> setting?
> 
>   (define-record-type <token-color>
>     (token-color name pred color-proc color)
>     token-color?
>     ...)
> 
>   (define %token-colors
>     `(,(token-color 'integer integer? color-integer '(blue bold))
>       ...))
> 

Hmm...if it's unnecessary, I prefer be lazy...

> > +(define type-checker
> > +  (lambda (data)
> > +    (call/cc (lambda (return)
> > +          (for-each (lambda (x)  ;; checkout user defined data type
> > +                      (and ((car x) data) (return (cdr x))))
> > +                    (current-custom-colorized))
> > +          (for-each (lambda (x)  ;; checkout default data type
> > +                      (and ((car x) data) (return (cdr x))))
> > +                    *colorize-list*)
> > +          (return `(UNKNOWN ,color-unknown (WHITE))))))) ;; no suitable 
> > data type ,return the unknown solution
> 
> Using call/cc here is fun but excessively bad-style.  :-)
> 
> Try something like:
> 
>   (or (any ... (current-custom-colorized))
>       (any ... %token-colors)
>       (token-color 'unknown (const #t) color-unknown '(white)))
> 

But in this context, I need a finder which could return the result, not
just predicate true/false, 'any' seems can't provide that.
Any other suggestion?

> Also, the name is misleading.  Should be called ‘data->token-color’ or
> something like that.
> 

Agreed~

> > +(define string-in-color
> > +  (lambda (str color)
> > +"@code{string-in-color}.  The argument @var{color} is the color list.
> > +   Example: (string-in-color \"hello\" '(BLUE BOLD))" 
> 
> No Texinfo escapes in docstrings.
> 

Agreed~

> Thanks,
> Ludo’.

It's here now:
https://github.com/NalaGinrut/guile-colorized/blob/upstream/ice-9/colorized.scm

And I'm waiting for any help to write the test-case.

Thanks!






reply via email to

[Prev in Thread] Current Thread [Next in Thread]