# vim: filetype=sh # >>> prompt <<< if [ -n "${SSH_CONNECTION-}" ]; then _hc='\fy.' # yellow hostname for SSH remote else _hc='\fb.' # blue hostname for local fi if [ "$(id -u)" -eq 0 ]; then _uc='\fr.' # red username for root _2c='\fr.' # red PS2 for root else _uc='\fc.' # cyan username for non-root _2c= # PS2 in normal color for non-root user fi : ${LOGNAME:=$(logname)} : ${HOSTNAME:=$(uname -n)} # the main prompt ($YASH_PS1) contains the username, hostname, working # directory, last exit status (only if non-zero) YASH_PS1=$_uc'${LOGNAME}'$_hc'@${HOSTNAME}\fdi. '\ '${PWD/#$HOME/\~} \fD.${{?:/0/}:+\\fr.$?\\fd. }\$ ' YASH_PS1P='\fkt.' # predicted command YASH_PS1R='\fc.$(git branch --show-current 2>/dev/null)' # on the right YASH_PS1S='\fo.' # following lines YASH_PS2=$_2c'> ' YASH_PS2R= YASH_PS2S=$YASH_PS1S YASH_PS4='\fm.+ ' YASH_PS4S='\fmo.' unset _hc _uc _2c # no escape sequences allowed in the POSIXly-correct mode. PS1='${LOGNAME}@${HOSTNAME%%.*} '$PS1 # >>> options <<< # variables needed for command history HISTFILE=${XDG_CACHE_HOME:=~/.cache}/yash_history HISTSIZE=5000 # enable bash-like extended expansion set --brace-expand # enable recursive pathname expansion set --extended-glob # don't implicitly expand non-existent variables to empty strings set --no-unset # don't save commands starting with a space in history set --hist-space set --vi # if yash is built with line-editing enabled... if command --identify --builtin-command bindkey >/dev/null; then # print job status update ASAP, but only while line-editing set --notify-le # some terminfo data are broken; meta flags have to be ignored for UTF-8 set --le-no-conv-meta # enable command line prediction set --le-predict # key bindings for vi mode, some of which are from emacs mode bindkey --vi-insert '\#' eof-or-delete bindkey --vi-insert '\$' backward-kill-line bindkey --vi-insert '\N' complete-next-column bindkey --vi-insert '\P' complete-prev-column bindkey --vi-insert '\^A' beginning-of-line bindkey --vi-insert '\^B' backward-char bindkey --vi-insert '\^D' eof-or-delete bindkey --vi-insert '\^E' end-of-line bindkey --vi-insert '\^F' forward-char bindkey --vi-insert '\^K' forward-kill-line bindkey --vi-insert '\^L' clear-and-redraw-all bindkey --vi-insert '\^N' beginning-search-forward bindkey --vi-insert '\^O' clear-candidates bindkey --vi-insert '\^P' beginning-search-backward bindkey --vi-insert '\^U' backward-kill-line bindkey --vi-insert '\^W' backward-delete-viword bindkey --vi-insert '\^Y' put-left bindkey --vi-command '\^L' clear-and-redraw-all bindkey --vi-command '\^N' beginning-search-forward bindkey --vi-command '\^P' beginning-search-backward fi # ensure job control works as expected case $- in (*m*) trap - TSTP TTIN TTOU esac # if the terminal supports color... if [ "$(tput colors 2>/dev/null || echo 0)" -ge 8 ]; then # make command output colorful if ls --color=auto -d / >/dev/null 2>&1; then ls() { command ls --color=auto "$@"; } fi if grep --color=auto -q X <</dev/null; then grep() { command grep --color=auto "$@"; } fi fi # initialize event handlers COMMAND_NOT_FOUND_HANDLER=() PROMPT_COMMAND=() # find escape sequence to change terminal window title case "$TERM" in (xterm|xterm[+-]*|gnome|gnome[+-]*|putty|putty[+-]*|cygwin) _tsl='\033];' _fsl='\a' ;; (*) _tsl=$( (tput tsl 0; echo) 2>/dev/null | sed -e 's;\\;\\\\;g' -e 's;;\\033;g' -e 's;;\\a;g' -e 's;%;%%;g') _fsl=$( (tput fsl ; echo) 2>/dev/null | sed -e 's;\\;\\\\;g' -e 's;;\\033;g' -e 's;;\\a;g' -e 's;%;%%;g') ;; esac # if terminal window title can be changed... if [ "$_tsl" ] && [ "$_fsl" ]; then # set terminal window title on each prompt _set_term_title() if [ -t 2 ]; then printf "$_tsl"'%s@%s:%s'"$_fsl" "${LOGNAME}" "${HOSTNAME%%.*}" \ "${${PWD:/$HOME/\~}/#$HOME\//\~\/}" >&2 fi PROMPT_COMMAND=("$PROMPT_COMMAND" '_set_term_title') # reset window title when changing host or user ssh() { if [ -t 2 ]; then printf "$_tsl"'ssh %s'"$_fsl" "$*" >&2; fi command ssh "$@" } su() { if [ -t 2 ]; then printf "$_tsl"'su %s'"$_fsl" "$*" >&2; fi command su "$@" } doas() { if [ -t 2 ]; then printf "$_tsl"'doas %s'"$_fsl" "$*" >&2; fi command doas "$@" } fi # when a directory name is entered as a command, treat as "cd" _autocd() if [ -d "$1" ]; then HANDLED=true cd -- "$@" break -i fi COMMAND_NOT_FOUND_HANDLER=("$COMMAND_NOT_FOUND_HANDLER" '_autocd "$@"') # print file type when executing non-executable files _file_type() if [ -e "$1" ] && ! [ -d "$1" ]; then file -- "$1" fi COMMAND_NOT_FOUND_HANDLER=("$COMMAND_NOT_FOUND_HANDLER" '_file_type "$@"') # >>> common aliases and functions <<< alias -- -='cd -' alias la='ls -a' alias ll='ls -l' alias lla='ll -a' alias o='xdg-open' # usage: weather [some place] # defaults to london function weather() { curl v2.wttr.in/${1:-london} } # adds venv bin to path. python devs are not POSIX :( function venv() { export PATH="$(pwd)/.venv/bin:$PATH" } # try to load a host-specific file now [ -e ${XDG_CONFIG_HOME:=~/.config}/yash/$(uname -n) ] && . $XDG_CONFIG_HOME/yash/$(uname -n)