jaff v0.0.4
Jaff Appends and Filters Files
Jaff is a small macro language that allows conditional filtering of Files through external programs and Javascript or Coffeescript functions in a way similar to commandline pipes between programs. Jaff scripts can be written to cumulatively apply filters while expanding variables in the text. Here is an example:
#begin coffee
indent = (lines) ->
return lines.map (line) ->
return ' ' + line
folder = "/etc"
#end
#if process.env.TEST
foo
#else
bar
#end
Contents of the {folder} folder:
#filter !indent
# filter nl
# filter grep rc$
# run ls -la {folder}
# end
# end
#endRunning this will print foo if process.env.TEST is defined and bar
otherwise. Next it will list the contents of the /etc folder, filter out files
ending with "rc", prepend a line number to each line and finally indent these
lines. The output might look like this:
$ jaff example
bar
Contents of the /etc folder:
1 -rw-r--r-- 1 root root 657 Mar 18 2012 bash.bashrc
2 -rw-r--r-- 1 root root 3095 Jan 9 21:22 drirc
3 -rw-r--r-- 1 root root 714 Nov 3 2011 inputrc
4 drwxr-xr-x 2 root root 4096 Mar 8 2013 lirc
5 -rw-r--r-- 1 root root 4243 Dec 28 09:18 mail.rc
6 -rw-r--r-- 1 root root 1347 Dec 9 21:55 quilt.quiltrc
7 -rw-r--r-- 1 root root 3312 Jul 14 2011 screenrc
8 -rw-r--r-- 1 root root 1437 Apr 25 2011 slsh.rcInstall
Using npm:
npm install -g jaffInvocation
This program takes a single argument:
$ jaff <filename>Alternatively a script can be written invoking jaff via the shebang line:
#!/usr/bin/env jaff
#begin coffee
foo = "This is foo"
#end
...Keywords
The following keywords are defined: begin, end, if, elif, else,
include, filter and run. Keywords appear following a comment at the
beginning of a line. Both Javascript // and Coffeescript comments # are
accepted and there may be whitespace between the comment and the keyword.
begin <js|coffee> ... end
Start a block of Javascript or Coffeescript code. Variables and code can be
referenced in variable expansions outside of the begin block.
Note that all variable expansions are interpreted as Javascript, even if they
have been defined in a begin coffee block. See section variable expansion.
Also note that begin blocks are cumulative meaning that all begin blocks will
use the same environment to place functions and variables.
The addition of begin blocks containing javascript code was inspired by
PYM - A Macro Preprocessor Based on Python.
end
The end keyword ends the nearest begin, if or filter block.
if <condition>, elif <condition>, else ... end
Evaluate <condition> as Javascript. If it evaluates to a truthy value the
lines immediately following this branch of the conditional up to the next
else, elif or end statement are included in the output.
#if 'foo' === 'bar'
Not shown
#elif 1
This is shown
#else
Not shown
#endinclude <filename>
Attempt to include the file in <filename>. If the file does not exist try
if the file can be found in parent paths up to the root.
- TODO add
include! <filename>to include raw data?
run <command>
Run the external program in <command> almost1 as if it were invoked on the
command line.
filter <command|!function> ... end
Run an external program like the run command and pipe the lines until end
through this command:
#filter nl
One
Two
#endNote that filtering through an external program is subject to shell escape limitations. 1
If the <command> is prefixed with an exclamation mark, command is taken to be
a function to filter commands through as in the example at the top of this
document.
[1] This is not quite correct at the moment because shell expansion is not taken
correctly into account.
Variable expansions
{code}
Run code as javascript. The code may reference variables and functions declared
in begin ... end blocks. This code may reference variables and functions that
are globals in node as well as some special variables:
__versionThe version of jaff__argvThe arguments passed to the script__quotesChange code reference quoting characters
The default quoting of a reference is {} but may be changed using the
__quotes() function in a begin block:
__quotes '[[', ']]'