Fabric: ANSI Color support

Created on 19 Aug 2011  ·  19Comments  ·  Source: fabric/fabric

Description

  • Easy ability for both internal code and users to specify that (at least) full lines are a given ANSI color, if not words or arbitrary parts of output strings.
  • Global flag for disabling ANSI so that anyone who cares can turn it off (e.g. for someone scripting Fab itself, or whatever.)
  • Have various internal output calls make use of color so that e.g. "executing task X" lines are blue, running lines are...uh...yellow? green?, aborts/errors are red, and etc etc etc.

Be nice to leverage an external library for this instead of reinventing the wheel for the actual mechanics -- see what's out there.


ok, there is a handful of prior art:

General ideas:

  • Unary functions. print(red(blink("text") + "non blinking text")) etc. Seems easy enough to use, possibly some tricky spots in actual implementation -- check Term::ANSIColor (source) for ideas, maybe.
  • Dead simple mapping of the codes to constants/vars. (Possibly why nobody's done a lib for this -- it's dead simple.) E.g. print(RED + BLINK + "text" + CLEAR + RED + "non blinking text" + CLEAR).

ANSI code maps:

More notes:

  • there are apparently issues with this on Windows terminals, so may want/need an automatic if win32: env.disable_colors = True sort of thing.
  • have regular expressions that can trigger certain highlights, so that e.g. stdout/stderr matching "error messages" can be colored red or whatnot. I.e. "Permission denied" and the like. (see also: capistrano-colors)
  • if/when we do logging (#57) it may make sense to turn colors off for the logs -- or make it an option in case anybody actually wants the ANSI codes in their log files.

Current status:

  • Implemented a barebones in-house lib as fabric.colors in Fabric 0.9.2
  • Not using it anywhere in Fabric core yet; only place I use it myself is in one seldom used task
  • May still be worth using a 3rd party lib if/when we get around to seriously leveraging color in Fabric itself

    • However, unless a bridge is provided to the current included colors module, doing so is likely to break backwards compatibility

    • So either write such a bridge, don't bother using a 3rd party lib, or wait to do so till 2.x


Originally submitted by Jeff Forcier (bitprophet) on 2009-11-11 at 05:46pm EST

Relations

  • Related to #151: Make fabfile print() statements controllable via output controls
  • Related to #240: Use background colors in fabric.colors
  • Related to #57: Support full logging to file
  • Related to #363: Consider integrating Clint
Feature UI

Most helpful comment

For people like me running Windows and trying to get things like run("ls --color") to look good, I'd like to note that this works:

  1. Install the colorama module (pip install colorama)
  2. Add this code to fabfile.py:
try:
    import colorama
    colorama.init()
except ImportError:
    print "WARNING: Some tasks may be hard to read unless you install colorama."

All 19 comments

Jeff Forcier (bitprophet) posted:


Started playing around with this. One possible color scheme, using magenta hostnames, green tasks and blue running lines:

colors

(You can ignore the actual text, it's just duplicated output from a real task run. No, the domains involved can't be accessed publicly :))


on 2009-11-12 at 02:10pm EST

Jeff Forcier (bitprophet) posted:


Another example, with additions:

  • yellow for stderr
  • red for abort messages (probably also warnings.)

colors2


on 2009-11-12 at 02:34pm EST

Jeff Forcier (bitprophet) posted:


Also, I've never said I don't use stupid crap as test messages :) no offense to anybody's mother.


on 2009-11-12 at 02:35pm EST

Nick Trew (vxnick) posted:


Consider adding env.always_use_bold (or similar).


on 2010-04-14 at 10:06am EDT

Kenneth Reitz (kennethreitz) posted:


I highly recommend colorama:

http://pypi.python.org/pypi/colorama


on 2010-10-11 at 10:49pm EDT

Rick Harding (mitechie) posted:


Kenneth Reitz wrote:

I highly recommend colorama:

http://pypi.python.org/pypi/colorama

+1 on colorama, very nice and easy to wrap so you make it optional. If colorama is installed you can output with colors, else plain.


on 2011-03-14 at 11:25am EDT

fabulous is a great library to work with colors in Python! I don't know colorama, but if we only need 8-bit colors, I can do a function to do it with just 20 lines of code (and will not depend on another library). But if we need more complete support, I think fabulous will be a great choice.

FWIW I am currently a huge proponent of 256-color terminals :) I will add fabulous to the list up top, thx!

my custom color function.

def colorize(msg, fg='green', bg='black', style='reset'):
    color_map = dict(black=0, red=1, green=2, yellow=3, blue=4, magenta=5, cyan=6, white=7)
    style_map = dict(reset=0, bold=1, underscore=4, blink=5, reverse=7, conceal=8, underline=4)
    return '\033[3%d;4%d;%dm%s\033[0m' % (color_map[fg], color_map[bg], style_map[style], msg)

554 includes a screenshot and possibly some code, to be considered alongside the above.

This afternoon, I had the idea to colorize the hostnames based on the hostname itself. Such that each hostname has a different color.

I _am_ going to fool around with this. Not sure where it goes.

I read through this issue and it seems that work on colorizing the output has a bit trailed off. Any particular reason for that? Has it somehow been abandoned?

I'll gladly give it a shot.

I've looked at some of the libraries mentioned above, and I am a bit sceptical. So far, fabulous is the one which I am least worried about. But I am not sure if it will work on windows (mainly because of the file named xterm256.(py|c)).

I also stumbled across urwid.

The reason for my scepticism is that all those libraries look to me like they're trying to do too much, if the only thing we need is colored text.

My go-to solution was a very simple snippet written by Nadia Alramli. Unfortunately, her blog is no longer online, but after a bit of googling, I came across her github page. It's very simple, and does what it should. Although I have never tested this on windows either.

There was also a really nice recipe on the ActiveState cookbook which I used from time to time. But I am unable to find this back. I will have to continue googling.

@exhuma Thanks for poking, notes greatly appreciated! I doubt Fab 1 will see heavy colorization (tho I think I merged a "show errors in red" thing recently? Memory hazy) but plan is to have it in Fab 2 from the get-go, where the output mechanisms should be written more intelligently. So this info is still useful.

No worries... and thanks for the update. I mostly forgot about this post... I do too much, and too many things in parallel :(

But, in the meantime, I was fiddling around with blessings as well. And it seems to "just work". Even 256 color support (even if undocumented). My fumblings are here: https://github.com/exhuma/blessings/compare/256-colour-support Output on the console looked fine.

Also, regarding my previous statement that all the mentioned libraries try to do too much, is _less_ true for blessings. It's quite minimalistic.

Yea blessings stood out as being pretty rad when I last looked at it. Will try and remember to look at it first for Fab 2 :)

FWIW blessings doesn't support Windows, colorama does (This is what we're using in pip for that). Or rather blessings needs colorama to get color on Windows.

For people like me running Windows and trying to get things like run("ls --color") to look good, I'd like to note that this works:

  1. Install the colorama module (pip install colorama)
  2. Add this code to fabfile.py:
try:
    import colorama
    colorama.init()
except ImportError:
    print "WARNING: Some tasks may be hard to read unless you install colorama."

Any updates on this? I am am looking for an option to colorize the remote commands. So far I see that ANSI escapes from remote commands are correctly displayed.

Still, I would like to be able to change the output of the prefix command and add ANSI escapes to it, maybe different color for local and remote, also different color for stderr (err) vs stdout (out).

I've added PR pyinvoke/invoke#663 to support this. Notice that this is primarily a PR to get the ball rolling again. It does not use any of the mentioned libraries because it is not yet clear to me how they should be integrated. See the notes on pyinvoke/invoke#663

I am absolutely willing to replace my own code with a third-party library.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

haydenflinner picture haydenflinner  ·  5Comments

26huitailang picture 26huitailang  ·  3Comments

Grazfather picture Grazfather  ·  4Comments

shadyabhi picture shadyabhi  ·  5Comments

peteruhnak picture peteruhnak  ·  4Comments