3 ## 16.2.1 Changing Directories
6 COMPLETE_IN_WORD GLOB_COMPLETE REC_EXACT
7 ## 16.2.3 Expansion and Globbing
8 EXTENDED_GLOB GLOB_DOTS GLOB_STAR_SHORT MAGIC_EQUAL_SUBST MARK_DIRS
11 # NOTE: NO_HIST_SAVE_BY_COPY to allow saving histfile if updating another
12 # user's histfile. this is for compatibility with zsu.
13 EXTENDED_HISTORY HIST_FCNTL_LOCK HIST_IGNORE_ALL_DUPS HIST_IGNORE_DUPS
14 HIST_IGNORE_SPACE HIST_LEX_WORDS HIST_NO_STORE HIST_REDUCE_BLANKS
15 NO_HIST_SAVE_BY_COPY HIST_SAVE_NO_DUPS SHARE_HISTORY
16 ## 16.2.6 Input/Output
17 NO_CLOBBER CLOBBER_EMPTY CORRECT_ALL INTERACTIVE_COMMENTS
20 AUTO_CONTINUE LONG_LIST_JOBS
29 export EDITOR=${$(whence -p nvim vim vi micro nano emacs)[(f)1]}
30 export PAGER=${$(whence -p less micro nano more)[(f)1]:s/micro/& -readonly true -multiopen tab/:s/nano/& --view}
32 # XXX: deprecated in GNU
33 export GREP_OPTIONS=--color=auto
35 export HISTFILE=~/.histfile
37 export SAVEHIST=$HISTSIZE
39 export PYTHONSTARTUP=${XDG_CONFIG_HOME:-~/.config}/pythonrc
41 export VIMINIT='let$MYVIMRC=($XDG_CONFIG_HOME??($HOME."/.config"))."/vim/.vimrc"|execute"source"$MYVIMRC'
45 autoload -Uz zmathfunc && zmathfunc
48 zstyle ':vcs_info:*' enable git
49 #zstyle ':vcs_info:git*' check-for-changes true #too slow
50 zstyle ':vcs_info:git*:dotfiles' check-for-changes true
51 zstyle ':vcs_info:git*' check-for-staged-changes true
55 zstyle ':completion:*' auto-description '[arg] %d'
56 zstyle ':completion:*' expand suffix
57 zstyle ':completion:*' format '# %d'
58 zstyle ':completion:*' group-name ''
59 zstyle ':completion:*' ignore-parents parent
60 zstyle ':completion:*' insert-unambiguous false
61 zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
62 zstyle ':completion:*' list-prompt '%B%i%b'
63 zstyle ':completion:*' list-suffixes true
64 zstyle ':completion:*' matcher-list '' 'm:{[:lower:]}={[:upper:]}' 'm:{[:lower:][:upper:]}={[:upper:][:lower:]} r:|[._-]=* r:|=*' 'm:{[:lower:][:upper:]}={[:upper:][:lower:]} l:|=* r:|=*'
65 zstyle ':completion:*' menu select=1
66 zstyle ':completion:*' original false
67 zstyle ':completion:*' select-prompt '%B%l%b'
68 zstyle ':completion:*' verbose true
70 cache=${XDG_CACHE_HOME:-~/.cache}/zsh
71 [[ -d $cache ]] || mkdir -p $cache
72 compinit -d $cache/.zcompdump
76 ## set up zkbd-style key array
77 if [[ ! -v _sev_force_zkbd && ( -v terminfo || -v termcap ) ]] {
78 # use application (keypad transmit) mode if the terminal supports it
79 # NOTE: we have to do this because termcap/terminfo keys are usually
80 # defined in application mode. terminals that do not define these
81 # capabilities are assumed to always be in application mode.
82 if [[ ( -v terminfo[smkx] && -v terminfo[rmkx] ) ||
83 ( -v termcap[ks] && -v terminfo[ke] ) ]] {
84 autoload -Uz add-zle-hook-widget
85 function _enter-application-mode {
86 [[ -v terminfo[smkx] ]] && echoti smkx || echotc ks
88 add-zle-hook-widget line-init _enter-application-mode
89 function _exit-application-mode {
90 [[ -v terminfo[rmkx] ]] && echoti rmkx || echotc ke
92 add-zle-hook-widget line-finish _exit-application-mode
93 trap _exit-application-mode EXIT
95 # pull keys from terminfo/termcap
96 # TODO: Menu and more Shift- modifiers
99 if [[ -v terminfo ]] {
101 newkey=(F1 kf1 F2 kf2 F3 kf3 F4 kf4 F5 kf5 F6 kf6 F7 kf7 F8 kf8 F9 kf9
102 F10 kf10 F11 kf11 F12 kf12
116 } elif [[ -v termcap ]] {
118 newkey=(F1 k1 F2 k2 F3 k3 F4 k4 F5 k5 F6 k6 F7 k7 F8 k8 F9 k9
119 F10 k\; F11 F1 F12 F2
134 for k v (${(kv)newkey}) {
135 key[$k]=${${(P)src}[$v]}
139 # use zkbd if termcap/terminfo unavailable
140 function find_keymap {
141 for f in ${ZDOTDIR:-~}/.zkbd/$TERM{-${DISPLAY:-$VENDOR-$OSTYPE},}
142 [[ -f $f ]] && keymap=$f && break
145 if [[ -z $keymap ]] {
146 if (read -q "?Can't read terminfo. Add new zkbd keymap? [y/N]") {
149 autoload -Uz zkbd && zkbd
158 if [[ -n $keymap ]] {
161 echo -E "Failed to source keymap file $keymap" >&2
163 unfunction find_keymap; unset keymap
166 ## load history search
167 autoload -Uz up-line-or-beginning-search down-line-or-beginning-search
168 zle -N up-line-or-beginning-search
169 zle -N down-line-or-beginning-search
171 ## bind keys in both viins and vicmd modes
172 # NOTE: cursor keys are bound to normal/raw/nontransmit mode strings by
173 # default, and keys like Home and End are not bound at all, so we rebind
174 # everything to cover all scenarios
178 Backspace 'backward-delete-char vi-backward-char'
179 Insert 'overwrite-mode vi-insert'
180 Home 'beginning-of-line'
181 PageUp 'up-history -'
184 PageDown 'down-history -'
185 Up 'up-line-or-beginning-search vi-up-line-or-history'
186 Down 'down-line-or-beginning-search vi-down-line-or-history'
192 if [[ -z $k ]] { continue }
195 if [[ $v[2] == - ]] {
196 # copy viins to vicmd verbatim
197 bindkey -a -- $k $v[1]
198 } elif (( $#v != 1 )) {
199 # set vicmd to any other value
200 bindkey -a -- $k $v[2]
202 # copy viins to vicmd and prepend vi- to it
203 bindkey -a -- $k vi-$v[1]
209 # bash-style reverse-search-history (i.e. reverse-i-search)
210 if [[ -v commands[fzf] ]] {
211 function _history-incremental-pattern-search-fzf {
212 l=(${(f)"$(fc -li -1 0 | fzf -e -m -n 1 +s --preview-window=hidden ${BUFFER:+-q $BUFFER})"})
213 l=$(for x ("${l[@]}") { echo ${${=x}:3}; })
216 zle -N _history-incremental-pattern-search-fzf
217 bindkey '^R' _history-incremental-pattern-search-fzf
219 bindkey '^R' history-incremental-pattern-search-backward
224 alias rehash='_sev_setpath; rehash'
229 if [[ "$OSTYPE" =~ '^(free|net)bsd' ]] {
237 alias syncwatch='sync & watch -d grep -Fe Dirty: -e Writeback: /proc/meminfo'
238 if [[ -v commands[grep] ]] {
239 [[ -v commands[fgrep] ]] || alias fgrep='grep -F'
240 [[ -v commands[egrep] ]] || alias fgrep='grep -E'
242 for x (cat cmp diff grep test update) {
243 [[ -v commands[zutils-z$x] ]] || alias z$x=zutils-z$x
248 # zsh zmv with noglob wildcards
249 alias zm='noglob zmv -WiM'
250 alias zc='noglob zmv -WiC'
251 alias zl='noglob zmv -WiL'
252 alias sm='noglob zmv -Wip"sudo mv"'
253 alias sc='noglob zmv -Wip"sudo cp"'
254 alias sl='noglob zmv -Wip"sudo ln"'
255 if [[ "$OSTYPE" =~ '^freebsd' ]] {
256 # don't confirm if only a few files are deleted
259 # TODO: similar behavior for non-freebsd, or impliment in zsh
262 [[ -v commands[trash-put] ]] && alias t=trash-put
264 if [[ -v commands[pstree] && $commands[pstree]:A:t != busybox ]] {
265 # use pstree, but NOT busybox pstree because it kinda sucks
267 } elif [[ "$OSTYPE" =~ '^freebsd' ]] {
268 ps='ps -aSdfxwwouser=USR -ogroup=GRP -opid,nice=NI \
269 -o%cpu,%mem,tty,stat,start=START -oetime,command'
270 } elif [[ $commands[ps]:A:t == busybox ]] {
272 ps="ps -eouser='USR ' -ogroup='GRP ' \
273 -opid=' PID' -onice=' NI' -ovsz=' MEM' \
274 -otty,stat,etime,comm"
276 # XXX: untested, posix
277 # TODO: support gnu ps
278 ps='ps -eouser=USR -ogroup=GRP -opid,nice=NI \
279 -opcpu=CPU -ovsz=MEM -otty,stat,etime,comm'
281 if [[ "$(basename "$PAGER")" = "less" ]] {
284 ps="$ps | \"${PAGER:-more}\""
290 alias va='source bin/activate'
292 alias vu="python3 -mvenv --upgrade"
293 alias svu="sudo python3 -mvenv --upgrade"
297 alias gdh='git diff HEAD'
298 alias gdp='git diff HEAD\^'
299 alias gds='git diff --staged'
301 alias ga.='git add .'
302 alias gai='git add -i'
303 alias gap='git add -p'
304 alias gc='git commit'
305 alias gca='git commit --amend'
309 alias gt='git tree' # from gitconfig
311 alias gshn='git show --name-status'
312 alias gst='git status'
313 alias gsts='git status --short'
315 alias gsp='git stash pop'
316 alias grc='git rebase --continue'
319 \cd $(printf '../%.0s' {1..${1:-1}})
322 if [[ -v commands[zoxide] ]] {
323 # https://github.com/ajeetdsouza/zoxide/issues/513
324 eval "${$(zoxide init zsh):s#_files -/#_cd#}"
330 alias dfu='function {
331 pushd -q ${$(echo -E - ~/.zshenv):P:h:h}
333 git submodule init &&
334 git submodule sync &&
339 # zsh doesnt really handle sudo very well, so ignore it
340 alias sudo='nocorrect sudo'
342 alias dcp='sudo docker compose pull'
343 alias dcu='sudo docker compose up -d'
344 alias dcr='sudo docker compose restart'
345 alias dcl='sudo docker compose logs -f'
348 autoload -Uz add-zsh-hook
349 typeset -gi _sev_exectime
350 function sev_preexec {
351 # change terminal title to show command
352 print -n "\e]2;$(print -P '%#')${SSH_CLIENT+$USER@$HOST:}$1\e\\"
353 # save last exec time for bell
354 # XXX: does not run for blank cmdline
355 _sev_exectime=$SECONDS
356 # update gpg forward, to always have unique filename and avoid clashes
357 if [[ -v _GNUPG_SOCK_DEST_EXT ]] {
358 export _GNUPG_SOCK_DEST_EXT=$(date +%s).$RANDOM
359 export _GNUPG_SOCK_DEST=$_GNUPG_SOCK_DEST_BASE.$_GNUPG_SOCK_DEST_EXT
362 add-zsh-hook preexec sev_preexec
363 function sev_precmd {
364 # change terminal title
365 # TODO: update and send BEL when job status changes
366 print -Pn "\e]2;%(1j,%j,)%#${SSH_CLIENT+$USER@$HOST:}%~\e\\"
367 # bell if exec takes 5s
368 if (( SECONDS - _sev_exectime >= 5 )) print "\a"
369 # we could update vcs_info here, but let prompt take care of it
370 # if it doesn't use vcs, it can be ignored safely
372 add-zsh-hook precmd sev_precmd
374 # echo dir on cwd change
377 add-zsh-hook chpwd sev_chpwd
379 ### system-specific configs and aliases
384 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'
387 function s { sysctl hw.snd.default_unit${1:+\=$1} }
390 ## install port dependencies from pkg (like pkgsrc `bmake bin-install')
391 # XXX: should probably use package-depends where possible, breaks when
392 # port name is different to package name
393 # (eg. graphics/sdl20 == sdl2, devel/glib20 == glib2, etc)
397 sudo pkg install -AU $(make ${1}-depends-list |
398 sed 's_/usr/ports/_ _' | tr -d '\n')
400 *) echo "Usage: \`portpkg <build|run>' in a port directory"
408 ll /dev/mixer /dev/sound /dev/audio
411 for x in mixer sound audio; do
412 ln -sf /dev/$x"$1" /dev/$x
417 for x in $(mixerctl -a | grep 'outputs\.master'); do
422 mixerctl -w outputs.master"$2"="$1"
426 # TODO: test alsa/oss/sndio/portaudio/pulse/pipewire in order of importance
432 autoload -Uz promptinit && promptinit
438 ### load site-specific
439 load-site-dotfile zshrc