]> git.sev.monster Git - dotfiles.git/blame_incremental - etc/zsh/.zshrc
zshrc: add z- alias
[dotfiles.git] / etc / zsh / .zshrc
... / ...
CommitLineData
1### options
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.
13 HIST_FCNTL_LOCK HIST_IGNORE_ALL_DUPS HIST_IGNORE_DUPS HIST_IGNORE_SPACE
14 HIST_LEX_WORDS HIST_NO_STORE HIST_REDUCE_BLANKS NO_HIST_SAVE_BY_COPY
15 HIST_SAVE_NO_DUPS SHARE_HISTORY
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
26
27### exports
28## common
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}
31## grep
32# XXX: deprecated in GNU
33export GREP_OPTIONS=--color=auto
34## histfile
35export HISTFILE=~/.histfile
36export HISTSIZE=10000
37export SAVEHIST=$HISTSIZE
38## python
39export PYTHONSTARTUP=${XDG_CONFIG_HOME:-~/.config}/pythonrc
40## vim
41export VIMINIT='let$MYVIMRC=($XDG_CONFIG_HOME??($HOME."/.config"))."/vim/.vimrc"|execute"source"$MYVIMRC'
42
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
75### keys
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
140 function find_keymap {
141 for f in ${ZDOTDIR:-~}/.zkbd/$TERM{-${DISPLAY:-$VENDOR-$OSTYPE},}
142 [[ -f $f ]] && keymap=$f && break
143 }
144 find_keymap
145 if [[ -z $keymap ]] {
146 if read -q "?Can't read terminfo. Add new zkbd keymap? [y/N]"; then
147 echo
148 autoload -Uz zkbd && zkbd
149 unfunction zkbd
150 find_keymap
151 fi
152 echo
153 }
154 if [[ -n $keymap ]] {
155 source $keymap
156 } else {
157 echo -E "Failed to source keymap file $keymap" >&2
158 }
159 unfunction find_keymap; unset keymap
160}
161
162## load history search
163autoload -Uz up-line-or-beginning-search down-line-or-beginning-search
164zle -N up-line-or-beginning-search
165zle -N down-line-or-beginning-search
166
167## bind keys in both viins and vicmd modes
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
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)
186for k v (${(kv)a}) {
187 k=$key[$k]
188 if [[ -z $k ]] { continue }
189 v=($=v)
190 bindkey -- $k $v[1]
191 if [[ $v[2] == - ]] {
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 }
201}
202unset a k v
203
204## fzf
205# bash-style reverse-search-history (i.e. reverse-i-search)
206if [[ -v commands[fzf] ]] {
207 function _history-incremental-pattern-search-fzf {
208 l=(${(f)"$(fc -li -1 0 | fzf -e -m -n 1 +s --preview-window=hidden ${BUFFER:+-q $BUFFER})"})
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}
217
218### aliases
219## builtins
220alias rehash='_sev_setpath; rehash'
221## utils
222alias h='fc -l -25'
223alias j='jobs -l'
224alias l='ls -AF'
225if [[ "$OSTYPE" =~ '^(free|net)bsd' ]] {
226 alias ll='ls -lAFho'
227} else {
228 alias ll='ls -lAFh'
229}
230alias p=\$PAGER
231alias e=\$EDITOR
232alias se=sudoedit
233alias syncwatch='sync & watch -d grep -Fe Dirty: -e Writeback: /proc/meminfo'
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}
241# be paranoid
242alias cp='cp -ip'
243alias mv='mv -i'
244# zsh zmv with noglob wildcards
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"'
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}
258[[ -v commands[trash-put] ]] && alias t=trash-put
259# ps
260if [[ -v commands[pstree] && $commands[pstree]:A:t != busybox ]] {
261 # use pstree, but NOT busybox pstree because it kinda sucks
262 ps='pstree -wg3'
263} elif [[ "$OSTYPE" =~ '^freebsd' ]] {
264 ps='ps -aSdfxwwouser=USR -ogroup=GRP -opid,nice=NI \
265 -o%cpu,%mem,tty,stat,start=START -oetime,command'
266} elif [[ $commands[ps]:A:t == busybox ]] {
267 # busybox compatible
268 ps="ps -eouser='USR ' -ogroup='GRP ' \
269 -opid=' PID' -onice=' NI' -ovsz=' MEM' \
270 -otty,stat,etime,comm"
271} else {
272 # XXX: untested, posix
273 # TODO: support gnu ps
274 ps='ps -eouser=USR -ogroup=GRP -opid,nice=NI \
275 -opcpu=CPU -ovsz=MEM -otty,stat,etime,comm'
276}
277if [[ "$(basename "$PAGER")" = "less" ]] {
278 ps="$ps | less -S"
279} else {
280 ps="$ps | \"${PAGER:-more}\""
281}
282alias pa=$ps
283alias spa="sudo $ps"
284unset ps
285## py venv
286alias va='source bin/activate'
287alias vd=deactivate
288alias vu="python3 -mvenv --upgrade"
289alias svu="sudo python3 -mvenv --upgrade"
290## git
291alias g=git
292alias gd='git diff'
293alias gdh='git diff HEAD'
294alias gdp='git diff HEAD\^'
295alias gds='git diff --staged'
296alias ga='git add'
297alias ga.='git add .'
298alias gai='git add -i'
299alias gap='git add -p'
300alias gc='git commit'
301alias gca='git commit --amend'
302alias gp='git push'
303alias gu='git pull'
304alias gl='git log'
305alias gt='git tree' # from gitconfig
306alias gsh='git show'
307alias gshn='git show --name-status'
308alias gst='git status'
309alias gsts='git status --short'
310alias gs='git stash'
311alias gsp='git stash pop'
312alias grc='git rebase --continue'
313## cd/zoxide
314function up {
315 \cd $(printf '../%.0s' {1..${1:-1}})
316}
317alias u=up
318if [[ -v commands[zoxide] ]] {
319 # https://github.com/ajeetdsouza/zoxide/issues/513
320 eval "${$(zoxide init zsh):s#_files -/#_cd#}"
321 alias cd=z
322 alias z-='z -'
323}
324alias cd..=up
325## dotfiles
326alias dfu='function {
327 pushd -q ${$(echo -E - ~/.zshenv):P:h:h}
328 git pull &&
329 git submodule init &&
330 git submodule sync &&
331 git submodule update
332 popd -q
333}'
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'
342
343### hooks
344autoload -Uz add-zsh-hook
345typeset -gi _sev_exectime
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
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 }
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
376case $OSTYPE; in
377 freebsd*)
378 ## colors
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
388 # port name is different to package name
389 # (eg. graphics/sdl20 == sdl2, devel/glib20 == glib2, etc)
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
414 echo -E - $x
415 done
416 return
417 }
418 mixerctl -w outputs.master"$2"="$1"
419 };;
420 *)
421 ## sound
422 # TODO: test alsa/oss/sndio/portaudio/pulse/pipewire in order of importance
423 function s {}
424 function vol {}
425esac
426
427### prompt
428autoload -Uz promptinit && promptinit
429prompt arrows
430
431### plugins
432load-plugins zshrc
433
434### load site-specific
435load-site-dotfile zshrc
This page took 0.044843 seconds and 4 git commands to generate.