aboutsummaryrefslogtreecommitdiff
path: root/ksh/kshrc.d/prompt.ksh
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2016-12-17 17:46:15 +1300
committerTom Ryder <tom@sanctum.geek.nz>2016-12-17 17:53:22 +1300
commit700ac112a3dd2041de5fc2a6abd3781103c704a8 (patch)
tree91c0a928697f6ddef11312b95d391b5c9afbb5e4 /ksh/kshrc.d/prompt.ksh
parentResolve an issue with find(1) compatibility (diff)
downloaddotfiles-700ac112a3dd2041de5fc2a6abd3781103c704a8.tar.gz
dotfiles-700ac112a3dd2041de5fc2a6abd3781103c704a8.zip
Rename all pdksh stuff to ksh
As part of a foray into more active use of ksh and derivatives.
Diffstat (limited to 'ksh/kshrc.d/prompt.ksh')
-rw-r--r--ksh/kshrc.d/prompt.ksh201
1 files changed, 201 insertions, 0 deletions
diff --git a/ksh/kshrc.d/prompt.ksh b/ksh/kshrc.d/prompt.ksh
new file mode 100644
index 00000000..90e813f0
--- /dev/null
+++ b/ksh/kshrc.d/prompt.ksh
@@ -0,0 +1,201 @@
+# All of this is only known to work on OpenBSD's fork of pdksh
+case $KSH_VERSION in
+ *'PD KSH'*)
+ case $(uname -s) in
+ OpenBSD) ;;
+ *) return ;;
+ esac
+ ;;
+ *) return ;;
+esac
+
+# Frontend to controlling prompt
+prompt() {
+
+ # If no arguments, print the prompt strings as they are
+ if ! (($#)) ; then
+ printf '%s\n' PS1="$PS1" PS2="$PS2" PS3="$PS3" PS4="$PS4"
+ return
+ fi
+
+ # What's done next depends on the first argument to the function
+ case $1 in
+
+ # Turn complex, colored PS1 and debugging PS4 prompts on
+ on)
+ # Basic prompt shape depends on whether we're in SSH or not
+ PS1=
+ if [[ -n $SSH_CLIENT ]] || [[ -n $SSH_CONNECTION ]] ; then
+ PS1=$PS1'\u@\h:'
+ fi
+ PS1=$PS1'\w'
+
+ # Add sub-commands; VCS, job, and return status checks
+ PS1=$PS1'$(prompt vcs)$(prompt job)$(prompt ret "$?")'
+
+ # Add prefix and suffix
+ PS1='${PROMPT_PREFIX}'$PS1'${PROMPT_SUFFIX}'
+
+ # Add terminating "$" or "#" sign
+ PS1=$PS1'\$'
+
+ # Declare variables to contain terminal control strings
+ typeset format reset
+
+ # Disregard output and error from these tput(1) calls
+ {
+ # Count available colors
+ typeset -i colors
+ colors=$(tput colors || tput Co)
+
+ # Prepare reset code
+ reset=$(tput sgr0 || tput me)
+
+ # Check if we have non-bold bright yellow available
+ if ((colors >= 16)) ; then
+ format=$(
+ : "${PROMPT_COLOR:=11}"
+ tput setaf "$PROMPT_COLOR" ||
+ tput setaf "$PROMPT_COLOR" 0 0 ||
+ tput AF "$PROMPT_COLOR" ||
+ tput AF "$PROMPT_COLOR" 0 0
+ )
+
+ # If we have only eight colors, use bold yellow
+ elif ((colors >= 8)) ; then
+ format=$(
+ : "${PROMPT_COLOR:=3}"
+ tput setaf "$PROMPT_COLOR" ||
+ tput AF "$PROMPT_COLOR"
+ tput bold || tput md
+ )
+
+ # Otherwise, we just try bold
+ else
+ format=$(tput bold || tput md)
+ fi
+
+ } >/dev/null 2>&1
+
+ # String it all together
+ PS1='\['"$format"'\]'"$PS1"'\['"$reset"'\] '
+ PS2='> '
+ PS3='? '
+ PS4='+<$?> $LINENO:'
+ ;;
+
+ # Git prompt function
+ git)
+
+ # Wrap as compound command; we don't want to see output from any of
+ # these git(1) calls
+ {
+ # Bail if we're not in a work tree--or, implicitly, if we don't
+ # have git(1).
+ [[ -n $(git rev-parse --is-inside-work-tree) ]] ||
+ return
+
+ # Refresh index so e.g. git-diff-files(1) is accurate
+ git update-index --refresh
+
+ # Find a local branch, remote branch, or tag (annotated or
+ # not), or failing all of that just show the short commit ID,
+ # in that order of preference; if none of that works, bail out
+ typeset name
+ name=$(
+ git symbolic-ref --quiet HEAD ||
+ git describe --tags --exact-match HEAD ||
+ git rev-parse --short HEAD
+ ) || return
+ name=${name##*/}
+ [[ -n $name ]] || return
+
+ # Check various files in .git to flag processes
+ typeset proc
+ [[ -d .git/rebase-merge || -d .git/rebase-apply ]] &&
+ proc=${proc:+"$proc",}'REBASE'
+ [[ -f .git/MERGE_HEAD ]] &&
+ proc=${proc:+"$proc",}'MERGE'
+ [[ -f .git/CHERRY_PICK_HEAD ]] &&
+ proc=${proc:+"$proc",}'PICK'
+ [[ -f .git/REVERT_HEAD ]] &&
+ proc=${proc:+"$proc",}'REVERT'
+ [[ -f .git/BISECT_LOG ]] &&
+ proc=${proc:+"$proc",}'BISECT'
+
+ # Collect symbols representing repository state
+ typeset state
+
+ # Upstream HEAD has commits after local HEAD; we're "behind"
+ (($(git rev-list --count 'HEAD..@{u}'))) &&
+ state=${state}'<'
+
+ # Local HEAD has commits after upstream HEAD; we're "ahead"
+ (($(git rev-list --count '@{u}..HEAD'))) &&
+ state=${state}'>'
+
+ # Tracked files are modified
+ git diff-files --no-ext-diff --quiet ||
+ state=${state}'!!'
+
+ # Changes are staged
+ git diff-index --cached --no-ext-diff --quiet HEAD ||
+ state=${state}'+'
+
+ # There are some untracked and unignored files
+ git ls-files --directory --error-unmatch --exclude-standard \
+ --no-empty-directory --others -- ':/*' &&
+ state=${state}'?'
+
+ # There are stashed changes
+ git rev-parse --quiet --verify refs/stash &&
+ state=${state}'^'
+
+ } >/dev/null 2>&1
+
+ # Print the status in brackets; add a git: prefix only if there
+ # might be another VCS prompt (because PROMPT_VCS is set)
+ printf '(%s%s%s%s)' \
+ "${PROMPT_VCS:+git:}" "$name" "${proc:+:"$proc"}" "$state"
+ ;;
+
+ # Revert to simple inexpensive prompts
+ off)
+ PS1='\$ '
+ PS2='> '
+ PS3='? '
+ PS4='+ '
+ ;;
+
+ # VCS wrapper prompt function; print the first relevant prompt, if any
+ vcs)
+ typeset vcs
+ for vcs in "${PROMPT_VCS[@]:-git}" ; do
+ prompt "$vcs" && return
+ done
+ ;;
+
+ # Show return status of previous command in angle brackets, if not zero
+ ret)
+ local ret=$2
+ ((ret)) && printf '<%u>' "$ret"
+ ;;
+
+ # Show the count of background jobs in curly brackets, if not zero
+ job)
+ typeset -i jobc
+ jobc=$(jobs -p | sed -n '$=')
+ ((jobc)) && printf '{%u}' "$jobc"
+ ;;
+
+ # Print error
+ *)
+ printf 'prompt: Unknown command %s\n' "$1" >&2
+ return 2
+ ;;
+
+ esac
+}
+
+# Start with full-fledged prompt
+prompt on