zshbrev allows you to mix zsh code and brev code. Not for polished li’l “eggs” but for your own duct tape and chewing gum hacking and automation. Quick and dirty♥.
The default directory is .zshbrev/
but you can change it with the
--dir
flag to zshbrev
.
Write functions in .zshbrev/functions.scm
and then call zshbrev
.
It’ll create an executable in .zshbrev/bin/
for each function, so
add that directory to your path so you can call brev functions from
zsh, or from any shell for that matter.
You can add this to your .zshrc
to automatically call zshbrev:
if [ ~/.zshbrev/functions.scm -nt ~/.zshbrev/brevbox ]; then
echo -n "Recompiling zshbrev… "
zshbrev
echo done.
fi
The function arguments are read
as sexps, which means symbols for
strings and numbers for numbers. Arguments starting with two dashes
are read as keywords, and arguments with one dash are interpreted as
the leftmost keyword that starts with that same letter, if any
(otherwise it’s passed through).
Arity must match, so if in functions.scm
:
(define (hollywood a b c)
(+ a b c 1000))
And then at your zsh command line:
ellen% hollywood 100 20 4
1124
If you mess up the arity, it’ll bork:
ellen% hollywood 1
hollywood 1
Error: bad argument count - received 1 but expected 3: #<procedure (hollywood a b c)>
followed by a call stack.
You can use match-generics
and all of brev, you can import stuff
like pyffi etc, and the functions can also call each other or
themselves.
(define-some (descseq num)
(cons num (descseq (sub1 num))))
ellen% descseq 4
(4 3 2 1)
Another example:
(define (reverse-even lis)
(reverse (filter even? lis)))
ellen% reverse-even "$(descseq 6)"
(2 4 6)
In functions.scm
, you can also import commands from your .zshrc
environment, including aliases and shell functions.
This works even if the other shell you’re calling zshbrev’s functions from isn’t zsh (as long as you have zsh installed).
zsh-import
is a macro that takes names as arguments to import. Each
name can be of the form (output-type name)
, for example if you have
an alias “ml” for mpc playlist
that you want to return a list of
strings, you can:
(zsh-import (strings ml))
and then you can call it with (ml)
.
The functions use arguments and stdin like normal shell functions.
You can do any zsh command, including executables in your path, aliases, and shell functions.
The types are:
stdout
: prints its output to stdout and returns success codeport
: forks off but returns a port where you can read its outputfile
: returns a temp file name that contains the outputstring
: returns its output as a string. The default, so you can do
(zsh-import ls)
instead of (zsh-import (string ls))
.chomp
: like string
, but ran through string-chomp
dwim
: tries to figure out the best type automagicallystrings
: returns it output as a list of strings, one for each line of outputsexp
: returns the first sexp (for example, a symbol or a number) of the outputsexps
: sorta like read-list
; turns the output into a list of sexpsYou can mix and match:
(zsh-import (strings ml) echo (file man))
When you want even more control, you have access to all of the
scsh-process
egg, which is imported and available from
functions.scm
. That gives you access to executables, but you can
also reach aliases and shell functions from your .zshrc by adding ,zz
to the run strings.
For example:
(run (,zz ml))
if you have ml
as an alias or shell function.
git clone https://idiomdrottning.org/zshbrev
The point isn’t to encourage gumming up your brev code with a bunch of zsh. You’ll end up with an unportable mess.
I made this because I have hundreds of zsh aliases and functions already. Sunk cost is a hell of a drug.
I made this as a way out from zsh.
Although, sometimes I hear of people using scheme as a shell, and then I see:
(set-file-permissions! zz (bitwise-ior perm/ixusr (file-permissions zz)))
and I’m like—who would want this over chmod
?