Ansi colour output in drracket

I run the following in drracket:

#lang racket/base
(require ansi-color)
(printf "plain text~n")
(with-colors 'red (lambda () (printf "red text~n")))
(with-colors 'green (lambda () (printf "green text~n")))

In the output window all the printf'd text appears in purple on a black background,, which are my usual default colours.
None of it is red or green.
The ansi colour escapes show up in purple too, introduced with a boxed hexadecimall character.

In case it is relevant, I use drracket in dark mode, and I have configured it to present parantheses in code in yellow -- so I can see these all-important charcters.

I use printf while debugging, and I'd like to use colour to emphasize milestones in printf trace output.

-- hendrik

Offhand, I don't think DrRacket supports ANSI escape sequences; I
think ansi-color targets ANSI-compatible terminal devices.

That is why I've implemented ANSI pict renderer for uni-table:

See Unicode Tables and 5 Pict Renderer for more information.

The core of the algorithm used is in private/sgr-pict.rkt · master · Dominik Joe PantĹŻÄŤek / uni-table · GitLab and the routines to convert ANSI sequences to sgr-list as provided by 1 Text Output are in private/ecma-sgr.rkt · master · Dominik Joe PantĹŻÄŤek / uni-table · GitLab

Not perfect, but it is a start for using ANSI sequences in DrRacket.

2 Likes

I've now checked that ansi-color works fine outside DrRacket when the standard output goes to an uxterm terminal. But not to DrRacket's output panel.

Dominik's pict hack looks useful, but not for my purpose. I'm looking for a way to write out printf-style debugging output in a visually distinctive manner, mixed in with all the other standard-output a program produces.

There has to be some mechanism for colour in DrRacket's outut panel, because DrRacket uses colour in its welcome and error messages.

The DrRacket interactions panel indeed does not appear to recognise the ANSI colour escape sequences. So I'll give up on that tack, unless that gets certified as a bug.

But DrRacket itself uses colour on the interactions panel -- so there has to be a mechanism for it.

In particular, error messages show up in red, my own printf output shows up in purple, and prompts by the REPL show up i white. (I'm still using dark mode, so white is a reasonable colour choice.)

So there is a way to affect colour in the interactions window, and it's probably not ANSI escape sequences.
I'm just trying to find out how to do it myself.

-- hendrik

Unfortunately, it is not really a general facility that's available to the programs running in the IDE. If you print to stdout, it comes out in purple. If you print to stderr, it comes out in red. To get the blue, you need to print to a secret port that you don't have access to.

If you want colored output, I think the best approach is to use another library somehow; perhaps one that makes picts or one that opens a separate window for your fancier output. There's not really a middle ground currently.

1 Like

Dr Racket just colors REPL output based purely on the port it's coming from. So you can choose between two colors that way, but it would be hacky. (There's also drracket:rep:current-value-port but I think you’ll find it’s difficult to use without causing weird DrRacket behavior.)

Oh, @mflatt suggested off-list that one could use string snips and styles. I'm not sure this is a good approach as there are limitations (like I'm not seeing how to get the right font) but here is some code that does a thing:

#lang racket
(require racket/snip)

(define (display-lines/color str color)
  (define sd (make-object style-delta%))
  (send sd set-delta-foreground color)
  (for ([str (string-split str "\n")])
    (define snip (make-object string-snip% str))
    (send snip set-style (send the-style-list find-or-create-style
                               (send the-style-list basic-style)
                               sd))
    (write-special snip)
    (display "\n")))

(display-lines/color "ab\ncd" "blue")
(display-lines/color "ab\ncd" "orange")
(display-lines/color "ab\ncd" "purple")
(display-lines/color "ab\ncd" "green")

Aha, here's how to get the right font.

#lang racket
(require racket/snip framework)

(define (display-lines/color str color)
  (define sd (make-object style-delta%))
  (send sd set-delta-foreground color)
  (define base
    (send the-style-list new-named-style
          "Standard"
          (send the-style-list basic-style)))
  (define colored
    (send the-style-list find-or-create-style
          base
          sd))
  (for ([str (string-split str "\n")])
    (define snip (make-object string-snip% str))
    (send snip set-style colored)
    (write-special snip)
    (display "\n")))

(display-lines/color "ab\ncd" "blue")
(display-lines/color "ab\ncd" "orange")
(display-lines/color "ab\ncd" "purple")
(display-lines/color "ab\ncd" "green")
1 Like