Shell + Lisp = <3

SHCL is a shell written in Common Lisp. It tries to adhere to the POSIX standard as closely as it can. Unlike those new-fangled shells, SHCL doesn't try to strap new features onto the POSIX Shell language to fix it. SHCL isn't a whole new language. Its just plain-old POSIX Shell. That's right. POSIX Shell, just like 'ma used to make it... but with a single, small tweak: you have the full power of Common Lisp at your disposal at all times.

Let's say... for some bizarre reason, you find yourself needing to compute e in your shell. Don't panic! Common Lisp has excellent support for complex numbers!

shcl> shcl-repl
shcl (lisp)> (define-builtin euler (&required theta)
> (let ((result (exp (complex 0 (read-from-string theta)))))
>   (format t "~4F~4@Fi~%" (realpart result) (imagpart result)))
> 0)
EULER
shcl (lisp)> ^D
shcl> euler 3.1415926
-1.0+0.0i

Phew. That was close. Wait... oh no! Due to a series of improbable events, you need to get the prime factorization of some number! Never fear! Common Lisp has a healthy community of packages you can call on!

shcl> shcl-repl
shcl (lisp)> (load "~/quicklisp/setup.lisp")
T
shcl (lisp)> (ql:quickload :cl-factoring)
To load "cl-factoring":
  Load 1 ASDF system:
    cl-factoring; Loading "cl-factoring"

(CL-FACTORING)
shcl (lisp)> ^D
shcl> echo ,(cl-factoring:factor 142)
(2 71)

Okay, yes, its extremely unlikely that you'd ever want to work with complex numbers or need to factor some numbers in a shell script. Still, feature creep is a real thing. One day your simple shell script might need to do something fancy like run queries against a Sqlite database or leverage an elaborate data structure like a bloom filter. Usually, when that day comes, people will tell you to re-write your script in a "real" language. With SHCL, your shell scripts can naturally grow and become full-fledged programs. You'll never need to re-write your shell scripts again!

Frequently asked questions

Where can I download it?

SHCL isn't stable enough for general use, yet. A lot of important features aren't done and it frequently drops into the debugger. If you're feeling adventurous, you can grab the source and try building it yourself.

Why Common Lisp? This actually could have been useful to me if you used <other language>.

Common Lisp's meta-programming facilities are second to none. Very few languages give the programmer the tools necessary to create something like SHCL. Sure, you can write a shell in any language, but SHCL's tight integration between POSIX Shell and Common Lisp is only possible with a language like Common Lisp.

Also, SHCL started out as an educational experiment in reader macros. It was never intended to be useful... it just sort of happened.

Why not try to make the shell language better, like <other shell>?

SHCL isn't trying to be a new shell language. POSIX Shell is pretty close to the platonic ideal for simple process creation tasks. POSIX Shell only starts to fail when you try to use it for other things. Luckily, you don't need to use the shell language for everything! If you need fancy features like local variables, associative arrays, or structured data you should use Common Lisp. With SHCL, its trivial to expose a Common Lisp function to the shell. Use POSIX Shell for the things its suited for, and use Common Lisp for the heavy lifting.

Does it have tab complete?

Its a work in progress, but yes! Tab complete is a tricky proposition for SHCL. SHCL is designed to allow new syntax to be defined at runtime. You can change how the lexer or the parser works at any moment. The completion engine needs to adapt to those changes without skipping a beat. So, creating a tab complete engine for SHCL has proven to be pretty tricky. At the moment, SHCL's tab complete is rudimentary, but it seems like the foundation is strong. Expect to see massive improvements in this area in the future!

What's that about changing the syntax?

Common Lisp allows you to define new syntax. It only felt right that SHCL should, too! SHCL's parser uses PEG-style parser combinators, and every nonterminal and terminal in the grammar is represented using an "advisable" function (inspired by Emacs's advisable functions). You can easily add extensions to the grammar at any level! Similarly, most of the lexer's functionality is based on a generalization of Common Lisp's readtables. If you want to, you can add new entries to the dispatch table or replace existing ones. The sky's the limit!

Why? WHYYYYYYYYYYYYY?!

For fun, of course!

How do you pronounce "SHCL"?

Pronounce it the same way you'd pronounce Shekel.

Which sexy person came up with such a weird and wonderful idea?

Ada did! She's pretty cool.

Is this project dead? It hasn't updated in, like, forever.

Its not dead! Ada has just had a bunch going on.