|

Colors in GHCi

Posted on Saturday, 27 February 2010 at 12:10.

Whenever you load a Haskell file into GHCi, it will either tell you your modules loaded fine, or that there were some errors. Sebas came with the awesome idea of coloring these messages green and red, respectively. Here is how to do this:

Create a script that looks like this:

#!/usr/bin/env bash

GREEN=`echo -e '33[92m'`
RED=`echo -e '33[91m'`
RESET=`echo -e '33[0m'`

/usr/bin/ghci "${@}" |
  sed "s/^Failed, modules loaded:/${RED}&${RESET}/g;s/^Ok, modules loaded:/${GREEN}&${RESET}/g"

If your ghci is not located in /usr/bin, change the path in the script accordingly. If you want, you can name your script ghci so that it takes over the original one. Just make sure its location appears in your PATH variable before the location of the true ghci.

If all goes well, you should now see colors whenever you load your modules:

% ghci Sirenial.Merge
...
Failed, modules loaded: Sirenial.Query.

And then when the bug has been fixed:

% ghci Sirenial.Merge
...
Ok, modules loaded: Sirenial.Merge, Sirenial.Query.

This has only been tested on Terminal.app in Snow Leopard. If it doesn’t work for your system, please leave a comment, with—if possible—a fix.

There is a small issue: sometimes sed delays the colored parts a bit, causing your prompt to be printed before the success or error message. Again, if you know a fix, please comment.

Comments

By Tom Lokhorst on Saturday, 27 February 2010 at 17:26:

This is very useful!

I’ve updated the script to also highlight warnings (as I usually launch ghci from vim with -Wall):

#!/usr/bin/env bash

YELLOW=`echo -e ’33[93m’`
GREEN=`echo -e ’33[92m’`
RED=`echo -e ’33[91m’`
RESET=`echo -e ’33[0m’`

/usr/bin/ghci “${@}” 2>&1 |
sed “s/ Warning:/${YELLOW}&${RESET}/g;s/^Failed, modules loaded:/${RED}&${RESET}/g;s/^Ok, modules loaded:/${GREEN}&${RESET}/g”

I’m not happy with the fact that this merges the stdout and stderr, but I don’t know of a better way to do this.

By Erlend on Saturday, 27 February 2010 at 19:12:

Cool. Thanks!
Works perfectly on openSuse 11.2. :-)

By Orphi on Monday, 01 March 2010 at 12:59:

I still think GHCi should have this built-in. We already have ansi-terminal on Hackage, which does this in a [ahem] *portable* way. (Your examples don’t work on Windows, because it fails to grok ANSI escape sequences.)

By Nikolas Mayr on Wednesday, 03 March 2010 at 14:39:

Why are you using

#!/usr/bin/env bash

intead of

#!/bin/bash

?

By Martijn on Thursday, 24 June 2010 at 10:24:

@Orphi Yes, I agree. It shouldn’t be too hard.

@Nikolas Good question. I have no good reason for it.

By enoksrd on Thursday, 16 September 2010 at 03:28:

Nice hack! But what I really wanted was to colorize the prompt, so that I could easily tell where long output (e.g. from :browse) started. I don’t understand why, but the sed trick doesn’t work for the prompt. But setting an ansi colored prompt in the ghci conf worked:

echo -e :set prompt ‘”33[32;1m%s33[34;1m>33[0m “‘ > ~/.ghc/ghci.conf

By enoksrd on Thursday, 16 September 2010 at 03:30:

Note: the backslash-zero sequences (‘s; double backslash here (\\), hope that works …) disappeared in my and Tom’s comments.

By Yifan Yu on Tuesday, 28 September 2010 at 03:53:

This works fine. But when I try to edit a file in ghci (`:set editor vim’ was performed) by using:

:e Somefile.hs

Vim gives a warning: Output is not to a terminal, and the file could not be edited.

Is there a way to handle this?

By Joel on Saturday, 10 September 2011 at 22:37:

Why not go all out and style the output as well? Here’s what I came up:

#!/bin/sh

# Colors
red=`echo “33[91m"`
green=`echo "33[92m"`
yellow=`echo "33[93m"`
blue=`echo "33[94m"`
purple=`echo "33[95m"`
cyan=`echo "33[96m"`

# Bold colors
bold=`echo "33[1m"`
bold_red=`echo "33[1;91m"`
bold_green=`echo "33[1;92m"`
bold_yellow=`echo "33[1;93m"`
bold_blue=`echo "33[1;94m"`
bold_purple=`echo "33[1;95m"`
bold_cyan=`echo "33[1;96m"`

# Color reset
reset=`echo "33[0m"`

# Patterns
double_colon="s/::/$red&$reset/;"
rocket="s/=>/$red&$reset/;"
left_arrow="s//$red&$reset/;"
strings="s/"[^"]*”/$yellow&$reset/g;”
chars=”s/’[a-zA-Z]*’/$purple&$reset/g;”

exec “`which ghc`” –interactive ${1+”$@”} |
sed “$double_colon
$rocket
$right_arrow
$left_arrow
$strings
$chars”

You could really take this pretty far and style all sorts of things. Numbers however can get a bit dicey since the color codes contain numbers.

Though this feels a bit hackish, it works well enough for me.

Leave a comment!

Martijn loves to receive comments! Add yours by filling out the fields below.