Customizable prompt for unix shells
A command line is a fundamental interface to a computer. The prompt is the status the computer shows the human after each command.
The prompt should:
- display as fast as possible
- give the human desired context for the next command
- be portable, not tied to a particular shell
I use this prompt as my daily driver. The code is basically "done", but I'm always open to suggestions.
Here are screenshots. First, a simple prompt:
Next, a more complex prompt, in a tmux session, with an active virtualenv, showing the user and host, in a git repository on 'my-branch' with a few files of different statuses, and finally indicating an active direnv.
Here's an example of job control and return code features. This prompt has prefix disabled:
This project depends on my other project, repo_status, to print source control status in the prompt.
Because I always wonder these things: the screenshots are in Kitty terminal using Fantasque Sans Mono. All my system config is open source if you're interested.
Requires the Zig programming language to build:
$ zig build-exe -OReleaseFast -lc prompt.zig
That creates a binary named prompt
. I put in ~/bin
so it's in my path.
Configurable environment variables:
$PROMPT_PREFIX
prefix prompt with this text
$PROMPT_BARE
set to enable a very minimal prompt. "zen mode"
I use the following alias to toggle:
alias pb='[[ $PROMPT_BARE ]] && unset PROMPT_BARE || export PROMPT_BARE=1'
$PROMPT_LONG
display username@host even if local
$PROMPT_FULL_HOST
if set, shows the full hostname (bash: \H \h -- zsh: %M %m)
$PROMPT_PATH
show this for the path, overriding the cwd
this enables you to use Zsh's hashed paths:
export PROMPT_PATH="$(print -P '%~')"
$PROMPT_RETURN_CODE
set to show the exit code of the previous program if != 0
export PROMPT_RETURN_CODE=$?
$PROMPT_JOBS
set to "{running} {suspended}" jobs, defaults to "0 0"
for zsh: (https://unix.stackexchange.com/a/68635)
export PROMPT_JOBS=${(M)#${jobstates%%:*}:#running}\ ${(M)#${jobstates%%:*}:#suspended}
$PROMPT_FULL_VENV
set to show the full name of virtualenvs, vs an indicator
$PROMPT_LINE_BEFORE, $PROMPT_LINE_AFTER
add newline before/after prompt, this enables a multi-line prompt
$PROMPT_HR
set to $COLUMNS to print a horizontal rule before each prompt line
in .zshrc:
alias title='printf "\e]0;%s\a"' # set window title
PROMPT='$(prompt zsh)'
precmd() {
export PROMPT_RETURN_CODE=$?
export PROMPT_JOBS=${(M)#${jobstates%%:*}:#running}\ ${(M)#${jobstates%%:*}:#suspended}
export PROMPT_PATH="$(print -P '%~')"
title "$PROMPT_PATH"
}
in .bashrc
jobscount() {
echo "$(jobs -rp | wc -l | tr -d ' ') $(jobs -sp | wc -l | tr -d ' ')"
}
PROMPT_COMMAND='PS1="$(PROMPT_RETURN_CODE=$? PROMPT_PATH="\w" PROMPT_JOBS="$(jobscount)" prompt bash)"'
in config.toml:
prompt = "echo $(prompt)"
in .xonshrc:
# prompt
def prmpt():
# $PROMPT_RETURN_CODE = __xonsh__.history.last_cmd_rtn # always zero?
$PROMPT_PATH = "{short_cwd}"
return $(prompt)
$PROMPT = prmpt