incava.org

About

It seems that every movie trailer begins "In a world..." Similarly, the narrative of most of my programs begins "This started as a Perl script".

Inspired by a couple of the examples in the first edition of Programming Perl, I decided to write my own version of cgrep (which shows lines before and after a match). This became bfgrep, the "b" and "f" being from "before" and "after", and also somewhat in reference to the BFG2000 in Doom, a favorite late-night-at-work game-of-choice where I worked at the time.

So for a while, this program was great. I could search for something like '/\b\w{4}\d?\s*==\s*\d+/' and get 20 lines of context around it. But the problem was that I couldn't easily see what actually matched. Inspired by tcgrep (from Programming Perl and the Perl Cookbook), I added ANSI escape sequences to this to highlight what the regular expression matched.

bfgrep was useful, but its code was ugly. I'd wanted to rewrite it, so when I began learning Ruby, I took it as an opportunity. To my surprise, the resulting program was much more elegant than I would have expected. A possibility evidenced itself now, that of being able to combine regular expressions. I'd done so with statements like:

'/foo/ && /bar/'

and

'/foo/ || /bar/'

but those weren't enough. And I especially wanted to be able to match over adjacent lines, since too often what I was searching for would be on two lines.

Thus, the --or and --and options were created. The --or option was trivial, since that executes on a single line, and it also proved fairly easy to implement the --and functionality to span an arbitrary number of lines. It was also possible to nest these expressions, so that an --or expression could be within an --and expression, or vice versa. I hadn't really counted on that, but every good programmer likes recursion, and I do too.

When I began the Ruby implementation, I didn't want to reuse the bfgrep name, especially since I wanted to keep it in its original state, to remind me of my nascent Perl days. This program is focused on two aspects of context -- for contextual matching, and for producing context around a match -- so I searched through the Jargon Dictionary for this term. "glark" was one of the matches, and it satisfied my other tests: easy to type, similar to "grep", and not a common term.

Over time, I have changed glark to be more like grep, specifically, to provide most of the options and functionality. Other than ls and cd, I probably run glark more than any other program, as some of my aliases (bash, zsh) may suggest:

# Java files
alias fj="find . -name '*.java' | xargs glark $*"

# Text files
alias ft="find . -name '*.txt' | xargs glark $*"

# C, C++, Lex and Yacc files
alias fc="find . \( -name '*.h' -o \
                    -name '*.cpp' -o -name '*.c' -o \
                    -name '*.y' -o -name '*.l' \) | xargs glark $*"

# All files
alias fall="find . -type f | xargs glark $*"

I hope that it is of similar use to others. But I still use the verb "grep".

Valid HTML 4.01!

Valid CSS!