]> git.sev.monster Git - dotfiles.git/blame - etc/zsh/.zshrc
zshrc: enable EXTENDED_HISTORY
[dotfiles.git] / etc / zsh / .zshrc
CommitLineData
43016843 1### options
1795d46e 2setopts=(
3 ## 16.2.1 Changing Directories
4 AUTO_CD CDABLE_VARS
5 ## 16.2.2 Completion
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
9 NUMERIC_GLOB_SORT
10 ## 16.2.4 History
11 # NOTE: NO_HIST_SAVE_BY_COPY to allow saving histfile if updating another
12 # user's histfile. this is for compatibility with zsu.
77e83154 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
1795d46e 16 ## 16.2.6 Input/Output
17 NO_CLOBBER CLOBBER_EMPTY CORRECT_ALL INTERACTIVE_COMMENTS
18 HASH_EXECUTABLES_ONLY
19 ## 16.2.7 Job Control
20 AUTO_CONTINUE LONG_LIST_JOBS
21 ## 16.2.12 Zle
22 NO_BEEP
23)
24setopt $setopts
25unset setopts
43016843 26
79d4a356 27### exports
28## common
8d4a98e1 29export EDITOR=${$(whence -p nvim vim vi micro nano emacs)[(f)1]}
30export PAGER=${$(whence -p less micro nano more)[(f)1]:s/micro/& -readonly true -multiopen tab/:s/nano/& --view}
79d4a356 31## grep
32# XXX: deprecated in GNU
33export GREP_OPTIONS=--color=auto
34## histfile
35export HISTFILE=~/.histfile
1795d46e 36export HISTSIZE=10000
37export SAVEHIST=$HISTSIZE
79d4a356 38## python
8d4a98e1 39export PYTHONSTARTUP=${XDG_CONFIG_HOME:-~/.config}/pythonrc
40## vim
e69caf64 41export VIMINIT='let$MYVIMRC=($XDG_CONFIG_HOME??($HOME."/.config"))."/vim/.vimrc"|execute"source"$MYVIMRC'
79d4a356 42
2bf94bab 43### imports
44autoload -Uz zmv
45autoload -Uz zmathfunc && zmathfunc
46
47## vcs
48zstyle ':vcs_info:*' enable git
49#zstyle ':vcs_info:git*' check-for-changes true #too slow
50zstyle ':vcs_info:git*:dotfiles' check-for-changes true
51zstyle ':vcs_info:git*' check-for-staged-changes true
52autoload -Uz vcs_info
53
54## compinit
55zstyle ':completion:*' auto-description '[arg] %d'
56zstyle ':completion:*' expand suffix
57zstyle ':completion:*' format '# %d'
58zstyle ':completion:*' group-name ''
59zstyle ':completion:*' ignore-parents parent
60zstyle ':completion:*' insert-unambiguous false
61zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
62zstyle ':completion:*' list-prompt '%B%i%b'
63zstyle ':completion:*' list-suffixes true
64zstyle ':completion:*' matcher-list '' 'm:{[:lower:]}={[:upper:]}' 'm:{[:lower:][:upper:]}={[:upper:][:lower:]} r:|[._-]=* r:|=*' 'm:{[:lower:][:upper:]}={[:upper:][:lower:]} l:|=* r:|=*'
65zstyle ':completion:*' menu select=1
66zstyle ':completion:*' original false
67zstyle ':completion:*' select-prompt '%B%l%b'
68zstyle ':completion:*' verbose true
69autoload -Uz compinit
70cache=${XDG_CACHE_HOME:-~/.cache}/zsh
71[[ -d $cache ]] || mkdir -p $cache
72compinit -d $cache/.zcompdump
73unset cache
74
43016843 75### keys
b484bab8 76## set up zkbd-style key array
77if [[ ! -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
87 }
88 add-zle-hook-widget line-init _enter-application-mode
89 function _exit-application-mode {
90 [[ -v terminfo[rmkx] ]] && echoti rmkx || echotc ke
91 }
92 add-zle-hook-widget line-finish _exit-application-mode
93 trap _exit-application-mode EXIT
94 }
95 # pull keys from terminfo/termcap
96 # TODO: Menu and more Shift- modifiers
97 typeset -gA key
98 typeset -lA newkey
99 if [[ -v terminfo ]] {
100 src=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
103 Backspace kbs
104 Shift-Tab kcbt
105 Insert kich1
106 Home khome
107 PageUp kpp
108 Delete kdch1
109 End kend
110 PageDown knp
111 Up kcuu1
112 Down kcud1
113 Left kcub1
114 Right kcuf1
115 )
116 } elif [[ -v termcap ]] {
117 src=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
120 Backspace kb
121 Shift-Tab kB
122 Insert kI
123 Home kh
124 PageUp kP
125 Delete kD
126 End @7
127 PageDown kN
128 Up ku
129 Down kd
130 Left kl
131 Right kr
132 )
133 }
134 for k v (${(kv)newkey}) {
135 key[$k]=${${(P)src}[$v]}
136 }
137 unset k v src newkey
138} else {
139 # use zkbd if termcap/terminfo unavailable
43016843 140 function find_keymap {
8d4a98e1 141 for f in ${ZDOTDIR:-~}/.zkbd/$TERM{-${DISPLAY:-$VENDOR-$OSTYPE},}
43016843 142 [[ -f $f ]] && keymap=$f && break
143 }
144 find_keymap
145 if [[ -z $keymap ]] {
3cebacf8 146 if (read -q "?Can't read terminfo. Add new zkbd keymap? [y/N]") {
43016843 147 echo
148 autoload -Uz zkbd && zkbd
149 unfunction zkbd
150 find_keymap
3cebacf8 151 }
43016843 152 echo
153 }
154 if [[ -n $keymap ]] {
155 source $keymap
156 } else {
294ed44e 157 echo -E "Failed to source keymap file $keymap" >&2
43016843 158 }
159 unfunction find_keymap; unset keymap
43016843 160}
2bf94bab 161
5b9a654a 162## load history search
43016843 163autoload -Uz up-line-or-beginning-search down-line-or-beginning-search
164zle -N up-line-or-beginning-search
43016843 165zle -N down-line-or-beginning-search
43016843 166
5b9a654a 167## bind keys in both viins and vicmd modes
b484bab8 168# NOTE: cursor keys are bound to normal/raw/nontransmit mode strings by
169# default, and keys like Home and End are not bound at all, so we rebind
170# everything to cover all scenarios
5b9a654a 171typeset -A a
172a=(
173 #key viins vicmd
174 Backspace 'backward-delete-char vi-backward-char'
175 Insert 'overwrite-mode vi-insert'
176 Home 'beginning-of-line'
177 PageUp 'up-history -'
178 Delete 'delete-char'
179 End 'end-of-line'
180 PageDown 'down-history -'
181 Up 'up-line-or-beginning-search vi-up-line-or-history'
182 Down 'down-line-or-beginning-search vi-down-line-or-history'
183 Left 'backward-char'
184 Right 'forward-char'
185)
b484bab8 186for k v (${(kv)a}) {
5b9a654a 187 k=$key[$k]
b484bab8 188 if [[ -z $k ]] { continue }
5b9a654a 189 v=($=v)
190 bindkey -- $k $v[1]
b484bab8 191 if [[ $v[2] == - ]] {
5b9a654a 192 # copy viins to vicmd verbatim
193 bindkey -a -- $k $v[1]
194 } elif (( $#v != 1 )) {
195 # set vicmd to any other value
196 bindkey -a -- $k $v[2]
197 } else {
198 # copy viins to vicmd and prepend vi- to it
199 bindkey -a -- $k vi-$v[1]
200 }
b484bab8 201}
5b9a654a 202unset a k v
203
e45f1c99 204## fzf
d928d58f 205# bash-style reverse-search-history (i.e. reverse-i-search)
e45f1c99 206if [[ -v commands[fzf] ]] {
207 function _history-incremental-pattern-search-fzf {
50816b00 208 l=(${(f)"$(fc -li -1 0 | fzf -e -m -n 1 +s --preview-window=hidden ${BUFFER:+-q $BUFFER})"})
e45f1c99 209 l=$(for x ("${l[@]}") { echo ${${=x}:3}; })
210 BUFFER="$l"
211 }
212 zle -N _history-incremental-pattern-search-fzf
213 bindkey '^R' _history-incremental-pattern-search-fzf
214} else {
215 bindkey '^R' history-incremental-pattern-search-backward
216}
d928d58f 217
8a92a2c0 218### aliases
219## builtins
220alias rehash='_sev_setpath; rehash'
221## utils
8d4a98e1 222alias h='fc -l -25'
5b9a654a 223alias j='jobs -l'
224alias l='ls -AF'
43016843 225if [[ "$OSTYPE" =~ '^(free|net)bsd' ]] {
5b9a654a 226 alias ll='ls -lAFho'
43016843 227} else {
5b9a654a 228 alias ll='ls -lAFh'
43016843 229}
b053a418 230alias p=\$PAGER
231alias e=\$EDITOR
43016843 232alias se=sudoedit
44bf4f6c 233alias syncwatch='sync & watch -d grep -Fe Dirty: -e Writeback: /proc/meminfo'
b7e624f5 234if [[ -v commands[grep] ]] {
235 [[ -v commands[fgrep] ]] || alias fgrep='grep -F'
236 [[ -v commands[egrep] ]] || alias fgrep='grep -E'
237}
238for x (cat cmp diff grep test update) {
239 [[ -v commands[zutils-z$x] ]] || alias z$x=zutils-z$x
240}
5b9a654a 241# be paranoid
43016843 242alias cp='cp -ip'
243alias mv='mv -i'
4ab73520 244# zsh zmv with noglob wildcards
bfbd0519 245alias zm='noglob zmv -WiM'
246alias zc='noglob zmv -WiC'
247alias zl='noglob zmv -WiL'
248alias sm='noglob zmv -Wip"sudo mv"'
249alias sc='noglob zmv -Wip"sudo cp"'
250alias sl='noglob zmv -Wip"sudo ln"'
43016843 251if [[ "$OSTYPE" =~ '^freebsd' ]] {
252 # don't confirm if only a few files are deleted
253 alias rm='rm -I'
254} else {
255 # TODO: similar behavior for non-freebsd, or impliment in zsh
256 alias rm='rm -i'
257}
8d4a98e1 258[[ -v commands[trash-put] ]] && alias t=trash-put
4ab73520 259# ps
c0bfd3fe 260if [[ -v commands[pstree] && $commands[pstree]:A:t != busybox ]] {
43016843 261 # use pstree, but NOT busybox pstree because it kinda sucks
dd6dcbd4 262 ps='pstree -wg3'
c0bfd3fe 263} elif [[ "$OSTYPE" =~ '^freebsd' ]] {
dd6dcbd4 264 ps='ps -aSdfxwwouser=USR -ogroup=GRP -opid,nice=NI \
265 -o%cpu,%mem,tty,stat,start=START -oetime,command'
c0bfd3fe 266} elif [[ $commands[ps]:A:t == busybox ]] {
43016843 267 # busybox compatible
268 ps="ps -eouser='USR ' -ogroup='GRP ' \
269 -opid=' PID' -onice=' NI' -ovsz=' MEM' \
270 -otty,stat,etime,comm"
c0bfd3fe 271} else {
43016843 272 # XXX: untested, posix
273 # TODO: support gnu ps
dd6dcbd4 274 ps='ps -eouser=USR -ogroup=GRP -opid,nice=NI \
275 -opcpu=CPU -ovsz=MEM -otty,stat,etime,comm'
c0bfd3fe 276}
43016843 277if [[ "$(basename "$PAGER")" = "less" ]] {
109fad20 278 ps="$ps | less -S"
43016843 279} else {
280 ps="$ps | \"${PAGER:-more}\""
281}
79d4a356 282alias pa=$ps
43016843 283alias spa="sudo $ps"
284unset ps
4ab73520 285## py venv
286alias va='source bin/activate'
287alias vd=deactivate
a03b8371 288alias vu="python3 -mvenv --upgrade"
b3d00f21 289alias svu="sudo python3 -mvenv --upgrade"
2bf94bab 290## git
390f6e67 291alias g=git
4851c231 292alias gd='git diff'
2bf94bab 293alias gdh='git diff HEAD'
5052ea51 294alias gdp='git diff HEAD\^'
57f9ed7a 295alias gds='git diff --staged'
2bf94bab 296alias ga='git add'
0ca7cf36 297alias ga.='git add .'
57f9ed7a 298alias gai='git add -i'
299alias gap='git add -p'
2bf94bab 300alias gc='git commit'
301alias gca='git commit --amend'
302alias gp='git push'
4851c231 303alias gu='git pull'
390f6e67 304alias gl='git log'
305alias gt='git tree' # from gitconfig
1e14973b 306alias gsh='git show'
5052ea51 307alias gshn='git show --name-status'
1e14973b 308alias gst='git status'
5052ea51 309alias gsts='git status --short'
1e14973b 310alias gs='git stash'
57f9ed7a 311alias gsp='git stash pop'
5052ea51 312alias grc='git rebase --continue'
2bf94bab 313## cd/zoxide
5b9a654a 314function up {
b053a418 315 \cd $(printf '../%.0s' {1..${1:-1}})
5b9a654a 316}
79d4a356 317alias u=up
b053a418 318if [[ -v commands[zoxide] ]] {
8a92a2c0 319 # https://github.com/ajeetdsouza/zoxide/issues/513
320 eval "${$(zoxide init zsh):s#_files -/#_cd#}"
6c74cef6 321 alias cd=z
692a75d3 322 alias z-='z -'
b053a418 323}
0ca7cf36 324alias cd..=up
4851c231 325## dotfiles
7ed1509a 326alias dfu='function {
327 pushd -q ${$(echo -E - ~/.zshenv):P:h:h}
4ab73520 328 git pull &&
329 git submodule init &&
330 git submodule sync &&
331 git submodule update
7ed1509a 332 popd -q
8ec56e91 333}'
4ab73520 334## nocorrect
335# zsh doesnt really handle sudo very well, so ignore it
336alias sudo='nocorrect sudo'
337## docker compose
338alias dcp='sudo docker compose pull'
339alias dcu='sudo docker compose up -d'
340alias dcr='sudo docker compose restart'
341alias dcl='sudo docker compose logs -f'
5b9a654a 342
43016843 343### hooks
344autoload -Uz add-zsh-hook
5437a0d2 345typeset -gi _sev_exectime
43016843 346function sev_preexec {
347 # change terminal title to show command
348 print -n "\e]2;$(print -P '%#')${SSH_CLIENT+$USER@$HOST:}$1\e\\"
349 # save last exec time for bell
350 # XXX: does not run for blank cmdline
351 _sev_exectime=$SECONDS
1ef46e01 352 # update gpg forward, to always have unique filename and avoid clashes
353 if [[ -v _GNUPG_SOCK_DEST_EXT ]] {
354 export _GNUPG_SOCK_DEST_EXT=$(date +%s).$RANDOM
355 export _GNUPG_SOCK_DEST=$_GNUPG_SOCK_DEST_BASE.$_GNUPG_SOCK_DEST_EXT
356 }
43016843 357}
358add-zsh-hook preexec sev_preexec
359function sev_precmd {
360 # change terminal title
361 # TODO: update and send BEL when job status changes
362 print -Pn "\e]2;%(1j,%j,)%#${SSH_CLIENT+$USER@$HOST:}%~\e\\"
363 # bell if exec takes 5s
364 if (( SECONDS - _sev_exectime >= 5 )) print "\a"
365 # we could update vcs_info here, but let prompt take care of it
366 # if it doesn't use vcs, it can be ignored safely
367}
368add-zsh-hook precmd sev_precmd
369function sev_chpwd {
370 # echo dir on cwd change
371 ls -AF
372}
373add-zsh-hook chpwd sev_chpwd
374
375### system-specific configs and aliases
79d4a356 376case $OSTYPE; in
43016843 377 freebsd*)
8a92a2c0 378 ## colors
43016843 379 export CLICOLOR=
380 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'
381
382 ## sound
383 function s { sysctl hw.snd.default_unit${1:+\=$1} }
384 alias vol mixer
385
386 ## install port dependencies from pkg (like pkgsrc `bmake bin-install')
387 # XXX: should probably use package-depends where possible, breaks when
8a92a2c0 388 # port name is different to package name
389 # (eg. graphics/sdl20 == sdl2, devel/glib20 == glib2, etc)
43016843 390 function portpkg {
391 case "$1" {
392 build|run)
393 sudo pkg install -AU $(make ${1}-depends-list |
394 sed 's_/usr/ports/_ _' | tr -d '\n')
395 ;;
396 *) echo "Usage: \`portpkg <build|run>' in a port directory"
397 return 1;;
398 }
399 };;
400 netbsd)
401 ## sound
402 function s {
403 if [[ -z "$1" ]] {
404 ll /dev/mixer /dev/sound /dev/audio
405 return
406 }
407 for x in mixer sound audio; do
408 ln -sf /dev/$x"$1" /dev/$x
409 done
410 }
411 function vol {
412 if [[ -z "$1" ]] {
413 for x in $(mixerctl -a | grep 'outputs\.master'); do
294ed44e 414 echo -E - $x
43016843 415 done
416 return
417 }
418 mixerctl -w outputs.master"$2"="$1"
419 };;
420 *)
421 ## sound
8d4a98e1 422 # TODO: test alsa/oss/sndio/portaudio/pulse/pipewire in order of importance
43016843 423 function s {}
424 function vol {}
425esac
426
43016843 427### prompt
428autoload -Uz promptinit && promptinit
429prompt arrows
430
d3e867c0 431### plugins
432load-plugins zshrc
433
8eb81f95 434### load site-specific
4ced48ed 435load-site-dotfile zshrc
This page took 0.171934 seconds and 4 git commands to generate.