Building interactive commands that uses editing history and tab completion can be easy in bash and serve as a wrapper for automating tasks.
Now that you’ve mastered the command line fu using .inputrc as described in a previous post, you’d like to use this in building other tools..
I’ve used this basic technique in scripts for automating deployments, monitoring and possible rollbacks for hundreds or thousands of hosts, but today I’d like to describe it using a “toy” example so that you can see how easy it is. It basically involves building a “read/eval” loop in your shell script.
The example I’ve chosen it to build a simple persistent history editing and tab completion facility into “bc”, with an added bonus of being able to use expressions with the “factor” application. Now in reality, “bc” is often already compiled with readline now; but the history isn’t written to a file (and it doesn’t have “factor” support).
How It Works
The script can be downloaded here: bcw github repo
We first set up a temporary directory where we’ll touch some files that are used for tab completion. We then read in the persistent history file if it exists and drop into a read/eval loop where the commands are interpreted.
While we are reading the command, we temporarily cd into the tab completion directory to facilitate users entering partial commands and using tab to complete. (This directory can be dynamically updated as well which I’ve used that in more complicated situations.)
In this session, I’ll add some comments which are relevant if you have “set editing-mode vi” set in your $HOME/.inputrc file. If you don’t have that set, then you’re on your own.. (You can still edit the command line history, just not using “vi” key bindings.)
twiggy:~/git/bcw$ grep editing-mode ~/.inputrc set editing-mode vi twiggy:~/git/bcw$ bcw [bcw]->help Help: expr expression # feed expression through bc factor expression # factor the expression history # list the history history clear # clear history sh # head out to the shell (exit or ^D to return) sh command # run command outside of bcw debug [on|off] # examine or change debug trace [on|off] # examine or change trace verbose [on|off] # examine or change verbose clear # clear clutter [bcw]->sh pwd /Users/bduncan/git/bcw [bcw]->expr 2^31-1 2147483647 [bcw]-># roll back and edit using "kcefac[tab]" [bcw]->factor 2^31-1 2147483647: 2147483647 [bcw]->exponent=19 [bcw]-># roll back and edit using "kkf3ce$exponent" [bcw]->factor 2^$exponent-1 524287: 524287 [bcw]-># roll back and edit using "kceecho" [bcw]->echo 2^$exponent-1 2^19-1 [bcw]->debug debug is off [bcw]->debug on [bcw debug]->factor 2^$exponent-1 docommand [factor 2^$exponent-1] 524287: 524287 [bcw debug]->debug off docommand [debug off] [bcw]->ibase=2 [bcw]-># 2^18-1 [bcw]->factor 111111111111111111 262143: 3 3 3 7 19 73 [bcw]-># roll back and edit using "kA1" [bcw]->factor 1111111111111111111 524287: 524287 [bcw]-># control-D to exit [bcw]->Bye!
I’ve used the technique to hide details for operating on groups of large numbers of hosts in parallel, keeping track of all operations and verifying them. Use your Imagination and build your own interactive commands leveraging your command line history editing kung fu!