1###############################################################################
4# This has been inspired by various examples from other people, not all
5# of whom I kept notes of.
6###############################################################################
9function print_current_directory
11 if string match -q "$TMPDIR*" (pwd); and test -n "$TMPDIR"
12 set remaining (string replace -r "^$TMPDIR" "" (pwd))
13 printf (echo -n "\$TMPDIR/$remaining")
15 printf (echo -n (prompt_pwd))
21# Print information about the current Git branch, if I'm in a Git repo.
23# At one point I had similar functions for getting SVN and Mercurial information,
24# but at time of writing (Apr 2022), it's been 5+ years since I used a non-Git VCS.
25# It's not worth maintaining those alternatives or running them against every
27function print_git_information
28 which git 2>&1 >/dev/null
30 set is_bare (git rev-parse --is-bare-repository 2> /dev/null)
31 if string match --quiet "true*" $is_bare
35 set branch (git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/')
40 if test (basename "$branch") = main
48 # Print an asterisk to indicate uncommitted changes, if there are any
49 # Try git update-index --really-refresh?
50 if ! git diff-index --quiet HEAD --
59# Print information about the current virtualenv, if one is enabled.
61# The VIRTUAL_ENV_DISABLE_PROMPT command disables the auto-prepending of the
62# venv into my prompt by the virtualenv itself; see
63# https://stackoverflow.com/a/63029769/1558022
64set -x VIRTUAL_ENV_DISABLE_PROMPT 1
66function print_venv_information
67 if test -n "$VIRTUAL_ENV"
69 # If the virtualenv has ceased to exist since the last prompt,
70 # then it can't possibly be activated, so deactivate and don't
71 # print it in the prompt.
72 if test ! -d "$VIRTUAL_ENV"
80 if test (basename "$VIRTUAL_ENV") = ".venv"
86 printf (basename "$VIRTUAL_ENV")
92# If I'm running over SSH, prepend the name of the remote host to
94function print_ssh_information
98 printf (echo -n (hostname))
105# Allow me to prevent certain dangerous commands from ever
106# appearing in autocomplete.
108# See https://alexwlchan.net/2023/forgetful-fish/
109# See https://github.com/fish-shell/fish-shell/issues/10066
110function forget_dangerous_history_commands
111 set last_typed_command (history --max 1)
113 if [ "$last_typed_command" = "git push origin (gcb) --force" ]
114 history delete --exact --case-sensitive "$last_typed_command"
120function fish_prompt --description 'Write out the prompt'
121 # forget_dangerous_history_commands
123 # Put a newline between new prompts for cleanliness, but not on the first run.
125 # This means the first prompt of a new session is right at the top of
126 # the terminal window, not with a newline above it.
128 # If we're in an SSH session, we always insert a newline, even on the first
129 # command -- to separate from the client session. I avoid getting the
130 # 'Last login' message with `touch ~/.hushlogin`
134 if test \( -f "/tmp/$TERM_SESSION_ID" -o -f "/tmp/$XDG_SESSION_ID" \)
138 touch "/tmp/$TERM_SESSION_ID" 2>/dev/null
139 touch "/tmp/$XDG_SESSION_ID" 2>/dev/null
142 # Print some context about where I'm running this command.
144 # If I'm in my home directory, the context isn't very interesting (it's where
145 # new shells open, and it's not in Git), so skip the context line to reduce
147 if [ (prompt_pwd) = "~" ]
149 print_ssh_information
156 print_ssh_information
157 print_current_directory
158 print_git_information
159 print_venv_information
161 # Print the shell prompt.
163 # I have a different prompt for when I'm running as root; admittedly this
164 # is extremely rare if I'm also using fish, but if I am I want a visual cue
165 # that this terminal is unusual.
167 # I print the prompt on a separate line to the context information so it's
168 # always in the same place: as I'm typing commands, I get the full width of
169 # the terminal to use, rather than a variable amount based on the context line.
171 if [ "$USER" = root ]