Sunday, September 1, 2013

Terminal Colors in Dart


Dart's package manager, affectionately known as Pub is pretty darn slick. The newest feature, pub serve is a nifty little web server that makes it blindingly simple to run example code. The pub serve web server is so slick, that I would like to borrow one or two features from it.

Tonight, I hope to figure out how they do the very pretty logging:



I do not necessarily need the pointer to the actual location on the file system—that makes much more sense in the confines of Pub, which sometimes needs to play tricks to make certain top-level directories behave as expected. Rather, what I would like to have is the color coding of successful… and not so successful requests:



Sure, this is just terminal escape codes, but maybe there is something reusable at play here.

It turns out that, no, there is nothing reusable. These are just hard-coded escape codes in strings. Well, even if they are not reusable, they are eminently copy-able.

I need this in two locations: my plummbur-kruk “real fake” server for testing and the dart comics. OK “need” is a strong word, but I would like to see this in the log output for both. I spend a little bit of time refreshing my memory about terminal escape codes with the intention of building a library… but thankfully I find ansicolor-dart and don't have to roll my own. The Dart community is so awesome.

I add this to plummbur-kruk's dependencies:
name: plummbur_kruk
description: A real pretend server for testing.
# ...
dependencies:
  # ...
  ansicolor: any
Then import the ansicolor package:
library plummbur_kruk;
// Other imports here...
import 'package:ansicolor/ansicolor.dart';

//...
The AnsiPen class in ansicolor turns out to have a very nice API. I can create a green “pen” for writing success strings and a red pen for failures. I then make use of them in the logStatus() method, which logs response status codes:
final AnsiPen red = new AnsiPen()..red(bold: true);
final AnsiPen green = new AnsiPen()..green(bold: true);

logStatusCode(HttpResponse res) {
  var code = res.statusCode;
  if (code > 399) return red(code);
  return green(code);
}
What is nice about these “pens” is that the strings that they write start with the necessary escape codes and, just as importantly, end with the clear escape sequence, that returns colors to normal. While I was thinking of rolling my own library, I was going to require the programmer to manually send the clear escape sequence. This is much better.

After a quick Pub install to add my newly declared dependency:
➜  plummbur-kruk git:(master) ✗ pub install
Resolving dependencies...................
Downloading ansicolor 0.0.9 from hosted...
Dependencies installed!
I am ready to try it out. Fortunately, the test suite generates both 200 and 400 HTTP response codes, so I already have the perfect place to give it a go:



Yay!

Another nice feature of ansicolor is that it is possible to set the color_disabled property to true in order to prevent the escape codes from cluttering up log files in environments that will not support xterm color sequences—like continuous integration servers.

For that, I read the shell environment for the CI shell variable. If set to “true” I disable color output globally:
setEnvOptions() {
  if (Platform.environment['CI'] == 'true') color_disabled = true;
}
And that works right away:



I confess that I am a little sad to have not found an excuse to write an xterm escape code library myself. That sadness is easily outweighed by the very nice library that John Thomas McDole had made.


Day #861

No comments:

Post a Comment