Shell Config Ergonomics
Loren (mcint) January 29, 2023 [Terminal] #cli #bash #config# ~/.profile
for; do
;
done
# .shell/paths
# .shell/aliases
# .shell/funcs
#src /usr/local/etc/profile.d/z.sh # replaced by z.lua
|| { && ; }
I have a src
script, so I don't have to rewrite the [[ -f $file ]] && $file
idiom every time. It also reports or logs errors for files that aren't present
but are called.
A paths file, with helper functions to read--newline delimited--, prepend, and append.
As I build more tools from C* ecosystems, I recently wrote a tool to prepend and append to other paths, package conf, libraries, and man pages.
Aliases
Aliases are invaluable as a quick shorthand. I write aliases often within the
first few minutes of using a host alias p=pushd pp=popd d="dirs -v"
. Using
the (bash) directory stack helps me externalize memory, so current status
doesn't have to stay in my head. It stays with project context on the machine,
even if I walk away. Unfortunately bash doesn't offer a way to export it, and
scripting gdb to inspect it and save it out is not possible on macOS, to my
dismay, so it can't be preseved by tmux-resurrect across restarts, although
window names, pane PWD, and nvim open files are preserved.
Aliases for inspection also make it easier to understand the environment exertion.
alias tt=type
.
Functions
Shell functions are essential shorthand if you have to pass parameters in midway through a pipeline construct. I also maintain functions to save select (or all) aliases, save bash functions by name, and to edit functions and reload them.
Paths
Path manipulation is a commond way to manipulate a shell environment. It's so common and powerful that many tools are build around doing just that.
Aliases
alias ppath=<<<"$PATH" tr : '\n'
alias pathgrep='<<<$PATH tr : "\n" | xargs fd . | grep'
Functions path_prepend
, path_append
, and path_remove
virtualenv - install project-local copy of packages direnv - (allows much more, but is often first pitched to) automatically update your environment
Ensemble configuration
In the wild / already in your life / already familiar
Updating configuration with directories, examples that prove the utility and strength of the pattern:
-
/etc/nginx/sites-available/ /etc/nginx/sites-enabled/
-
/etc/nginx/conf.d/
-
/etc/sudoers.d/*.conf
-
/etc/update-motd.d/ - see
run-parts
, withman
-fu to render yourself -
init systems: SystemD, init.d /etc/systemd/system/
My use in shell configuation
I move disabled shell files into ~/.config/shell/disabled, and don't handle directories in my bulk-sourcing script.
I have, on 2 or 3 occasions, written tracing scripts into my shell configuration to debug long initializion times. I'll start thinking seriously about it at .5 seconds, and then, when my computer is under load at that jumps over 3 seconds, I'll bite the bullet and dig into my shell rc files to cut out the inconsiderate loading scripts.
Goals
I don't want to mix many separate concerns in the same file, and I enjoy quick cycle times where I can Save-Load-Test configuration files or Save-Spawn-Verify desired configuration in new shells.
Other power tools
A friend at the OCF wrote how
, to inspect scripts and quickly learn about
the system.
I've attend -e
--edit
flags to edit scripts,
and more recently -c
--create
flags, to begin new
utility shell scripts in single command.
the other profile
.bash_profile
consists of
. .profile
# prompt set up, split over two dozen lines for editability
# I like venv default modifications so dislike forced resetting of prompt
# Return codes from a previous command can be included in a static definition of PS1,
# including conditional styling. PROMPT_DIRTRIM handles the other major concern
# Variables to include local context sometimes make an appearance. Serving like a
# window title, or a short todo list, in one of the panes of dozens of local tmux
# windows, or on remote servers.
[[ -r "/usr/local/etc/profile.d/bash_completion.sh" ]] && . "/usr/local/etc/profile.d/bash_completion.sh"
eval "$(lua /usr/local/share/z.lua/z.lua --init bash enhanced once echo)"
# in: ~/.env, and ~/.paths ##export GOPATH="$HOME/go"; export GOROOT="$HOME/.go"; export PATH="$GOPATH/bin:$PATH"; # g-install: do NOT edit, see https://github.com/stefanmaric/g
_conda_load(){ [[ -f ~/.bash_conda ]] && . ~/.bash_conda; }
_mamba_load(){ [[ -f ~/.bash_mamba ]] && . ~/.bash_mamba; }
I defer conda loading because I don't want to be in that environment by default, and becuase it adds a noticable (but not always unbearable) delay to shell startup times.