| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- #!/bin/bash
- # A modern, informative and configurable command prompt for the Bash shell.
- #
- # URL: github.com/bluz71/bash-seafly-prompt
- # License: MIT (https://opensource.org/licenses/MIT)
- # Non-interactive shells don't have a prompt, exit early.
- [[ $- =~ i ]] || return 0
- # Set a simple prompt for non-256color, non-alacritty and non-kitty terminals.
- if [[ $TERM != *-256color ]] && [[ $TERM != alacritty* ]] && [[ $TERM != *-kitty ]]; then
- PS1='\h \w > '
- return 0
- fi
- # Default colors used in the prompt.
- : ${SEAFLY_PREFIX_COLOR:=$(tput setaf 153)}
- : ${SEAFLY_NORMAL_COLOR:=$(tput setaf 111)}
- : ${SEAFLY_ALERT_COLOR:=$(tput setaf 203)}
- : ${SEAFLY_HOST_COLOR:=$(tput setaf 255)}
- : ${SEAFLY_GIT_COLOR:=$(tput setaf 147)}
- : ${SEAFLY_PATH_COLOR:=$(tput setaf 150)}
- : ${NOCOLOR:=$(tput sgr0)}
- # Shorten directory paths to a maximum of four components unless PROMPT_DIRTRIM
- # has already been set.
- : ${PROMPT_DIRTRIM:=4}
- # Default Git indicator values.
- : ${GIT_PS1_SHOWDIRTYSTATE:=1}
- : ${GIT_PS1_SHOWSTASHSTATE:=1}
- : ${GIT_PS1_SHOWUPSTREAM:=1}
- # Default layout settings.
- : ${SEAFLY_LAYOUT:=1}
- : ${SEAFLY_MULTILINE:=0}
- : ${SEAFLY_SHOW_USER:=0}
- : ${SEAFLY_SHOW_HOST:=1}
- # Default symbols used in the prompt.
- : ${SEAFLY_PROMPT_SYMBOL:="❯"}
- : ${SEAFLY_PS2_PROMPT_SYMBOL:="❯"}
- : ${SEAFLY_GIT_PREFIX:=""}
- : ${SEAFLY_GIT_SUFFIX:=""}
- : ${SEAFLY_GIT_DIRTY:="✗"}
- : ${SEAFLY_GIT_STAGED:="✓"}
- : ${SEAFLY_GIT_STASH:="⚑"}
- : ${SEAFLY_GIT_AHEAD:="↑"}
- : ${SEAFLY_GIT_BEHIND:="↓"}
- : ${SEAFLY_GIT_DIVERGED:="↕"}
- # Location of [gitstatus](https://github.com/romkatv/gitstatus).
- : ${SEAFLY_GITSTATUS_DIR:="$HOME/.gitstatus"}
- # Optional command to run before every prompt; output is ignored.
- : ${SEAFLY_PRE_COMMAND:=""}
- # Optional command that outputs as the prompt prefix.
- : ${SEAFLY_PROMPT_PREFIX:=""}
- # Collate Git details using the optimized
- # [gitstatus](https://github.com/romkatv/gitstatus) command.
- #
- _seafly_git_optimized() {
- local flags
- # Note, gitstatus will automatically set '-p' if the local repository has
- # set 'bash.showDirtyState' to false.
- [[ $GIT_PS1_SHOWDIRTYSTATE == 0 ]] && flags=-p # Avoid unnecessary work
- if ! hash gitstatus_query 2>/dev/null || ! gitstatus_query $flags; then
- # Either gitstatus_query does not exist or it failed, use fallback
- # instead.
- _seafly_git_fallback
- return
- fi
- [[ $VCS_STATUS_RESULT == ok-sync ]] || return
- # We are in a Git repository and gitstatus_query succeeded.
- local branch=$VCS_STATUS_LOCAL_BRANCH
- if [[ -z $branch ]]; then
- branch="detached*$(git rev-parse --short HEAD 2>/dev/null)"
- fi
- branch=${branch//\\/\\\\} # Escape backslashes
- branch=${branch//\$/\\\$} # Escape dollars
- local dirty
- local staged
- if [[ $GIT_PS1_SHOWDIRTYSTATE != 0 && $VCS_STATUS_HAS_UNSTAGED == 1 ]]; then
- dirty=$SEAFLY_GIT_DIRTY
- fi
- if [[ $GIT_PS1_SHOWDIRTYSTATE != 0 && $VCS_STATUS_HAS_STAGED == 1 ]]; then
- staged=$SEAFLY_GIT_STAGED
- fi
- local stash
- if [[ $GIT_PS1_SHOWSTASHSTATE != 0 && $VCS_STATUS_STASHES -gt 0 ]]; then
- stash=$SEAFLY_GIT_STASH
- fi
- local upstream
- if [[ $GIT_PS1_SHOWUPSTREAM != 0 ]]; then
- if [[ $VCS_STATUS_COMMITS_AHEAD -gt 0 &&
- $VCS_STATUS_COMMITS_BEHIND -gt 0 ]]; then
- upstream=$SEAFLY_GIT_DIVERGED
- elif [[ $VCS_STATUS_COMMITS_AHEAD -gt 0 ]]; then
- upstream=$SEAFLY_GIT_AHEAD
- elif [[ $VCS_STATUS_COMMITS_BEHIND -gt 0 ]]; then
- upstream=$SEAFLY_GIT_BEHIND
- elif [[ -n $VCS_STATUS_REMOTE_NAME ]]; then
- upstream="="
- fi
- fi
- local spacer
- if [[ -n $dirty || -n $staged || -n $stash || -n $upstream ]]; then
- spacer=" "
- fi
- _seafly_git=" $SEAFLY_GIT_PREFIX$branch$spacer\[$SEAFLY_ALERT_COLOR\]$dirty\[$SEAFLY_NORMAL_COLOR\]$staged$upstream\[$SEAFLY_GIT_COLOR\]$stash$SEAFLY_GIT_SUFFIX"
- }
- # Collate Git details using just the 'git' command.
- #
- _seafly_git_fallback() {
- local is_git_repo
- if [[ $(git rev-parse --is-inside-work-tree --is-bare-repository 2>/dev/null) =~ true ]]; then
- is_git_repo=1
- fi
- [[ $is_git_repo == 1 ]] || return
- # We are in a Git repository.
- local branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null)"
- if [[ $branch == "HEAD" ]]; then
- branch="detached*$(git rev-parse --short HEAD 2>/dev/null)"
- fi
- branch=${branch//\\/\\\\} # Escape backslashes
- branch=${branch//\$/\\\$} # Escape dollars
- local dirty
- local staged
- if [[ $branch != "detached*" &&
- $GIT_PS1_SHOWDIRTYSTATE != 0 &&
- $(git config --bool bash.showDirtyState) != "false" ]]; then
- git diff --no-ext-diff --quiet --exit-code --ignore-submodules 2>/dev/null || dirty=$SEAFLY_GIT_DIRTY
- git diff --no-ext-diff --quiet --cached --exit-code --ignore-submodules 2>/dev/null || staged=$SEAFLY_GIT_STAGED
- fi
- local stash
- if [[ $GIT_PS1_SHOWSTASHSTATE != 0 ]]; then
- git rev-parse --verify --quiet refs/stash >/dev/null && stash=$SEAFLY_GIT_STASH
- fi
- local upstream
- if [[ $GIT_PS1_SHOWUPSTREAM != 0 ]]; then
- case "$(git rev-list --left-right --count HEAD...@'{u}' 2>/dev/null)" in
- "") # no upstream
- upstream="" ;;
- "0 0") # equal to upstream
- upstream="=" ;;
- "0 "*) # behind upstream
- upstream=$SEAFLY_GIT_BEHIND ;;
- *" 0") # ahead of upstream
- upstream=$SEAFLY_GIT_AHEAD ;;
- *) # diverged from upstream
- upstream=$SEAFLY_GIT_DIVERGED ;;
- esac
- fi
- local spacer
- if [[ -n $dirty || -n $staged || -n $stash || -n $upstream ]]; then
- spacer=" "
- fi
- _seafly_git=" $SEAFLY_GIT_PREFIX$branch$spacer\[$SEAFLY_ALERT_COLOR\]$dirty\[$SEAFLY_NORMAL_COLOR\]$staged$upstream\[$SEAFLY_GIT_COLOR\]$stash$SEAFLY_GIT_SUFFIX"
- }
- _seafly_command_prompt() {
- # QNET: Custom Prompting
- MSG="/tmp/prompt_msg"
- if [[ -f "$MSG" ]]; then # var exists
- if [[ -n "$MSG" ]]; then # not empty
- cat "$MSG"
- echo ''
- fi
- fi
- # Run the pre-command if set.
- eval $SEAFLY_PRE_COMMAND
- local prompt_prefix
- local prefix_value=$(eval $SEAFLY_PROMPT_PREFIX)
- if [[ -n $prefix_value ]]; then
- prompt_prefix="\[$SEAFLY_PREFIX_COLOR\]$prefix_value "
- fi
- if [[ $SEAFLY_MULTILINE = 1 ]]; then
- prompt_prefix="\n$prompt_prefix"
- fi
- local prompt_start
- if [[ $SEAFLY_SHOW_USER = 1 && $SEAFLY_SHOW_HOST = 1 ]]; then
- prompt_start="\[$SEAFLY_HOST_COLOR\]\u@\h"
- elif [[ $SEAFLY_SHOW_USER = 1 ]]; then
- prompt_start="\[$SEAFLY_HOST_COLOR\]\u"
- elif [[ $SEAFLY_SHOW_HOST = 1 ]]; then
- prompt_start="\[$SEAFLY_HOST_COLOR\]\h"
- fi
- # Collate Git details, if applicable, for the current directory.
- _seafly_git_optimized
- local prompt_middle
- if [[ $SEAFLY_LAYOUT = 1 ]]; then
- prompt_middle="\[$SEAFLY_GIT_COLOR\]$_seafly_git\[$SEAFLY_PATH_COLOR\] \w"
- else
- prompt_middle="\[$SEAFLY_PATH_COLOR\] \w\[$SEAFLY_GIT_COLOR\]$_seafly_git"
- fi
- unset _seafly_git
- # Normal prompt indicates that the last command ran successfully.
- # Alert prompt indicates that the last command failed.
- _seafly_colors=("$SEAFLY_ALERT_COLOR" "$SEAFLY_NORMAL_COLOR")
- local prompt_end="\[\${_seafly_colors[\$((!\$?))]}\] $SEAFLY_PROMPT_SYMBOL\[\$NOCOLOR\] "
- if [[ $SEAFLY_MULTILINE = 1 ]]; then
- prompt_end="\n$prompt_end"
- fi
- PS1="$prompt_prefix$prompt_start$prompt_middle$prompt_end"
- PS2="\[$SEAFLY_NORMAL_COLOR\]$SEAFLY_PS2_PROMPT_SYMBOL\[\$NOCOLOR\] "
- }
- # Use [gitstatus](https://github.com/romkatv/gitstatus) if it is available.
- if [[ -r $SEAFLY_GITSTATUS_DIR/gitstatus.plugin.sh ]]; then
- source "$SEAFLY_GITSTATUS_DIR"/gitstatus.plugin.sh
- gitstatus_stop && gitstatus_start -c 0 -d 0
- fi
- # Bind and call the '_seafly_command_prompt' function as the Bash prompt.
- PROMPT_COMMAND=_seafly_command_prompt
|