2008-04-11

Please to dance round for the one called the Greenbar

Inspired by what I can only guess is my unsightly python version of greenbar, drewp has created a version with 100 percent more fun to look at. Thanks!

Drewp's version (see here) is what I always hoped greenbar would grow up to look like when it was written by someone who was not me. I wish the enumerate thing would work - I tried that originally too, but no, it's not to be. It works fine if the input is a regular file, but not when you want to read the stdout of another process. There's internal buffering in python that chunks up the input making the most common use of greenbar, watching a growing log file, hopeless.

Combining the two versions results in a super hybrid that works and is easy on your eyes. Tada!
#!/usr/bin/python -u

import sys

try:
pat = sys.argv[1]
except IndexError:
pat = None

lineno = 0
while 1:
line = sys.stdin.readline()
if not line:
break
if (pat and pat in line) or (not pat and lineno % 2 == 0):
print "\x1b[7m%s\x1b[0m" % line.rstrip()
else:
print line,
lineno = lineno + 1
P.s. The original awk version was shorter still. If I find a copy, I'll bury it so that python looks better.

5 comments:

Anonymous said...

I saw your original post on this, and I was thinking that the best way to do this would be with a generator-adapter. (I had some example code but blogger doesn't seem to like the pre tag)
It'd take an iterator and yield values from that iterator plus an alternating value. You could then iterator over sys.stdin and alterate between plain formatting and green formatting.

Anonymous said...

My original awk version was shorter, I think, but it didn't include the pattern matching functionality (a very cool idea).

Given that it was awk, it probably also didn't use unbuffered I/O.

I really wanted, someday, to use terminfo to do the inversing rather than hardcoded VT100 escape sequences. Get to work. :-)

Anonymous said...

Thanks for taking my untested version and actually exposing it to the real world :)

What is the false value that readline() eventually returns? IIRC it's "", so you may be able to use something like this:

for lineno, line in enumerate(iter(sys.stdin.readline, "")):

John Speno said...

Drew,

You're welcome. Thank YOU for being my brain and thinking up the solutions I want to be thinking of. It's nice to wake up in the morning and find the answers in your inbox.

Your iter() solution works just fine and makes the code even more pythonic.

Justin A said...

How about this:

green = False
...
if (pat and pat in line) or (not pat and green):
...
green = not green