main dotfiles / dot_config / yash / base.sh
Eric Bower  ·  2026-06-16
  1set --brace-expand    # bash-like extended exp
  2set --extended-glob   # recursive pathname exp
  3set --no-clobber      # prevent redirections from overwriting existing files
  4set --no-unset        # don't expand non-existent variables to empty strings
  5set --hist-space      # don't save cmds starting with a space in history
  6set --notify-le       # print job status update asap while line-editing
  7set --le-no-conv-meta # terminfo data broken; meta flags ignore utf-8
  8set --le-predict      # enable line prediction
  9set -o vi             # vim mode
 10
 11bindkey --vi-insert '\^F' accept-prediction
 12
 13sh() { yash --posix "$@"; }
 14yash() { command yash "$@"; }
 15
 16if [ "${COLORTERM-}" = "truecolor" ] || [ "${COLORTERM-}" = "24bit" ] || \
 17  [ "$(tput colors 2>/dev/null || echo 0)" -ge 8 ]; then
 18  ls() { command ls --color=auto "$@"; }
 19  grep() { command grep --color=auto "$@"; }
 20fi
 21
 22: ${LOGNAME:=$(logname)} ${HOSTNAME:=$(uname -n)}
 23# disable confusing treatment of arguments in the echo command
 24: ${ECHO_STYLE:=RAW}
 25
 26if ! [ "${HISTFILE-}" ]; then
 27  HISTFILE=${XDG_STATE_HOME:-~/.local/state}/yash/history
 28fi
 29# create HISTFILE parent directory if missing
 30! [ -d "${HISTFILE%/*}" ] && mkdir -p "${HISTFILE%/*}"
 31
 32HISTSIZE=5000
 33
 34# default mail check interval is too long
 35MAILCHECK=0
 36
 37# emulate bash's $SHLVL
 38if [ "${_old_shlvl+set}" != set ]; then
 39  _old_shlvl=${SHLVL-}
 40fi
 41SHLVL=$((_old_shlvl+1)) 2>/dev/null || SHLVL=1
 42export SHLVL
 43
 44# initialize event handlers
 45COMMAND_NOT_FOUND_HANDLER=()
 46PROMPT_COMMAND=()
 47POST_PROMPT_COMMAND=()
 48YASH_AFTER_CD=()
 49
 50# define prompt
 51if [ -n "${SSH_CONNECTION-}" ]; then
 52  _hc='\fy.'     # yellow hostname for SSH remote
 53else
 54  _hc='\fg.'     # green hostname for local
 55fi
 56if [ "$(id -u)" -eq 0 ]; then
 57  _uc='\fr.'     # red username for root
 58  _2c='\fr.'     # red PS2 for root
 59else
 60  _uc=$_hc _hc=  # same username color as hostname for non-root user
 61  _2c=           # PS2 in normal color for non-root user
 62fi
 63# The main prompt ($YASH_PS1) contains the username, hostname, working
 64# directory, last exit status (only if non-zero), and $SHLVL (only if
 65# non-one).
 66YASH_PS1=$_uc'${LOGNAME}'$_hc'@${HOSTNAME%%.*}\fd. '\
 67'${${${PWD:/~/\~}##*/}:-$PWD} ${{?:/0/}:+\\fr.$?\\fd. }${{SHLVL-0}:/1}\$ '
 68YASH_PS1S='\fo.'
 69YASH_PS2=$_2c'> '
 70YASH_PS2S=$YASH_PS1S
 71YASH_PS4='\fm.+ '
 72YASH_PS4S='\fmo.'
 73unset _hc _uc _2c
 74# No escape sequences allowed in the POSIXly-correct mode.
 75PS1='${LOGNAME}@${HOSTNAME%%.*} '$PS1
 76
 77# find escape sequence to change terminal window title
 78case "$TERM" in
 79  (xterm|xterm[+-]*|gnome|gnome[+-]*|putty|putty[+-]*|cygwin)
 80    _tsl='\033];' _fsl='\a' ;;
 81  (*)
 82    _tsl=$( (tput tsl 0; echo) 2>/dev/null |
 83    sed -e 's/\\/\\\\/g' -e 's/%/%%/g')
 84    _fsl=$( (tput fsl  ; echo) 2>/dev/null |
 85    sed -e 's/\\/\\\\/g' -e 's/%/%%/g') ;;
 86esac
 87# if terminal window title can be changed...
 88if [ "$_tsl" ] && [ "$_fsl" ]; then
 89  # set terminal window title on each prompt
 90  _set_term_title()
 91  if [ -t 2 ]; then
 92    printf "$_tsl"'%s@%s:%s'"$_fsl" "${LOGNAME}" "${HOSTNAME%%.*}" \
 93      "${${PWD:/$HOME/\~}/#$HOME\//\~\/}" >&2
 94  fi
 95  PROMPT_COMMAND=("$PROMPT_COMMAND" '_set_term_title')
 96
 97  # reset window title when changing host or user
 98  ssh() {
 99    if [ -t 2 ]; then printf "$_tsl"'ssh %s'"$_fsl" "$*" >&2; fi
100    command ssh "$@"
101  }
102  su() {
103    if [ -t 2 ]; then printf "$_tsl"'su %s'"$_fsl" "$*" >&2; fi
104    command su "$@"
105  }
106  sudo() {
107    if [ -t 2 ]; then printf "$_tsl"'sudo %s'"$_fsl" "$*" >&2; fi
108    command sudo "$@"
109  }
110  doas() {
111    if [ -t 2 ]; then printf "$_tsl"'doas %s'"$_fsl" "$*" >&2; fi
112    command doas "$@"
113  }
114fi
115
116_osc7_cwd() {
117  local tmp="${PWD}" encoded="" cut c esc
118  esc="$(printf '\33')"  # or: esc="$(/usr/bin/printf '\033')"
119  while [ -n "$tmp" ]; do
120    cut="${tmp#?}"
121    c="${tmp%"$cut"}"
122    case "$c" in
123      [-/:_.!\'\(\)~[:alnum:]]) encoded="$encoded$c" ;;
124      *) encoded="$encoded$(printf '%%%02X' "'$c")" ;;
125    esac
126    tmp="$cut"
127  done
128  printf '%s]7;file://%s%s%s\\' "$esc" "${HOSTNAME:-$(uname -n)}" "$encoded" "$esc" > /dev/tty
129}
130
131_update_direnv() {
132  if ! command -v direnv > /dev/null 2>&1; then
133    return
134  fi
135
136 eval "$(
137   direnv export json |
138   jq -r 'to_entries | .[] |
139   if .value == null then
140     @sh "unset \(.key)"
141   else
142     @sh "export \(.key)=\(.value)"
143   end'
144 )"
145}
146
147YASH_AFTER_CD=("$YASH_AFTER_CD" _osc7_cwd _update_direnv)
148_osc7_cwd
149_update_direnv > /dev/null 2>&1
150
151# kak: filetype=sh