Not Using Terminals Pt. 4: Quick Script Creation
In our previous episode, we made a case for creating an excessive number of scripts, as a replacement for shell history + typing in commands on the fly. We even added a script that lets you save previous invocations as a script. But then... trivial inconveniences might still prevent you from doing this, reverting to "just typing in this one command".
What we need is... making this even more accessible. By which we mean... you shouldn't think about it.
Shell history is something that you can access without much thinking. Accessing your "scripts" directory can be the same! E.g. you can just do something like
(defvar ssafar-scripts-path "h:\\bin")
(defun ssafar-open-scripts-dir ()
(interactive)
(find-file ssafar-scripts-path))
(global-set-key (kbd "") 'ssafar-open-scripts-dir)
With this, wherever you are, F2 will open up your scripts directory in dired.
Of course, there should be one default "scripts" directory. Doesn't even need to be on the path, but it should have an easy to remember name (e.g. ~/bin
). The important part is that figuring out where to put this script should take about the same amount of mental effort as deciding which bash history file to save your latest command to (i.e. "none"; you don't even choose, there is just the one, period).
But then... you'd still need to... pick unique names for them...?
Well, we don't have to. Take the following snippet:
(defun ssafar-new-bash-script (name skip-date-p)
(interactive "MName for new script: \nP") ;; takes 2 args: a name and a universal arg to switch whether we'd want a date on
(let* ((script-name ;; looks like "something_you_typed_in_20240915"
(format "%s%s"
name
(if skip-date-p "" (format-time-string "_%Y%m%d"))))
(script-full-path ;; turn it into a full absolute path
(format "%s%s" (file-name-as-directory ssafar-scripts-path)
script-name))) ;; file-name-as-directory adds a trailing / or \ if needed
(find-file script-full-path) ;; open the new script
(shell-script-mode) ;; shell script syntax highlighting
(insert "#!/bin/bash\n\n") ;; some template text
(insert "set -e\n\n")
(save-buffer) ;; ... so that we can run it later
(compilation-start script-full-path))) ;; run it!
You can bind this to... e.g. the key "N" in dired:
(define-key dired-mode-map (kbd "N") 'ssafar-new-bash-script)
... so whenever you want a new script, all you have to do is
- F2 to view the scripts dir
- N to create a new one
This will:
- create a script for you, named
your_name_20240915
. Note the name: you can get arbitrarily spammy with them, as you pick different names within the same day. - fills out the shebang line & some reasonable defaults. Do you want a bash argument count check in there? Just add an extra "insert" to the lisp code! Deleting things in new scripts is a lot easier than looking them up & writing them from scratch all the time.
- launch compilation mode on the result. It's an empty script, so it won't actually do anything, but you're now ready to iterate & re-run your newest creation with switching to the compilation buffer & hitting
g
.
More ideas
Doing this for bash scrips merely brings up pretty close to how easy it is to throw in command line commands. Do the same with Python scripts: suddenly, the difference between "this is just a command on the command line" and "this is a full-blown Python program" ends up being a lot smaller.
For additional fun: at the first sign of shell scripting getting ugly, throw the entire thing into an LLM, "please turn this into Python", and continue from there, with a new script.