764 lines
26 KiB
Bash
764 lines
26 KiB
Bash
# _ _ _
|
|
# _ __ ___ | |_ _ __ _| | ___ | |_
|
|
# | '_ \ / _ \| | | | |/ _` | |/ _ \| __|
|
|
# | |_) | (_) | | |_| | (_| | | (_) | |_
|
|
# | .__/ \___/|_|\__, |\__, |_|\___/ \__|
|
|
# |_| |___/ |___/
|
|
#
|
|
# Polyglot Prompt
|
|
#
|
|
# A dynamic color Git prompt for zsh, bash, ksh93, mksh, pdksh, oksh, dash,
|
|
# yash,busybox ash, and osh
|
|
#
|
|
#
|
|
# Source this file from a relevant dotfile (e.g. .zshrc, .bashrc, .shrc, .kshrc,
|
|
# .mkshrc, .yashrc, or ~/.config/oil/oshrc) thus:
|
|
#
|
|
# . /path/to/polyglot.sh
|
|
#
|
|
# Set $POLYGLOT_PROMPT_DIRTRIM to the number of directory elements you would
|
|
# like to have displayed in your prompt (the default is 2). For example,
|
|
#
|
|
# POLYGLOT_PROMPT_DIRTRIM=3
|
|
#
|
|
# results in
|
|
#
|
|
# ~/foo/bar/bat/quux
|
|
#
|
|
# displaying as
|
|
#
|
|
# ~/.../bar/bat/quux
|
|
#
|
|
#
|
|
# Copyright 2017-2024 Alexandros Kozak
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
# of this software and associated documentation files (the "Software"), to
|
|
# deal in the Software without restriction, including without limitation the
|
|
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
# sell copies of the Software, and to permit persons to whom the Software is
|
|
# furnished to do so, subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be included in
|
|
# all copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
# IN THE SOFTWARE.
|
|
#
|
|
#
|
|
# https://github.com/agkozak/polyglot
|
|
#
|
|
|
|
# shellcheck shell=ksh
|
|
# shellcheck disable=SC2016,SC2034,SC2088,SC3024
|
|
|
|
# Only run in interactive shells
|
|
case $- in
|
|
*i*) ;;
|
|
*) return ;;
|
|
esac
|
|
|
|
# Bail if the shell doesn't have command
|
|
if ! type command > /dev/null 2>&1; then
|
|
printf '%s\n' 'Polyglot Prompt does not support your shell.' >&2
|
|
return 1
|
|
fi
|
|
|
|
# Don't let virtual env active scripts alter prompt
|
|
VIRTUAL_ENV_DISABLE_PROMPT=1
|
|
|
|
############################################################
|
|
# Display non-zero exit status
|
|
#
|
|
# Arguments:
|
|
# $1 exit status of last command (always $?)
|
|
############################################################
|
|
_polyglot_exit_status() {
|
|
case $1 in
|
|
0) return ;;
|
|
*) printf '(%d) ' "$1" ;;
|
|
esac
|
|
}
|
|
|
|
###########################################################
|
|
# Is the user connected via SSH?
|
|
###########################################################
|
|
_polyglot_is_ssh() {
|
|
[ -n "${SSH_CONNECTION-}${SSH_CLIENT-}${SSH_TTY-}" ]
|
|
}
|
|
|
|
###########################################################
|
|
# Provide the effective user ID
|
|
###########################################################
|
|
_polyglot_euid() {
|
|
case ${POLYGLOT_UNAME:=$(uname -s)} in
|
|
SunOS) /usr/xpg4/bin/id -u ;;
|
|
*) id -u ;;
|
|
esac
|
|
}
|
|
|
|
###########################################################
|
|
# Is the user a superuser?
|
|
###########################################################
|
|
_polyglot_is_superuser() {
|
|
# shellcheck disable=SC3028
|
|
[ ${EUID:-$(_polyglot_euid)} -eq 0 ]
|
|
}
|
|
|
|
###########################################################
|
|
# Does the terminal support enough colors?
|
|
###########################################################
|
|
_polyglot_has_colors() {
|
|
[ -n "$ZSH_VERSION" ] && setopt LOCAL_OPTIONS NO_WARN_CREATE_GLOBAL
|
|
|
|
# The DragonFly BSD system console has trouble displaying colors in pdksh
|
|
case ${POLYGLOT_UNAME:=$(uname -s)} in
|
|
DragonFly)
|
|
case $(who am i) in *ttyv*) return 1 ;; esac
|
|
;;
|
|
esac
|
|
|
|
case $TERM in
|
|
*-256color) POLYGLOT_TERM_COLORS=256 ;;
|
|
vt100|dumb) POLYGLOT_TERM_COLORS=-1 ;;
|
|
*)
|
|
if command -v tput > /dev/null 2>&1; then
|
|
case ${POLYGLOT_UNAME:=$(uname -s)} in
|
|
FreeBSD|DragonFly) POLYGLOT_TERM_COLORS=$(tput Co) ;;
|
|
UWIN*) POLYGLOT_TERM_COLORS=$(tput cols) ;;
|
|
*) POLYGLOT_TERM_COLORS=$(tput colors) ;;
|
|
esac
|
|
else
|
|
POLYGLOT_TERM_COLORS=-1
|
|
fi
|
|
;;
|
|
esac
|
|
if [ "${POLYGLOT_TERM_COLORS:-0}" -ge 8 ]; then
|
|
unset POLYGLOT_TERM_COLORS
|
|
return 0
|
|
else
|
|
unset POLYGLOT_TERM_COLORS
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
############################################################
|
|
# Emulation of bash's PROMPT_DIRTRIM for all other shells
|
|
# and for bash before v4.0
|
|
#
|
|
# In $PWD, substitute $HOME with ~; if the remainder of the
|
|
# $PWD has more than a certain number of directory elements
|
|
# to display (default: 2), abbreviate it with '...', e.g.
|
|
#
|
|
# $HOME/dotfiles/polyglot/img
|
|
#
|
|
# will be displayed as
|
|
#
|
|
# ~/.../polyglot/img
|
|
#
|
|
# If $1 is 0, no abbreviation will occur other than that
|
|
# $HOME will be displayed as ~.
|
|
#
|
|
# Arguments:
|
|
# $1 Number of directory elements to display
|
|
############################################################
|
|
_polyglot_prompt_dirtrim() {
|
|
# Necessary for set -- $1 to undergo field separation in zsh
|
|
[ -n "$ZSH_VERSION" ] && setopt LOCAL_OPTIONS SH_WORD_SPLIT \
|
|
NO_WARN_CREATE_GLOBAL NO_WARN_NESTED_VAR 2> /dev/null
|
|
|
|
POLYGLOT_DIRTRIM_ELEMENTS="${1:-2}"
|
|
|
|
# If root has / as $HOME, print /, not ~
|
|
[ "$PWD" = '/' ] && printf '%s' '/' && return
|
|
[ "$PWD" = "$HOME" ] && printf '%s' '~' && return
|
|
|
|
case $HOME in
|
|
/) POLYGLOT_PWD_MINUS_HOME="$PWD" ;; # In case root's $HOME is /
|
|
*) POLYGLOT_PWD_MINUS_HOME="${PWD#"$HOME"}" ;;
|
|
esac
|
|
|
|
if [ "$POLYGLOT_DIRTRIM_ELEMENTS" -eq 0 ]; then
|
|
[ "$HOME" = '/' ] && printf '%s' "$PWD" && return
|
|
case $PWD in
|
|
${HOME}*) printf '~%s' "$POLYGLOT_PWD_MINUS_HOME" ;;
|
|
*) printf '%s' "$PWD" ;;
|
|
esac
|
|
else
|
|
# Calculate the part of $PWD that will be displayed in the prompt
|
|
POLYGLOT_OLD_IFS="$IFS"
|
|
IFS='/'
|
|
# shellcheck disable=SC2086
|
|
set -- $POLYGLOT_PWD_MINUS_HOME
|
|
shift # Discard empty first field preceding /
|
|
|
|
# Discard path elements > $POLYGLOT_PROMPT_DIRTRIM
|
|
while [ $# -gt "$POLYGLOT_DIRTRIM_ELEMENTS" ]; do
|
|
shift
|
|
done
|
|
|
|
# Reassemble the remaining path elements with slashes
|
|
while [ $# -ne 0 ]; do
|
|
POLYGLOT_ABBREVIATED_PATH="${POLYGLOT_ABBREVIATED_PATH}/$1"
|
|
shift
|
|
done
|
|
|
|
IFS="$POLYGLOT_OLD_IFS"
|
|
|
|
# If the working directory has not been abbreviated, display it thus
|
|
if [ "$POLYGLOT_ABBREVIATED_PATH" = "${POLYGLOT_PWD_MINUS_HOME}" ]; then
|
|
if [ "$HOME" = '/' ]; then
|
|
printf '%s' "$PWD"
|
|
else
|
|
case $PWD in
|
|
${HOME}*) printf '~%s' "${POLYGLOT_PWD_MINUS_HOME}" ;;
|
|
*) printf '%s' "$PWD" ;;
|
|
esac
|
|
fi
|
|
# Otherwise include an ellipsis to show that abbreviation has taken place
|
|
else
|
|
if [ "$HOME" = '/' ]; then
|
|
printf '...%s' "$POLYGLOT_ABBREVIATED_PATH"
|
|
else
|
|
case $PWD in
|
|
${HOME}*) printf '~/...%s' "$POLYGLOT_ABBREVIATED_PATH" ;;
|
|
*) printf '...%s' "$POLYGLOT_ABBREVIATED_PATH" ;;
|
|
esac
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
unset POLYGLOT_DIRTRIM_ELEMENTS POLYGLOT_PWD_MINUS_HOME POLYGLOT_OLD_IFS \
|
|
POLYGLOT_ABBREVIATED_PATH
|
|
}
|
|
|
|
###########################################################
|
|
# Display current branch name, followed by symbols
|
|
# representing changes to the working copy
|
|
#
|
|
# Arguments:
|
|
# $1 If ksh, escape ! as !!
|
|
#
|
|
# shellcheck disable=SC2120
|
|
###########################################################
|
|
_polyglot_branch_status() {
|
|
[ -n "$ZSH_VERSION" ] && setopt LOCAL_OPTIONS NO_WARN_CREATE_GLOBAL \
|
|
NO_WARN_NESTED_VAR > /dev/null 2>&1
|
|
|
|
POLYGLOT_REF="$(env git symbolic-ref --quiet HEAD 2> /dev/null)"
|
|
case $? in # See what the exit code is.
|
|
0) ;; # $POLYGLOT_REF contains the name of a checked-out branch.
|
|
128) return ;; # No Git repository here.
|
|
# Otherwise, see if HEAD is in a detached state.
|
|
*) POLYGLOT_REF="$(env git rev-parse --short HEAD 2> /dev/null)" || return ;;
|
|
esac
|
|
|
|
if [ -n "$POLYGLOT_REF" ]; then
|
|
if [ "${POLYGLOT_SHOW_UNTRACKED:-1}" -eq 0 ]; then
|
|
POLYGLOT_GIT_STATUS=$(LC_ALL=C GIT_OPTIONAL_LOCKS=0 env git status -uno 2>&1)
|
|
else
|
|
POLYGLOT_GIT_STATUS=$(LC_ALL=C GIT_OPTIONAL_LOCKS=0 env git status 2>&1)
|
|
fi
|
|
|
|
POLYGLOT_SYMBOLS=''
|
|
|
|
case $POLYGLOT_GIT_STATUS in
|
|
*' have diverged,'*) POLYGLOT_SYMBOLS="${POLYGLOT_SYMBOLS}&*" ;;
|
|
esac
|
|
case $POLYGLOT_GIT_STATUS in
|
|
*'Your branch is behind '*) POLYGLOT_SYMBOLS="${POLYGLOT_SYMBOLS}&" ;;
|
|
esac
|
|
case $POLYGLOT_GIT_STATUS in
|
|
*'Your branch is ahead of '*) POLYGLOT_SYMBOLS="${POLYGLOT_SYMBOLS}*" ;;
|
|
esac
|
|
case $POLYGLOT_GIT_STATUS in
|
|
*'new file: '*) POLYGLOT_SYMBOLS="${POLYGLOT_SYMBOLS}+" ;;
|
|
esac
|
|
case $POLYGLOT_GIT_STATUS in
|
|
*'deleted: '*) POLYGLOT_SYMBOLS="${POLYGLOT_SYMBOLS}x" ;;
|
|
esac
|
|
case $POLYGLOT_GIT_STATUS in
|
|
*'modified: '*)
|
|
if [ "$1" = 'ksh' ]; then
|
|
POLYGLOT_SYMBOLS="${POLYGLOT_SYMBOLS}!!"
|
|
else
|
|
POLYGLOT_SYMBOLS="${POLYGLOT_SYMBOLS}!"
|
|
fi
|
|
;;
|
|
esac
|
|
case $POLYGLOT_GIT_STATUS in
|
|
*'renamed: '*) POLYGLOT_SYMBOLS="${POLYGLOT_SYMBOLS}>" ;;
|
|
esac
|
|
case $POLYGLOT_GIT_STATUS in
|
|
*'Untracked files:'*) POLYGLOT_SYMBOLS="${POLYGLOT_SYMBOLS}?" ;;
|
|
esac
|
|
|
|
[ -n "$POLYGLOT_SYMBOLS" ] && POLYGLOT_SYMBOLS=" $POLYGLOT_SYMBOLS"
|
|
|
|
printf ' (%s%s)' "${POLYGLOT_REF#refs/heads/}" "$POLYGLOT_SYMBOLS"
|
|
fi
|
|
|
|
unset POLYGLOT_REF POLYGLOT_GIT_STATUS POLYGLOT_SYMBOLS
|
|
}
|
|
|
|
###########################################################
|
|
# Native sh alternative to basename. See
|
|
# https://github.com/dylanaraps/pure-sh-bible
|
|
#
|
|
# Arguments:
|
|
# $1 Filename
|
|
# $2 Suffix
|
|
###########################################################
|
|
_polyglot_basename() {
|
|
POLYGLOT_BASENAME_DIR=${1%"${1##*[!/]}"}
|
|
POLYGLOT_BASENAME_DIR=${POLYGLOT_BASENAME_DIR##*/}
|
|
POLYGLOT_BASENAME_DIR=${POLYGLOT_BASENAME_DIR%"$2"}
|
|
|
|
printf '%s\n' "${POLYGLOT_BASENAME_DIR:-/}"
|
|
|
|
unset POLYGLOT_BASENAME_DIR
|
|
}
|
|
|
|
###########################################################
|
|
# Tests to see if the current shell is busybox ash
|
|
###########################################################
|
|
_polyglot_is_busybox() {
|
|
case $(help 2> /dev/null) in
|
|
'Built-in commands:'*) return 0 ;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
###########################################################
|
|
# Test to see if the current shell is pdksh or oksh
|
|
###########################################################
|
|
_polyglot_is_pdksh() {
|
|
case $KSH_VERSION in
|
|
*'PD KSH'*)
|
|
if [ "${POLYGLOT_UNAME:=$(uname -s)}" = 'OpenBSD' ] ||
|
|
[ "${0#-}" = 'oksh' ]; then
|
|
POLYGLOT_KSH_BANG='ksh'
|
|
fi
|
|
return 0
|
|
;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
###########################################################
|
|
# Test to see if the current shell is dtksh (Desktop Korn
|
|
# Shell).
|
|
###########################################################
|
|
_polyglot_is_dtksh() {
|
|
case ${0#-} in
|
|
*dtksh) return 0 ;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
###########################################################
|
|
# Test to see if sh is really dash
|
|
###########################################################
|
|
_polyglot_sh_is_dash() {
|
|
case $(ls -l "$(command -v "${0#-}")") in
|
|
*dash*) return 0 ;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
_polyglot_is_yash()
|
|
{
|
|
case "${0#-}" in
|
|
*yash) return 0 ;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
###########################################################
|
|
# Output virtual environment name
|
|
###########################################################
|
|
_polyglot_venv() {
|
|
# pipenv/poetry: when the virtualenv is in the project directory
|
|
if [ "${VIRTUAL_ENV##*/}" = '.venv' ]; then
|
|
POLYGLOT_VENV=${VIRTUAL_ENV%/.venv}
|
|
POLYGLOT_VENV=${POLYGLOT_VENV##*/}
|
|
# pipenv
|
|
elif [ -n "$PIPENV_ACTIVE" ]; then
|
|
POLYGLOT_VENV=${VIRTUAL_ENV%-*}
|
|
POLYGLOT_VENV=${POLYGLOT_VENV##*/}
|
|
# virtualenv/venv
|
|
elif [ -n "$VIRTUAL_ENV" ]; then
|
|
POLYGLOT_VENV=${VIRTUAL_ENV##*/}
|
|
# conda
|
|
elif [ -n "$CONDA_DEFAULT_ENV" ]; then
|
|
POLYGLOT_VENV=$CONDA_DEFAULT_ENV
|
|
fi
|
|
|
|
[ -n "$POLYGLOT_VENV" ] && printf '(%s) ' "$POLYGLOT_VENV"
|
|
|
|
unset POLYGLOT_VENV
|
|
}
|
|
|
|
#####################################################################
|
|
# zsh
|
|
#####################################################################
|
|
|
|
# Make sure that ZSH is not emulating ksh or bash
|
|
if [ -n "$ZSH_VERSION" ] && [ "${0#-}" != 'ksh' ] &&
|
|
[ "${0#-}" != 'bash' ] && [ "${0#-}" != 'sh' ]; then
|
|
|
|
setopt PROMPT_SUBST
|
|
|
|
###########################################################
|
|
# Runs right before the prompt is displayed
|
|
# Imitates bash's PROMPT_DIRTRIM behavior and calculates
|
|
# working branch and working copy status
|
|
###########################################################
|
|
_polyglot_precmd() {
|
|
psvar[2]=$(_polyglot_prompt_dirtrim "$POLYGLOT_PROMPT_DIRTRIM")
|
|
psvar[3]=$(_polyglot_branch_status)
|
|
psvar[5]=$(_polyglot_venv)
|
|
|
|
PS1=''
|
|
# The ZSH vi mode indicator won't work in Emacs shell (but it does in term
|
|
# and ansi-term)
|
|
if [ "$TERM" != 'dumb' ]; then
|
|
PS1+='%(4V.:.+)'
|
|
fi
|
|
if _polyglot_has_colors; then
|
|
PS1+='%(?..%B%F{red}(%?%)%b%f )'
|
|
PS1+='%5v'
|
|
PS1+='%(!.%S.%B%F{green})%n%1v%(!.%s.%f%b) '
|
|
PS1+='%B%F{blue}%2v%f%b'
|
|
PS1+='%F{yellow}%3v%f %# '
|
|
else
|
|
PS1+='%(?..(%?%) )'
|
|
PS1+='%5v'
|
|
PS1+='%(!.%S.)%n%1v%(!.%s.) '
|
|
PS1+='%2v'
|
|
PS1+='%3v %# '
|
|
fi
|
|
}
|
|
|
|
###########################################################
|
|
# Redraw the prompt when the vi mode changes
|
|
#
|
|
# Whn in vi mode, the prompt will use a bash 4.3-style
|
|
# mode indicator at the beginniing of the line: '+' for
|
|
# insert mode; ':' for command mode
|
|
#
|
|
# Underscores are used in this function's name to keep
|
|
# dash from choking on hyphens
|
|
###########################################################
|
|
_polyglot_zle_keymap_select() {
|
|
[ "$KEYMAP" = 'vicmd' ] && psvar[4]='vicmd' || psvar[4]=''
|
|
zle reset-prompt
|
|
zle -R
|
|
}
|
|
|
|
zle -N _polyglot_zle_keymap_select
|
|
zle -A _polyglot_zle_keymap_select zle-keymap-select
|
|
zle -A _polyglot_zle_keymap_select zle-line-init
|
|
|
|
###########################################################
|
|
# Redraw prompt when terminal size changes
|
|
###########################################################
|
|
TRAPWINCH() {
|
|
zle && zle -R
|
|
}
|
|
|
|
# TODO: add-zsh-hook was added in ZSH v4.3.4. It would be nice to be
|
|
# compatible with even earlier versions of ZSH, but that seems to require
|
|
# use of array syntax that is incompatible with ash.
|
|
autoload add-zsh-hook
|
|
add-zsh-hook precmd _polyglot_precmd
|
|
|
|
# Only display the $HOSTNAME for an ssh connection, except for a superuser
|
|
if _polyglot_is_ssh || _polyglot_is_superuser; then
|
|
psvar[1]="@${HOST%%\.*}"
|
|
else
|
|
psvar[1]=''
|
|
fi
|
|
|
|
unset RPROMPT # Clean up detritus from previously loaded prompts
|
|
|
|
#####################################################################
|
|
# bash
|
|
#####################################################################
|
|
elif [ -n "$BASH_VERSION" ]; then
|
|
|
|
###########################################################
|
|
# Create the bash $PROMPT_COMMAND
|
|
#
|
|
# If $1 is 0, bash's PROMPT_DIRTRIM abbreviations will be
|
|
# disabled; the only abbreviation that will occur is that
|
|
# $HOME will be displayed as ~.
|
|
#
|
|
# Arguments:
|
|
# $1 Number of directory elements to display
|
|
###########################################################
|
|
_polyglot_prompt_command() {
|
|
# $POLYGLOT_PROMPT_DIRTRIM must be greater than 0 and defaults to 2
|
|
[ "$1" ] && PROMPT_DIRTRIM=$1 || PROMPT_DIRTRIM=2
|
|
|
|
if ! _polyglot_is_superuser; then
|
|
if _polyglot_has_colors; then
|
|
PS1="\[\e[01;31m\]\$(_polyglot_exit_status \$?)\[\e[0m\]"
|
|
PS1+="\$(_polyglot_venv)"
|
|
PS1+="\[\e[01;32m\]\u$(printf '%s' "$POLYGLOT_HOSTNAME_STRING")\[\e[0m\] "
|
|
case $BASH_VERSION in
|
|
# bash, before v4.0, did not have $PROMPT_DIRTRIM
|
|
1.*|2.*|3.*)
|
|
PS1+="\[\e[01;34m\]\$(_polyglot_prompt_dirtrim \$POLYGLOT_PROMPT_DIRTRIM)\[\e[0m\]"
|
|
;;
|
|
*) PS1+="\[\e[01;34m\]\w\[\e[0m\]" ;;
|
|
esac
|
|
PS1+="\[\e[33m\]\$(_polyglot_branch_status)\[\e[0m\] \$ "
|
|
else
|
|
PS1="\$(_polyglot_exit_status \$?)"
|
|
PS1+="\$(_polyglot_venv)"
|
|
PS1+="\u$(printf '%s' "$POLYGLOT_HOSTNAME_STRING") "
|
|
case $BASH_VERSION in
|
|
1.*|2.*|3.*)
|
|
PS1="\$(_polyglot_prompt_dirtrim \$POLYGLOT_PROMPT_DIRTRIM)"
|
|
;;
|
|
*) PS1+="\w" ;;
|
|
esac
|
|
PS1+="\$(_polyglot_branch_status) \$ "
|
|
fi
|
|
else # Superuser
|
|
if _polyglot_has_colors; then
|
|
PS1="\[\e[01;31m\]\$(_polyglot_exit_status \$?)\[\e[0m\]"
|
|
PS1+="\$(_polyglot_venv)"
|
|
PS1+="\[\e[7m\]\u@\h\[\e[0m\] "
|
|
case $BASH_VERSION in
|
|
1.*|2.*|3.*)
|
|
PS1+="\[\e[01;34m\]\$(_polyglot_prompt_dirtrim \$POLYGLOT_PROMPT_DIRTRIM)\[\e[0m\]"
|
|
;;
|
|
*) PS1+="\[\e[01;34m\]\w\[\e[0m\]" ;;
|
|
esac
|
|
PS1+="\[\e[33m\]\$(_polyglot_branch_status)\[\e[0m\] # "
|
|
else
|
|
PS1="\$(_polyglot_exit_status \$?)"
|
|
PS1+="\$(_polyglot_venv)"
|
|
PS1+="\[\e[7m\]\u@\h\[\e[0m\] "
|
|
case $BASH_VERSION in
|
|
1.*|2.*|3.*)
|
|
PS1+="\$(_polyglot_prompt_dirtrim \$POLYGLOT_PROMPT_DIRTRIM)"
|
|
;;
|
|
*) PS1+="\w" ;;
|
|
esac
|
|
PS1+="\$(_polyglot_branch_status) # "
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Only display the $HOSTNAME for an ssh connection
|
|
if _polyglot_is_ssh; then
|
|
POLYGLOT_HOSTNAME_STRING='@\h'
|
|
else
|
|
POLYGLOT_HOSTNAME_STRING=''
|
|
fi
|
|
|
|
PROMPT_COMMAND='_polyglot_prompt_command $POLYGLOT_PROMPT_DIRTRIM'
|
|
|
|
# vi command mode
|
|
if [ "$TERM" != 'dumb' ]; then # Line editing not enabled in Emacs shell
|
|
bind 'set show-mode-in-prompt' # Since bash 4.3
|
|
bind 'set vi-ins-mode-string "+"'
|
|
bind 'set vi-cmd-mode-string ":"'
|
|
fi
|
|
#####################################################################
|
|
# ksh93, mksh, and zsh in bash, ksh, and sh emulation mode
|
|
#####################################################################
|
|
|
|
elif [ -n "$KSH_VERSION" ] || _polyglot_is_dtksh || [ -n "$ZSH_VERSION" ] &&
|
|
! _polyglot_is_pdksh ; then
|
|
# Only display the $HOSTNAME for an ssh connection
|
|
if _polyglot_is_ssh || _polyglot_is_superuser; then
|
|
POLYGLOT_HOSTNAME_STRING=$(hostname)
|
|
POLYGLOT_HOSTNAME_STRING="@${POLYGLOT_HOSTNAME_STRING%%\.*}"
|
|
else
|
|
POLYGLOT_HOSTNAME_STRING=''
|
|
fi
|
|
|
|
if [ "${0#-}" = 'bash' ] || [ "${0#-}" = 'sh' ]; then
|
|
POLYGLOT_KSH_BANG=''
|
|
else
|
|
case $KSH_VERSION in
|
|
*MIRBSD*) POLYGLOT_KSH_BANG='' ;;
|
|
*) POLYGLOT_KSH_BANG='ksh' ;;
|
|
esac
|
|
fi
|
|
|
|
case $KSH_VERSION in
|
|
*MIRBSD*)
|
|
# To know how long the prompt is, and thus to know how far it is to the
|
|
# edge of the screen, mksh requires an otherwise unused character (in this
|
|
# case \001) followed by a carriage return at the beginning of the
|
|
# prompt, which is then used to mark off escape sequences as zero-length.
|
|
# See https://www.mirbsd.org/htman/i386/man1/mksh.htm
|
|
if ! _polyglot_is_superuser; then
|
|
if _polyglot_has_colors; then
|
|
PS1=$(print "\001\r\001\E[31;1m\001")
|
|
PS1+='$(_polyglot_exit_status $?)'
|
|
PS1+=$(print "\001\E[0m")
|
|
PS1+='$(_polyglot_venv)'
|
|
PS1+=$(print "\E[32;1m\001")
|
|
PS1+='${LOGNAME:-$(logname)}$POLYGLOT_HOSTNAME_STRING'
|
|
PS1+=$(print "\001\E[0m\001")
|
|
PS1+=' '
|
|
PS1+=$(print "\001\E[34;1m\001")
|
|
PS1+='$(_polyglot_prompt_dirtrim "$POLYGLOT_PROMPT_DIRTRIM")'
|
|
PS1+=$(print "\001\E[0m\E[33m\001")
|
|
PS1+='$(_polyglot_branch_status $POLYGLOT_KSH_BANG)'
|
|
PS1+=$(print "\001\E[0m\001")
|
|
PS1+=' \$ '
|
|
else
|
|
PS1='$(_polyglot_exit_status $?)'
|
|
PS1+='$(_polyglot_venv)'
|
|
PS1+='${LOGNAME:-$(logname)}$POLYGLOT_HOSTNAME_STRING '
|
|
PS1+='$(_polyglot_prompt_dirtrim "$POLYGLOT_PROMPT_DIRTRIM")'
|
|
PS1+='$(_polyglot_branch_status $POLYGLOT_KSH_BANG)'
|
|
PS1+=' \$ '
|
|
fi
|
|
else # Superuser
|
|
if _polyglot_has_colors; then
|
|
PS1=$(print "\001\r\001\E[31;1m\001")
|
|
PS1+='$(_polyglot_exit_status $?)'
|
|
PS1+=$(print "\001\E[0m")
|
|
PS1+='$(_polyglot_venv)'
|
|
PS1+=$(print "\E[7m\001")
|
|
PS1+='${LOGNAME:-$(logname)}$POLYGLOT_HOSTNAME_STRING'
|
|
PS1+=$(print "\001\E[0m\001")
|
|
PS1+=' '
|
|
PS1+=$(print "\001\E[34;1m\001")
|
|
PS1+='$(_polyglot_prompt_dirtrim "$POLYGLOT_PROMPT_DIRTRIM")'
|
|
PS1+=$(print "\001\E[0m\E[33m\001")
|
|
PS1+='$(_polyglot_branch_status $POLYGLOT_KSH_BANG)'
|
|
PS1+=$(print "\001\E[0m\001")
|
|
PS1+=' # '
|
|
else
|
|
PS1=$(print "\001\r")
|
|
PS1+='$(_polyglot_exit_status $?)'
|
|
PS1+='$(_polyglot_venv)'
|
|
PS1+=$(print "\001\E[7m\001")
|
|
PS1+='${LOGNAME:-$(logname)}$POLYGLOT_HOSTNAME_STRING'
|
|
PS1+=$(print "\001\E[0m\001")
|
|
PS1+=' '
|
|
PS1+='$(_polyglot_prompt_dirtrim "$POLYGLOT_PROMPT_DIRTRIM")'
|
|
PS1+='$(_polyglot_branch_status $POLYGLOT_KSH_BANG)'
|
|
PS1+=' # '
|
|
fi
|
|
fi
|
|
;;
|
|
*)
|
|
if ! _polyglot_is_superuser; then
|
|
# zsh emulating other shells doesn't handle colors well
|
|
if _polyglot_has_colors && [ -z "$ZSH_VERSION" ]; then
|
|
# FreeBSD sh chokes on ANSI C quoting, so I'll avoid it
|
|
PS1="$(print '\E[31;1m$(_polyglot_exit_status $?)\E[0m$(_polyglot_venv)\E[32;1m${LOGNAME:-$(logname)}$POLYGLOT_HOSTNAME_STRING\E[0m \E[34;1m$(_polyglot_prompt_dirtrim "$POLYGLOT_PROMPT_DIRTRIM")\E[0m\E[33m$(_polyglot_branch_status $POLYGLOT_KSH_BANG)\E[0m \$ ')"
|
|
else
|
|
PS1='$(_polyglot_exit_status $?)$(_polyglot_venv)${LOGNAME:-$(logname)}$POLYGLOT_HOSTNAME_STRING $(_polyglot_prompt_dirtrim "$POLYGLOT_PROMPT_DIRTRIM")$(_polyglot_branch_status $POLYGLOT_KSH_BANG) \$ '
|
|
fi
|
|
else # Superuser
|
|
if _polyglot_has_colors && [ -z "$ZSH_VERSION" ]; then
|
|
PS1="$(print '\E[31;1m$(_polyglot_exit_status $?)\E[0m$(_polyglot_venv)\E[7m${LOGNAME:-$(logname)}$POLYGLOT_HOSTNAME_STRING\E[0m \E[34;1m$(_polyglot_prompt_dirtrim "$POLYGLOT_PROMPT_DIRTRIM")\E[0m\E[33m$(_polyglot_branch_status $POLYGLOT_KSH_BANG)\E[0m\E[0m # ')"
|
|
else
|
|
PS1="$(print '$(_polyglot_exit_status $?)$(_polyglot_venv)\E[7m${LOGNAME:-$(logname)}$POLYGLOT_HOSTNAME_STRING\E[0m $(_polyglot_prompt_dirtrim "$POLYGLOT_PROMPT_DIRTRIM")$(_polyglot_branch_status $POLYGLOT_KSH_BANG) # ')"
|
|
fi
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
####################################################################
|
|
# pdksh, oksh, dash, busybox ash, yash, osh,
|
|
# and zsh in sh emulation mode
|
|
####################################################################
|
|
|
|
elif _polyglot_is_pdksh || [ "${0#-}" = 'dash' ] || _polyglot_is_busybox ||
|
|
_polyglot_is_yash || _polyglot_sh_is_dash || [ "${0#-}" = 'osh' ]; then
|
|
|
|
# Only display the $HOSTNAME for an ssh connection
|
|
if _polyglot_is_ssh || _polyglot_is_superuser; then
|
|
POLYGLOT_HOSTNAME_STRING=$(hostname)
|
|
POLYGLOT_HOSTNAME_STRING="@${POLYGLOT_HOSTNAME_STRING%%\.*}"
|
|
else
|
|
POLYGLOT_HOSTNAME_STRING=''
|
|
fi
|
|
|
|
# pdksh uses an arbitrary non-printing character to delimit color escape
|
|
# sequences in the prompt. In practice, however, it is impossible to find
|
|
# one single non-printing character that will work with all operating systems
|
|
# and terminals. The Polyglot Prompt defaults to \021 for OpenBSD/NetBSD
|
|
# and \016 for everything else. If you want to specify your own non-printing
|
|
# character, do so thus:
|
|
#
|
|
# POLYGLOT_NP="\016" # Set this variable to whatever value you like
|
|
#
|
|
# Or set POLYGLOT_PDKSH_COLORS=0 to disable color entirely in pdksh.
|
|
|
|
case ${POLYGLOT_UNAME} in
|
|
NetBSD*|OpenBSD*) POLYGLOT_NP=${POLYGLOT_NP:-"\021"} ;;
|
|
*) POLYGLOT_NP=${POLYGLOT_NP:-"\016"} ;;
|
|
esac
|
|
|
|
if _polyglot_is_pdksh &&
|
|
_polyglot_has_colors &&
|
|
[ ${POLYGLOT_PDKSH_COLORS:-1} -ne 0 ]; then
|
|
|
|
PS1=$(print "$POLYGLOT_NP\r")
|
|
case $POLYGLOT_UNAME in
|
|
NetBSD*|OpenBSD*) PS1=$PS1$(print "$POLYGLOT_NP") ;;
|
|
esac
|
|
PS1=$PS1$(print "\033[31;1m$POLYGLOT_NP")
|
|
PS1=$PS1'$(_polyglot_exit_status $?)'
|
|
PS1=$PS1$(print "$POLYGLOT_NP\033[0m$POLYGLOT_NP")
|
|
PS1=$PS1'$(_polyglot_venv)'
|
|
if ! _polyglot_is_superuser; then
|
|
PS1=$PS1$(print "$POLYGLOT_NP\033[32;1m$POLYGLOT_NP")
|
|
else
|
|
PS1=$PS1$(print "$POLYGLOT_NP\033[7m$POLYGLOT_NP")
|
|
fi
|
|
PS1=$PS1'${LOGNAME:-$(logname)}$POLYGLOT_HOSTNAME_STRING'
|
|
PS1=$PS1$(print "$POLYGLOT_NP\033[0m$POLYGLOT_NP")
|
|
PS1=$PS1' '
|
|
PS1=$PS1$(print "$POLYGLOT_NP\033[34;1m$POLYGLOT_NP")
|
|
PS1=$PS1'$(_polyglot_prompt_dirtrim "$POLYGLOT_PROMPT_DIRTRIM")'
|
|
PS1=$PS1$(print "$POLYGLOT_NP\033[0m\033[33m$POLYGLOT_NP")
|
|
PS1=$PS1'$(_polyglot_branch_status $POLYGLOT_KSH_BANG)'
|
|
PS1=$PS1$(print "$POLYGLOT_NP\033[0m$POLYGLOT_NP")
|
|
PS1=$PS1' \$ '
|
|
|
|
elif _polyglot_is_yash || [ "${0#-}" = 'osh' ] && _polyglot_has_colors; then
|
|
PS1='\[\e[01;31m\]$(_polyglot_exit_status $?)\[\e[0m\]'
|
|
PS1=$PS1'$(_polyglot_venv)'
|
|
if ! _polyglot_is_superuser; then
|
|
PS1=$PS1'\[\e[01;32m\]${LOGNAME:-$(logname)}$POLYGLOT_HOSTNAME_STRING\[\e[0m\] '
|
|
else
|
|
PS1=$PS1'\[\e[7m\]${LOGNAME:-$(logname)}$POLYGLOT_HOSTNAME_STRING\[\e[0m\] '
|
|
fi
|
|
PS1=$PS1'\[\e[01;34m\]$(_polyglot_prompt_dirtrim "$POLYGLOT_PROMPT_DIRTRIM")\[\e[0m\]'
|
|
PS1=$PS1'\[\e[33m\]$(_polyglot_branch_status $POLYGLOT_KSH_BANG)\[\e[0m\] \$ '
|
|
else
|
|
PS1='$(_polyglot_exit_status $?)$(_polyglot_venv)${LOGNAME:-$(logname)}$POLYGLOT_HOSTNAME_STRING $(_polyglot_prompt_dirtrim "$POLYGLOT_PROMPT_DIRTRIM")$(_polyglot_branch_status $POLYGLOT_KSH_BANG) '
|
|
if ! _polyglot_is_superuser; then
|
|
PS1=$PS1'$ '
|
|
else
|
|
PS1=$PS1'# '
|
|
fi
|
|
fi
|
|
else
|
|
printf '%s\n' 'Polyglot Prompt does not support your shell.' >&2
|
|
fi
|
|
|
|
# Clean up environment
|
|
unset -f _polyglot_is_ssh _polyglot_basename _polyglot_is_busybox \
|
|
_polyglot_is_dtksh _polyglot_is_pdksh _polyglot_sh_is_dash
|
|
|
|
# vim: ts=2:et:sts=2:sw=2
|