unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
From: Nala Ginrut <nalaginrut@gmail.com>
To: "Ludovic Courtès" <ludo@gnu.org>
Cc: guile-devel <guile-devel@gnu.org>
Subject: Re: [PATCH] Colorized REPL
Date: Tue, 22 Jan 2013 00:10:54 +0800	[thread overview]
Message-ID: <CAPjoZoeOMUkREH09XEkwACSBpy7OWOR8LbxZ_+k_wqnPnM9L-g@mail.gmail.com> (raw)
In-Reply-To: <87k3rj7psf.fsf@gnu.org>


[-- Attachment #1.1: Type: text/plain, Size: 10788 bytes --]

hi folks!
test-case is ready. I've tested, it works and passed all items.
Please review it.
I'll work on manual for it ASAP.

Thanks!


On Fri, Jan 11, 2013 at 10:33 PM, Ludovic Courtès <ludo@gnu.org> wrote:

> Hi Nala,
>
> Thanks for the update.
>
> Nala Ginrut <nalaginrut@gmail.com> skribis:
>
> > On Fri, 2013-01-04 at 15:06 +0100, Ludovic Courtès wrote:
>
> [...]
>
> >> Nala Ginrut <nalaginrut@gmail.com> 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'?
>
> An inner REPL (info "(guile) Error Handling").
>
> >> > 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.
>
> Hmm, there’s other info that helps debugging, such as location info of
> the procedure, but OK.
>
> >> 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?
>
> See under test-suite/tests/*.test.  There’s a small set of constructs to
> express unit tests, such as ‘pass-if’.
>
> >> 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.
>
> That’s not the question. ;-)  It doesn’t justify pulling in all of R6RS.
>
> >> > +(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.
>
> Ping!
>
> >> > +(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...
>
> Which implementation?  I still think that using a disjoint type for
> colors would be better than symbols.  Also, this is something part of
> the API, so we can’t just leave it for later discussion.
>
> >> > +(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.
>
> Surely, but it mixes concerns.  Can you try to make sure ‘color-scheme’
> objects are just that, color scheme?
>
> >> > +(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.
>
> String ports are seekable, right.  However, seeking here seems like a
> hack: you could just as well adjust the printer to not write that extra
> character instead of writing it and then seeking backwards.  WDYT?
>
> >> > +    (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. ;-)
>
> There are still many conventions wrong, such as procedure definitions,
> global variable names, missing docstrings, etc.  Could you try to fix
> them as well?
>
> >> > +(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.
>
> When we include features in Guile, we review the /implementation/ of
> that feature in the hope that it’ll be reasonably pleasant our eyes.
> This particular procedure could surely be made more pleasant to the eye.
> WDYT?
>
> >> > +(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...
>
> Using disjoint types is beneficial in helping catch programming errors,
> and clarify what the objects being worked on are.
>
> Again, this thing is part of the API, so it’s worth thinking it through.
> Using a record makes it easier to eventually extend the thing.
>
> So you may consider it necessary.
>
> >> > +(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.
>
> Sorry, it should be ‘find’, not ‘any’.
>
> > It's here now:
> >
> https://github.com/NalaGinrut/guile-colorized/blob/upstream/ice-9/colorized.scm
>
> (Next time please post the code; this facilitates review.)
>
> It seems it’s improved (thanks!), but I would like to see the API issues
> and stylistic problems to be addressed.
>
> > And I'm waiting for any help to write the test-case.
>
> If you have specific questions as you work on it, I’m happy to help.
> Otherwise, I won’t offer to write the actual tests.
>
> BTW, before it can be integrated, it will also need to have a section in
> the manual, probably under “Using Guile Interactively”.  Could you work
> on it?
>
> I reckon I’m asking for some extra work, but I think it’s important to
> not compromise on Guile’s current standards.
>
> Thank you!
>
> Ludo’.
>

[-- Attachment #1.2: Type: text/html, Size: 14414 bytes --]

[-- Attachment #2: colorized.test --]
[-- Type: application/octet-stream, Size: 2728 bytes --]

;;;; colorized.test --- test (ice-9 colorized) module -*- scheme -*-
;;;; 
;;;; Copyright 2012 Free Software Foundation, Inc.
;;;; 
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 3 of the License, or (at your option) any later version.
;;;; 
;;;; This library is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;;;; Lesser General Public License for more details.
;;;; 
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

(define-module (test-suite test-ice-9-colorized)
  #:use-module (test-suite lib)
  #:use-module (oop goops)
  #:use-module (srfi srfi-9)
  #:use-module (ice-9 colorized))

;; enable colorized-REPL test printer
((@@ (ice-9 colorized) enable-color-test))

;;;
;;; colorzed object test
;;;

(define (test-me obj)
  (pass-if "OK" 
           (equal? (call-with-output-string
                    (lambda (port) (colorize obj port)))
                   (object->string obj))))

(with-test-prefix "colorized object tests"

  (with-test-prefix "integer"
    (test-me 123))

  (with-test-prefix "char"
    (test-me #\c))

  (with-test-prefix "string"
    (test-me "hello world\n"))

  (with-test-prefix "list"
    (test-me '(1 2 3 4 5)))

  (with-test-prefix "pair"
    (test-me (cons 1 2)))

  (with-test-prefix "class"
    (test-me <integer>))

  (with-test-prefix "procedure"
    (test-me +))

  (with-test-prefix "vector"
    (test-me (vector 1 2 3)))

  (with-test-prefix "keyword"
    (test-me #:test-me))

  (with-test-prefix "char-set"
    (test-me char-set:ascii))

  (with-test-prefix "symbol"
    (test-me 'test-me))

  (with-test-prefix "stack"
    (test-me (make-stack #t)))

  (with-test-prefix "record-type"
    (define-record-type aaa (make-aaa a) aaa? (a a))
    (test-me aaa))

  (with-test-prefix "inexact"
    (test-me 1.2))

  (with-test-prefix "exact"
    (test-me 1/2))

  (with-test-prefix "regexp"
    (test-me (make-regexp "[0-9]*")))

  (with-test-prefix "bitvector"
    (test-me (make-bitvector 8)))

  (with-test-prefix "array"
    (test-me #2u32@2@3((1 2) (3 4))))

  (with-test-prefix "boolean"
    (test-me #f)
    (test-me #t))

  (with-test-prefix "complex"
    (test-me 3+4i))

  (with-test-prefix "hash table"
    (test-me (make-hash-table)))

  (with-test-prefix "hook"
    (test-me (make-hook))))

  

  parent reply	other threads:[~2013-01-21 16:10 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-05  7:21 [PATCH] Colorized REPL Nala Ginrut
2012-12-05  8:23 ` Daniel Hartwig
2012-12-05  8:48   ` Nala Ginrut
2012-12-05  9:02     ` Nala Ginrut
2012-12-05  9:45     ` Daniel Hartwig
2012-12-05 10:27       ` Nala Ginrut
2012-12-05 11:19         ` Daniel Hartwig
2012-12-06  2:43           ` Nala Ginrut
2012-12-06  3:09             ` Daniel Hartwig
2012-12-06  4:28               ` Nala Ginrut
2012-12-06  5:30                 ` Daniel Hartwig
2012-12-09 23:29           ` Ludovic Courtès
2012-12-10  2:23             ` Nala Ginrut
2012-12-10 21:42               ` Ludovic Courtès
2012-12-11  2:31                 ` Nala Ginrut
2012-12-11 14:13                   ` Nala Ginrut
2012-12-31  8:29                 ` Nala Ginrut
2013-01-04 14:06                   ` Ludovic Courtès
2013-01-04 16:57                     ` Mike Gran
2013-01-09 10:17                     ` Nala Ginrut
     [not found]                       ` <CAN3veRfF5muf+zrfdU7ZogDw=YboW=QRP08zTF6NUeKzDJ__uA@mail.gmail.com>
2013-01-10  8:20                         ` Daniel Hartwig
2013-01-11  6:29                         ` Nala Ginrut
2013-01-11  8:13                           ` Daniel Hartwig
2013-01-11 10:40                             ` Nala Ginrut
2013-01-12  1:01                               ` Daniel Hartwig
2013-01-11 14:33                       ` Ludovic Courtès
2013-01-11 17:20                         ` Noah Lavine
2013-01-11 23:26                           ` Ludovic Courtès
2013-01-12 15:35                             ` Noah Lavine
2013-01-13 21:01                               ` Ludovic Courtès
2013-01-12  0:26                         ` Daniel Hartwig
2013-01-12  9:59                           ` Nala Ginrut
2013-01-12 21:16                           ` Ludovic Courtès
2013-01-26 10:15                             ` Nala Ginrut
2013-01-27 10:06                               ` Andy Wingo
2013-01-28  4:14                                 ` Nala Ginrut
2013-01-28 13:58                                   ` David Pirotte
2013-01-28 14:56                                     ` Nala Ginrut
2013-01-31 14:25                                       ` Nala Ginrut
2013-01-31 14:31                                         ` Nala Ginrut
2013-01-31 16:51                                           ` Nala Ginrut
2013-01-21 16:10                         ` Nala Ginrut [this message]
2013-01-22 11:06                         ` Nala Ginrut
     [not found] <mailman.913570.1354697338.854.guile-devel@gnu.org>
2012-12-05  9:50 ` Daniel Llorens
2012-12-05  9:57   ` Nala Ginrut
2012-12-05 10:11   ` Daniel Hartwig
2012-12-08 21:35   ` Ian Price
2012-12-09  0:50     ` Daniel Hartwig
2012-12-09 10:44       ` Nala Ginrut
2012-12-17  6:04       ` Nala Ginrut
2013-01-21 20:18   ` Andy Wingo
2013-01-28 10:57     ` Nala Ginrut

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

  List information: https://www.gnu.org/software/guile/

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

  git send-email \
    --in-reply-to=CAPjoZoeOMUkREH09XEkwACSBpy7OWOR8LbxZ_+k_wqnPnM9L-g@mail.gmail.com \
    --to=nalaginrut@gmail.com \
    --cc=guile-devel@gnu.org \
    --cc=ludo@gnu.org \
    /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 read-only IMAP folder(s) and NNTP newsgroup(s).