I swore off shell programming ever since I switched to using Fish. You can write shell scripts in Fish, the way people do for other shells, but I rarely do. That’s because one of the major reasons I dropped GNU Bash is because I felt that shell scripting had become tedious when I could use something like Python instead.
But how about shells built on top of what some people would consider ‘real’ programming languages compared to shell scripting?
Years ago I spent time using Scsh, a shell built entirely around Scheme, specifically the Scheme 48 implementation. (Which means Scsh is not R6RS compliant.) For a few years I loved using Lisp dialects for everything and that made Scsh an attractive shell. Having the full power of an elegant language like Scheme at my fingertips was empowering. On top of that Scsh had a great library for writing command-line utilities, allowing code like this:
(define read-passwd (field-reader (infix-splitter ":"))) (call-with-input-file "/etc/passwd" (lambda (port) ;; Do something with (read-passwd port) to reach each line of data ;; out of the /etc/passwd file. ))
Scsh even has AWK as a built-in macro, which makes it even easier to parse more complicated files. Having functions like
file-exists? also makes Scsh scripts more readable to me than the typical POSIX shell script.
Perhaps the biggest program with Scsh, though, is its lack of portability. Shells like Bash are ubiquitous. If you are using a shell in complete isolation then Scsh can be great. But when you want to share a useful script you wrote you’ll suddenly find that no one can run it because most people aren’t even aware that Scsh exists.
twosheds is a library for making command language interpreters, or shells.
In other words, Twosheds allows us to create our own shells using the full power of Python and all the libraries available to it. Here is a bare-bones example from the Twosheds site:
#!/usr/bin/env python3 import twosheds shell = twosheds.Shell() shell.interact()
If we make that script executable and run it then we end up with a simple form of Bash. Not the most impressive thing in the world. The power of Twosheds, however, stems from how it’s bundled inside of Python. You can create a subclass of
twosheds.Shell to create custom behavior, such as showing the current branch in a Git repository if you happen to be in such a directory. Or you could go absolutely nuts and use PyGame to replace the
ps command with a Zork-like adventure interface.
Note: Anyone remember the Doom mod where you killed processes on your computer by shooting enemies? Each enemy represented a running process and blasting them in the face with a shotgun would shutdown that process. I haven’t been able to find that program and would appreciate it if anyone could provide a link, just for the sake of nostalgia.
Honestly, I would take the time to program my personal shell needs around Twosheds if I were not already using Fish. I have replaced a lot of my old Bash shell scripts with Python, so using that same language for my shell would create nice consistency. But right now I am happy enough with Fish.
If you’re a programmer sick of the intricacies and tediousness of classic POSIX shell programming then I suggest taking a look at Scsh and Twosheds.