X-Git-Url: https://git.sev.monster/~sev/dotfiles.git/blobdiff_plain/6c74cef6ac35d25dd4991e7ff5cccada15eb0ffb..HEAD:/etc/zsh/.zshrc diff --git a/etc/zsh/.zshrc b/etc/zsh/.zshrc index 30625bd..893cac5 100644 --- a/etc/zsh/.zshrc +++ b/etc/zsh/.zshrc @@ -1,15 +1,27 @@ ### options -setopt NO_BEEP NO_CLOBBER \ - AUTO_CD CDABLE_VARS \ - EXTENDED_GLOB GLOB_DOTS GLOB_STAR_SHORT MARK_DIRS NUMERIC_GLOB_SORT \ - CORRECT_ALL INTERACTIVE_COMMENTS \ - GLOB_COMPLETE \ - AUTO_CONTINUE LONG_LIST_JOBS \ - NO_HIST_SAVE_BY_COPY HIST_IGNORE_DUPS SHARE_HISTORY HIST_REDUCE_BLANKS - -### imports -autoload -Uz zmv -autoload -Uz zmathfunc && zmathfunc +setopts=( + ## 16.2.1 Changing Directories + AUTO_CD CDABLE_VARS + ## 16.2.2 Completion + COMPLETE_IN_WORD GLOB_COMPLETE REC_EXACT + ## 16.2.3 Expansion and Globbing + EXTENDED_GLOB GLOB_DOTS GLOB_STAR_SHORT MAGIC_EQUAL_SUBST MARK_DIRS + NUMERIC_GLOB_SORT + ## 16.2.4 History + # NOTE: NO_HIST_SAVE_BY_COPY to allow saving histfile if updating another + # user's histfile. this is for compatibility with zsu. + HIST_FCNTL_LOCK HIST_IGNORE_DUPS HIST_IGNORE_SPACE HIST_LEX_WORDS + HIST_NO_STORE HIST_REDUCE_BLANKS NO_HIST_SAVE_BY_COPY SHARE_HISTORY + ## 16.2.6 Input/Output + NO_CLOBBER CLOBBER_EMPTY CORRECT_ALL INTERACTIVE_COMMENTS + HASH_EXECUTABLES_ONLY + ## 16.2.7 Job Control + AUTO_CONTINUE LONG_LIST_JOBS + ## 16.2.12 Zle + NO_BEEP +) +setopt $setopts +unset setopts ### exports ## common @@ -20,26 +32,110 @@ export PAGER=${$(whence -p less micro nano more)[(f)1]:s/micro/& -readonly true export GREP_OPTIONS=--color=auto ## histfile export HISTFILE=~/.histfile -export HISTSIZE=1000 -export SAVEHIST=1000 +export HISTSIZE=10000 +export SAVEHIST=$HISTSIZE ## python export PYTHONSTARTUP=${XDG_CONFIG_HOME:-~/.config}/pythonrc ## vim export VIMINIT='let$MYVIMRC=($XDG_CONFIG_HOME??($HOME."/.config"))."/vim/.vimrc"|execute"source"$MYVIMRC' -## wayland/sway -# XXX: only do this if we're actually in wayland, but without a start script -export XDG_SESSION_TYPE=wayland -export QT_QPA_PLATFORM=wayland-egl -export QT_WAYLAND_DISABLE_WINDOWDECORATION=-1 -export SDL_VIDEODRIVER=wayland -export TERMINAL=${$(whence -p konsole footclient urxvt xterm)[(f)1]} + +### imports +autoload -Uz zmv +autoload -Uz zmathfunc && zmathfunc + +## vcs +zstyle ':vcs_info:*' enable git +#zstyle ':vcs_info:git*' check-for-changes true #too slow +zstyle ':vcs_info:git*:dotfiles' check-for-changes true +zstyle ':vcs_info:git*' check-for-staged-changes true +autoload -Uz vcs_info + +## compinit +zstyle ':completion:*' auto-description '[arg] %d' +zstyle ':completion:*' expand suffix +zstyle ':completion:*' format '# %d' +zstyle ':completion:*' group-name '' +zstyle ':completion:*' ignore-parents parent +zstyle ':completion:*' insert-unambiguous false +zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS} +zstyle ':completion:*' list-prompt '%B%i%b' +zstyle ':completion:*' list-suffixes true +zstyle ':completion:*' matcher-list '' 'm:{[:lower:]}={[:upper:]}' 'm:{[:lower:][:upper:]}={[:upper:][:lower:]} r:|[._-]=* r:|=*' 'm:{[:lower:][:upper:]}={[:upper:][:lower:]} l:|=* r:|=*' +zstyle ':completion:*' menu select=1 +zstyle ':completion:*' original false +zstyle ':completion:*' select-prompt '%B%l%b' +zstyle ':completion:*' verbose true +autoload -Uz compinit +cache=${XDG_CACHE_HOME:-~/.cache}/zsh +[[ -d $cache ]] || mkdir -p $cache +compinit -d $cache/.zcompdump +unset cache ### keys -bindkey -v -KEYTIMEOUT=10 -## populate key array -if (( $#terminfo == 0 )) { - # terminfo is not set or empty +## set up zkbd-style key array +if [[ ! -v _sev_force_zkbd && ( -v terminfo || -v termcap ) ]] { + # use application (keypad transmit) mode if the terminal supports it + # NOTE: we have to do this because termcap/terminfo keys are usually + # defined in application mode. terminals that do not define these + # capabilities are assumed to always be in application mode. + if [[ ( -v terminfo[smkx] && -v terminfo[rmkx] ) || + ( -v termcap[ks] && -v terminfo[ke] ) ]] { + autoload -Uz add-zle-hook-widget + function _enter-application-mode { + [[ -v terminfo[smkx] ]] && echoti smkx || echotc ks + } + add-zle-hook-widget line-init _enter-application-mode + function _exit-application-mode { + [[ -v terminfo[rmkx] ]] && echoti rmkx || echotc ke + } + add-zle-hook-widget line-finish _exit-application-mode + trap _exit-application-mode EXIT + } + # pull keys from terminfo/termcap + # TODO: Menu and more Shift- modifiers + typeset -gA key + typeset -lA newkey + if [[ -v terminfo ]] { + src=terminfo + newkey=(F1 kf1 F2 kf2 F3 kf3 F4 kf4 F5 kf5 F6 kf6 F7 kf7 F8 kf8 F9 kf9 + F10 kf10 F11 kf11 F12 kf12 + Backspace kbs + Shift-Tab kcbt + Insert kich1 + Home khome + PageUp kpp + Delete kdch1 + End kend + PageDown knp + Up kcuu1 + Down kcud1 + Left kcub1 + Right kcuf1 + ) + } elif [[ -v termcap ]] { + src=termcap + newkey=(F1 k1 F2 k2 F3 k3 F4 k4 F5 k5 F6 k6 F7 k7 F8 k8 F9 k9 + F10 k\; F11 F1 F12 F2 + Backspace kb + Shift-Tab kB + Insert kI + Home kh + PageUp kP + Delete kD + End @7 + PageDown kN + Up ku + Down kd + Left kl + Right kr + ) + } + for k v (${(kv)newkey}) { + key[$k]=${${(P)src}[$v]} + } + unset k v src newkey +} else { + # use zkbd if termcap/terminfo unavailable function find_keymap { for f in ${ZDOTDIR:-~}/.zkbd/$TERM{-${DISPLAY:-$VENDOR-$OSTYPE},} [[ -f $f ]] && keymap=$f && break @@ -57,49 +153,20 @@ if (( $#terminfo == 0 )) { if [[ -n $keymap ]] { source $keymap } else { - echo "Failed to source keymap file $keymap" >&2 + echo -E "Failed to source keymap file $keymap" >&2 } unfunction find_keymap; unset keymap -} else { - # activate application mode for zle so terminfo keys work - # NOTE: don't do this for zkbd since application mode shouldn't have been - # enabled by zkbd when the keymap file was generated - if [[ -v terminfo[smkx] && -v terminfo[rmkx] ]] { - autoload -Uz add-zle-hook-widget - function _enter-application-mode { echoti smkx } - add-zle-hook-widget line-init _enter-application-mode - function _exit-application-mode { echoti rmkx } - add-zle-hook-widget line-finish _exit-application-mode - trap _exit-application-mode EXIT - } - # match zkbd hash as best we can to terminfo - typeset -gA key - key=(F1 kf1 F2 kf2 F3 kf3 F4 kf4 F5 kf5 F6 kf6 F7 kf7 F8 kf8 F9 kf9 - F10 kf10 F11 kf11 F12 kf12 - Backspace kbs - Backtab kcbt - Shift-Tab kcbt - Insert kich1 - Home khome - PageUp kpp - Delete kdch1 - End kend - PageDown knp - Up kcuu1 - Down kcud1 - Left kcub1 - Right kcuf1 - ) - for k v in ${(kv)key}; do - key[$k]=$terminfo[$v] - done; unset k v } + ## load history search autoload -Uz up-line-or-beginning-search down-line-or-beginning-search zle -N up-line-or-beginning-search zle -N down-line-or-beginning-search ## bind keys in both viins and vicmd modes +# NOTE: cursor keys are bound to normal/raw/nontransmit mode strings by +# default, and keys like Home and End are not bound at all, so we rebind +# everything to cover all scenarios typeset -A a a=( #key viins vicmd @@ -115,12 +182,12 @@ a=( Left 'backward-char' Right 'forward-char' ) -for k v in ${(kv)a}; do +for k v (${(kv)a}) { k=$key[$k] - if [[ -z "$k" ]] { continue } + if [[ -z $k ]] { continue } v=($=v) bindkey -- $k $v[1] - if [[ $v[2] == '-' ]] { + if [[ $v[2] == - ]] { # copy viins to vicmd verbatim bindkey -a -- $k $v[1] } elif (( $#v != 1 )) { @@ -130,10 +197,27 @@ for k v in ${(kv)a}; do # copy viins to vicmd and prepend vi- to it bindkey -a -- $k vi-$v[1] } -done +} unset a k v -### abbreviation aliases +## fzf +# bash-style reverse-search-history (i.e. reverse-i-search) +if [[ -v commands[fzf] ]] { + function _history-incremental-pattern-search-fzf { + l=(${(f)"$(fc -li -1 0 | fzf -e -m -n 1 +s --preview-window=hidden ${BUFFER:+-q $BUFFER})"}) + l=$(for x ("${l[@]}") { echo ${${=x}:3}; }) + BUFFER="$l" + } + zle -N _history-incremental-pattern-search-fzf + bindkey '^R' _history-incremental-pattern-search-fzf +} else { + bindkey '^R' history-incremental-pattern-search-backward +} + +### aliases +## builtins +alias rehash='_sev_setpath; rehash' +## utils alias h='fc -l -25' alias j='jobs -l' alias l='ls -AF' @@ -145,9 +229,24 @@ if [[ "$OSTYPE" =~ '^(free|net)bsd' ]] { alias p=\$PAGER alias e=\$EDITOR alias se=sudoedit +alias syncwatch='sync & watch -d grep -Fe Dirty: -e Writeback: /proc/meminfo' +if [[ -v commands[grep] ]] { + [[ -v commands[fgrep] ]] || alias fgrep='grep -F' + [[ -v commands[egrep] ]] || alias fgrep='grep -E' +} +for x (cat cmp diff grep test update) { + [[ -v commands[zutils-z$x] ]] || alias z$x=zutils-z$x +} # be paranoid alias cp='cp -ip' alias mv='mv -i' +# zsh zmv with noglob wildcards +alias zm='noglob zmv -WiM' +alias zc='noglob zmv -WiC' +alias zl='noglob zmv -WiL' +alias sm='noglob zmv -Wip"sudo mv"' +alias sc='noglob zmv -Wip"sudo cp"' +alias sl='noglob zmv -Wip"sudo ln"' if [[ "$OSTYPE" =~ '^freebsd' ]] { # don't confirm if only a few files are deleted alias rm='rm -I' @@ -156,29 +255,24 @@ if [[ "$OSTYPE" =~ '^freebsd' ]] { alias rm='rm -i' } [[ -v commands[trash-put] ]] && alias t=trash-put -## py venv -alias va='source bin/activate' -alias vd=deactivate -## ps -source ~/.local/bin/.check-busybox -if [[ -v commands[pstree] ]] && ! check-busybox pstree; then +# ps +if [[ -v commands[pstree] && $commands[pstree]:A:t != busybox ]] { # use pstree, but NOT busybox pstree because it kinda sucks - ps="pstree -wg3" -elif [[ "$OSTYPE" =~ '^freebsd' ]]; then - ps="ps -aSdfxwwouser=USR -ogroup=GRP -opid,nice=NI \ - -o%cpu,%mem,tty,stat,start=START -oetime,command" -elif check-busybox ps; then + ps='pstree -wg3' +} elif [[ "$OSTYPE" =~ '^freebsd' ]] { + ps='ps -aSdfxwwouser=USR -ogroup=GRP -opid,nice=NI \ + -o%cpu,%mem,tty,stat,start=START -oetime,command' +} elif [[ $commands[ps]:A:t == busybox ]] { # busybox compatible ps="ps -eouser='USR ' -ogroup='GRP ' \ -opid=' PID' -onice=' NI' -ovsz=' MEM' \ -otty,stat,etime,comm" -else +} else { # XXX: untested, posix # TODO: support gnu ps - ps="ps -eouser=USR -ogroup=GRP -opid,nice=NI \ - -opcpu=CPU -ovsz=MEM -otty,stat,etime,comm" -fi -unfunction check-busybox + ps='ps -eouser=USR -ogroup=GRP -opid,nice=NI \ + -opcpu=CPU -ovsz=MEM -otty,stat,etime,comm' +} if [[ "$(basename "$PAGER")" = "less" ]] { ps="$ps | less -S" } else { @@ -187,25 +281,62 @@ if [[ "$(basename "$PAGER")" = "less" ]] { alias pa=$ps alias spa="sudo $ps" unset ps - -### specialized aliases -## go up directories +## py venv +alias va='source bin/activate' +alias vd=deactivate +alias vu="python3 -mvenv --upgrade" +alias svu="sudo python3 -mvenv --upgrade" +## git +alias g=git +alias gd='git diff' +alias gdh='git diff HEAD' +alias gds='git diff --staged' +alias ga='git add' +alias ga.='git add .' +alias gai='git add -i' +alias gap='git add -p' +alias gc='git commit' +alias gca='git commit --amend' +alias gp='git push' +alias gu='git pull' +alias gl='git log' +alias gt='git tree' # from gitconfig +alias gsh='git show' +alias gst='git status' +alias gs='git stash' +alias gsp='git stash pop' +## cd/zoxide function up { \cd $(printf '../%.0s' {1..${1:-1}}) } alias u=up -## zoxide if [[ -v commands[zoxide] ]] { - eval "$(zoxide init zsh)" + # https://github.com/ajeetdsouza/zoxide/issues/513 + eval "${$(zoxide init zsh):s#_files -/#_cd#}" alias cd=z } -## git -alias ga='git add' -alias gdh='git diff HEAD' +alias cd..=up +## dotfiles +alias dfu='function { + pushd -q ${$(echo -E - ~/.zshenv):P:h:h} + git pull && + git submodule init && + git submodule sync && + git submodule update + popd -q +}' +## nocorrect +# zsh doesnt really handle sudo very well, so ignore it +alias sudo='nocorrect sudo' +## docker compose +alias dcp='sudo docker compose pull' +alias dcu='sudo docker compose up -d' +alias dcr='sudo docker compose restart' +alias dcl='sudo docker compose logs -f' ### hooks autoload -Uz add-zsh-hook -_sev_exectime= +typeset -gi _sev_exectime function sev_preexec { # change terminal title to show command print -n "\e]2;$(print -P '%#')${SSH_CLIENT+$USER@$HOST:}$1\e\\" @@ -238,7 +369,7 @@ add-zsh-hook chpwd sev_chpwd ### system-specific configs and aliases case $OSTYPE; in freebsd*) - # colors + ## colors export CLICOLOR= export LS_COLORS='di=34:ln=35:so=32:pi=33:ex=31:bd=46;34:cd=43;34:su=41;30:sg=46;30:tw=42;30:ow=43;30' @@ -248,8 +379,8 @@ case $OSTYPE; in ## install port dependencies from pkg (like pkgsrc `bmake bin-install') # XXX: should probably use package-depends where possible, breaks when - # port name is different to package name - # (eg. graphics/sdl20 == sdl2, devel/glib20 == glib2, etc) + # port name is different to package name + # (eg. graphics/sdl20 == sdl2, devel/glib20 == glib2, etc) function portpkg { case "$1" { build|run) @@ -274,7 +405,7 @@ case $OSTYPE; in function vol { if [[ -z "$1" ]] { for x in $(mixerctl -a | grep 'outputs\.master'); do - echo $x + echo -E - $x done return } @@ -287,38 +418,12 @@ case $OSTYPE; in function vol {} esac -### modules & styles -## vcs -zstyle ':vcs_info:*' enable git -#zstyle ':vcs_info:git*' check-for-changes true #too slow -zstyle ':vcs_info:git*:dotfiles' check-for-changes true -zstyle ':vcs_info:git*' check-for-staged-changes true -autoload -Uz vcs_info - -## compinit -zstyle ':completion:*' auto-description '[arg] %d' -zstyle ':completion:*' expand suffix -zstyle ':completion:*' format '# %d' -zstyle ':completion:*' group-name '' -zstyle ':completion:*' ignore-parents parent -zstyle ':completion:*' insert-unambiguous false -zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS} -zstyle ':completion:*' list-prompt '%B%i%b' -zstyle ':completion:*' list-suffixes true -zstyle ':completion:*' matcher-list '' 'm:{[:lower:]}={[:upper:]}' 'm:{[:lower:][:upper:]}={[:upper:][:lower:]} r:|[._-]=* r:|=*' 'm:{[:lower:][:upper:]}={[:upper:][:lower:]} l:|=* r:|=*' -zstyle ':completion:*' menu select=1 -zstyle ':completion:*' original false -zstyle ':completion:*' select-prompt '%B%l%b' -zstyle ':completion:*' verbose true -autoload -Uz compinit -cache=${XDG_CACHE_HOME:-~/.cache}/zsh -[[ -d $cache ]] || mkdir -p $cache -compinit -d $cache/.zcompdump -unset cache - ### prompt autoload -Uz promptinit && promptinit prompt arrows +### plugins +load-plugins zshrc + ### load site-specific load-site-dotfile zshrc