### 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
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
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
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 )) {
# copy viins to vicmd and prepend vi- to it
bindkey -a -- $k vi-$v[1]
}
-done
+}
unset a k v
-### abbreviation aliases
+## other binds
+# bash-style reverse-search-history (i.e. reverse-i-search)
+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'
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'
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 {
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 gs='git show'
+alias gst='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\\"
### 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'
## 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)
function vol {
if [[ -z "$1" ]] {
for x in $(mixerctl -a | grep 'outputs\.master'); do
- echo $x
+ echo -E - $x
done
return
}
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