]> git.sev.monster Git - dotfiles.git/blame - etc/zsh/.zshrc
make key handling and logout more robust
[dotfiles.git] / etc / zsh / .zshrc
CommitLineData
43016843 1### options
a7e41770 2setopt NO_BEEP NO_CLOBBER \
3 AUTO_CD CDABLE_VARS \
4 EXTENDED_GLOB GLOB_DOTS GLOB_STAR_SHORT MARK_DIRS NUMERIC_GLOB_SORT \
5 CORRECT_ALL INTERACTIVE_COMMENTS \
6 GLOB_COMPLETE \
7 AUTO_CONTINUE LONG_LIST_JOBS \
8 NO_HIST_SAVE_BY_COPY HIST_IGNORE_DUPS SHARE_HISTORY HIST_REDUCE_BLANKS
43016843 9
79d4a356 10### exports
11## common
8d4a98e1 12export EDITOR=${$(whence -p nvim vim vi micro nano emacs)[(f)1]}
13export PAGER=${$(whence -p less micro nano more)[(f)1]:s/micro/& -readonly true -multiopen tab/:s/nano/& --view}
79d4a356 14## grep
15# XXX: deprecated in GNU
16export GREP_OPTIONS=--color=auto
17## histfile
18export HISTFILE=~/.histfile
19export HISTSIZE=1000
20export SAVEHIST=1000
21## python
8d4a98e1 22export PYTHONSTARTUP=${XDG_CONFIG_HOME:-~/.config}/pythonrc
23## vim
e69caf64 24export VIMINIT='let$MYVIMRC=($XDG_CONFIG_HOME??($HOME."/.config"))."/vim/.vimrc"|execute"source"$MYVIMRC'
67052349 25## wayland/gui env
26export XDG_SESSION_TYPE=${XDG_SESSION_TYPE:-wayland}
27export QT_QPA_PLATFORM=${QT_QPA_PLATFORM:-wayland-egl}
28export QT_WAYLAND_DISABLE_WINDOWDECORATION=${QT_WAYLAND_DISABLE_WINDOWDECORATION:--1}
29export SDL_VIDEODRIVER=${SDL_VIDEODRIVER:-wayland}
30export TERMINAL=${TERMINAL:-$(whence -p konsole footclient urxvt xterm)[(f)1]}
79d4a356 31
2bf94bab 32### imports
33autoload -Uz zmv
34autoload -Uz zmathfunc && zmathfunc
35
36## vcs
37zstyle ':vcs_info:*' enable git
38#zstyle ':vcs_info:git*' check-for-changes true #too slow
39zstyle ':vcs_info:git*:dotfiles' check-for-changes true
40zstyle ':vcs_info:git*' check-for-staged-changes true
41autoload -Uz vcs_info
42
43## compinit
44zstyle ':completion:*' auto-description '[arg] %d'
45zstyle ':completion:*' expand suffix
46zstyle ':completion:*' format '# %d'
47zstyle ':completion:*' group-name ''
48zstyle ':completion:*' ignore-parents parent
49zstyle ':completion:*' insert-unambiguous false
50zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
51zstyle ':completion:*' list-prompt '%B%i%b'
52zstyle ':completion:*' list-suffixes true
53zstyle ':completion:*' matcher-list '' 'm:{[:lower:]}={[:upper:]}' 'm:{[:lower:][:upper:]}={[:upper:][:lower:]} r:|[._-]=* r:|=*' 'm:{[:lower:][:upper:]}={[:upper:][:lower:]} l:|=* r:|=*'
54zstyle ':completion:*' menu select=1
55zstyle ':completion:*' original false
56zstyle ':completion:*' select-prompt '%B%l%b'
57zstyle ':completion:*' verbose true
58autoload -Uz compinit
59cache=${XDG_CACHE_HOME:-~/.cache}/zsh
60[[ -d $cache ]] || mkdir -p $cache
61compinit -d $cache/.zcompdump
62unset cache
63
43016843 64### keys
b484bab8 65## set up zkbd-style key array
66if [[ ! -v _sev_force_zkbd && ( -v terminfo || -v termcap ) ]] {
67 # use application (keypad transmit) mode if the terminal supports it
68 # NOTE: we have to do this because termcap/terminfo keys are usually
69 # defined in application mode. terminals that do not define these
70 # capabilities are assumed to always be in application mode.
71 if [[ ( -v terminfo[smkx] && -v terminfo[rmkx] ) ||
72 ( -v termcap[ks] && -v terminfo[ke] ) ]] {
73 autoload -Uz add-zle-hook-widget
74 function _enter-application-mode {
75 [[ -v terminfo[smkx] ]] && echoti smkx || echotc ks
76 }
77 add-zle-hook-widget line-init _enter-application-mode
78 function _exit-application-mode {
79 [[ -v terminfo[rmkx] ]] && echoti rmkx || echotc ke
80 }
81 add-zle-hook-widget line-finish _exit-application-mode
82 trap _exit-application-mode EXIT
83 }
84 # pull keys from terminfo/termcap
85 # TODO: Menu and more Shift- modifiers
86 typeset -gA key
87 typeset -lA newkey
88 if [[ -v terminfo ]] {
89 src=terminfo
90 newkey=(F1 kf1 F2 kf2 F3 kf3 F4 kf4 F5 kf5 F6 kf6 F7 kf7 F8 kf8 F9 kf9
91 F10 kf10 F11 kf11 F12 kf12
92 Backspace kbs
93 Shift-Tab kcbt
94 Insert kich1
95 Home khome
96 PageUp kpp
97 Delete kdch1
98 End kend
99 PageDown knp
100 Up kcuu1
101 Down kcud1
102 Left kcub1
103 Right kcuf1
104 )
105 } elif [[ -v termcap ]] {
106 src=termcap
107 newkey=(F1 k1 F2 k2 F3 k3 F4 k4 F5 k5 F6 k6 F7 k7 F8 k8 F9 k9
108 F10 k\; F11 F1 F12 F2
109 Backspace kb
110 Shift-Tab kB
111 Insert kI
112 Home kh
113 PageUp kP
114 Delete kD
115 End @7
116 PageDown kN
117 Up ku
118 Down kd
119 Left kl
120 Right kr
121 )
122 }
123 for k v (${(kv)newkey}) {
124 key[$k]=${${(P)src}[$v]}
125 }
126 unset k v src newkey
127} else {
128 # use zkbd if termcap/terminfo unavailable
43016843 129 function find_keymap {
8d4a98e1 130 for f in ${ZDOTDIR:-~}/.zkbd/$TERM{-${DISPLAY:-$VENDOR-$OSTYPE},}
43016843 131 [[ -f $f ]] && keymap=$f && break
132 }
133 find_keymap
134 if [[ -z $keymap ]] {
135 if read -q "?Can't read terminfo. Add new zkbd keymap? [y/N]"; then
136 echo
137 autoload -Uz zkbd && zkbd
138 unfunction zkbd
139 find_keymap
140 fi
141 echo
142 }
143 if [[ -n $keymap ]] {
144 source $keymap
145 } else {
c3608beb 146 echo "Failed to source keymap file $keymap" >&2
43016843 147 }
148 unfunction find_keymap; unset keymap
43016843 149}
2bf94bab 150
5b9a654a 151## load history search
43016843 152autoload -Uz up-line-or-beginning-search down-line-or-beginning-search
153zle -N up-line-or-beginning-search
43016843 154zle -N down-line-or-beginning-search
43016843 155
5b9a654a 156## bind keys in both viins and vicmd modes
b484bab8 157# NOTE: cursor keys are bound to normal/raw/nontransmit mode strings by
158# default, and keys like Home and End are not bound at all, so we rebind
159# everything to cover all scenarios
5b9a654a 160typeset -A a
161a=(
162 #key viins vicmd
163 Backspace 'backward-delete-char vi-backward-char'
164 Insert 'overwrite-mode vi-insert'
165 Home 'beginning-of-line'
166 PageUp 'up-history -'
167 Delete 'delete-char'
168 End 'end-of-line'
169 PageDown 'down-history -'
170 Up 'up-line-or-beginning-search vi-up-line-or-history'
171 Down 'down-line-or-beginning-search vi-down-line-or-history'
172 Left 'backward-char'
173 Right 'forward-char'
174)
b484bab8 175for k v (${(kv)a}) {
5b9a654a 176 k=$key[$k]
b484bab8 177 if [[ -z $k ]] { continue }
5b9a654a 178 v=($=v)
179 bindkey -- $k $v[1]
b484bab8 180 if [[ $v[2] == - ]] {
5b9a654a 181 # copy viins to vicmd verbatim
182 bindkey -a -- $k $v[1]
183 } elif (( $#v != 1 )) {
184 # set vicmd to any other value
185 bindkey -a -- $k $v[2]
186 } else {
187 # copy viins to vicmd and prepend vi- to it
188 bindkey -a -- $k vi-$v[1]
189 }
b484bab8 190}
5b9a654a 191unset a k v
192
8a92a2c0 193### aliases
194## builtins
195alias rehash='_sev_setpath; rehash'
196## utils
8d4a98e1 197alias h='fc -l -25'
5b9a654a 198alias j='jobs -l'
199alias l='ls -AF'
43016843 200if [[ "$OSTYPE" =~ '^(free|net)bsd' ]] {
5b9a654a 201 alias ll='ls -lAFho'
43016843 202} else {
5b9a654a 203 alias ll='ls -lAFh'
43016843 204}
b053a418 205alias p=\$PAGER
206alias e=\$EDITOR
43016843 207alias se=sudoedit
5b9a654a 208# be paranoid
43016843 209alias cp='cp -ip'
210alias mv='mv -i'
211if [[ "$OSTYPE" =~ '^freebsd' ]] {
212 # don't confirm if only a few files are deleted
213 alias rm='rm -I'
214} else {
215 # TODO: similar behavior for non-freebsd, or impliment in zsh
216 alias rm='rm -i'
217}
8d4a98e1 218[[ -v commands[trash-put] ]] && alias t=trash-put
43016843 219## py venv
79d4a356 220alias va='source bin/activate'
221alias vd=deactivate
43016843 222## ps
8d4a98e1 223source ~/.local/bin/.check-busybox
79d4a356 224if [[ -v commands[pstree] ]] && ! check-busybox pstree; then
43016843 225 # use pstree, but NOT busybox pstree because it kinda sucks
226 ps="pstree -wg3"
227elif [[ "$OSTYPE" =~ '^freebsd' ]]; then
228 ps="ps -aSdfxwwouser=USR -ogroup=GRP -opid,nice=NI \
229 -o%cpu,%mem,tty,stat,start=START -oetime,command"
230elif check-busybox ps; then
231 # busybox compatible
232 ps="ps -eouser='USR ' -ogroup='GRP ' \
233 -opid=' PID' -onice=' NI' -ovsz=' MEM' \
234 -otty,stat,etime,comm"
235else
236 # XXX: untested, posix
237 # TODO: support gnu ps
238 ps="ps -eouser=USR -ogroup=GRP -opid,nice=NI \
239 -opcpu=CPU -ovsz=MEM -otty,stat,etime,comm"
240fi
241unfunction check-busybox
242if [[ "$(basename "$PAGER")" = "less" ]] {
109fad20 243 ps="$ps | less -S"
43016843 244} else {
245 ps="$ps | \"${PAGER:-more}\""
246}
79d4a356 247alias pa=$ps
43016843 248alias spa="sudo $ps"
249unset ps
2bf94bab 250## git
4851c231 251alias gd='git diff'
2bf94bab 252alias gdh='git diff HEAD'
253alias ga='git add'
254alias gc='git commit'
255alias gca='git commit --amend'
256alias gp='git push'
4851c231 257alias gu='git pull'
2bf94bab 258## cd/zoxide
5b9a654a 259function up {
b053a418 260 \cd $(printf '../%.0s' {1..${1:-1}})
5b9a654a 261}
79d4a356 262alias u=up
b053a418 263if [[ -v commands[zoxide] ]] {
8a92a2c0 264 # https://github.com/ajeetdsouza/zoxide/issues/513
265 eval "${$(zoxide init zsh):s#_files -/#_cd#}"
6c74cef6 266 alias cd=z
b053a418 267}
4851c231 268## dotfiles
269alias dfu='d=${$(echo ~/.zshenv):P:h:h};GIT_DIR=$d/.git GIT_WORK_TREE=$d git pull'
5b9a654a 270
43016843 271### hooks
272autoload -Uz add-zsh-hook
273_sev_exectime=
274function sev_preexec {
275 # change terminal title to show command
276 print -n "\e]2;$(print -P '%#')${SSH_CLIENT+$USER@$HOST:}$1\e\\"
277 # save last exec time for bell
278 # XXX: does not run for blank cmdline
279 _sev_exectime=$SECONDS
1ef46e01 280 # update gpg forward, to always have unique filename and avoid clashes
281 if [[ -v _GNUPG_SOCK_DEST_EXT ]] {
282 export _GNUPG_SOCK_DEST_EXT=$(date +%s).$RANDOM
283 export _GNUPG_SOCK_DEST=$_GNUPG_SOCK_DEST_BASE.$_GNUPG_SOCK_DEST_EXT
284 }
43016843 285}
286add-zsh-hook preexec sev_preexec
287function sev_precmd {
288 # change terminal title
289 # TODO: update and send BEL when job status changes
290 print -Pn "\e]2;%(1j,%j,)%#${SSH_CLIENT+$USER@$HOST:}%~\e\\"
291 # bell if exec takes 5s
292 if (( SECONDS - _sev_exectime >= 5 )) print "\a"
293 # we could update vcs_info here, but let prompt take care of it
294 # if it doesn't use vcs, it can be ignored safely
295}
296add-zsh-hook precmd sev_precmd
297function sev_chpwd {
298 # echo dir on cwd change
299 ls -AF
300}
301add-zsh-hook chpwd sev_chpwd
302
303### system-specific configs and aliases
79d4a356 304case $OSTYPE; in
43016843 305 freebsd*)
8a92a2c0 306 ## colors
43016843 307 export CLICOLOR=
308 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'
309
310 ## sound
311 function s { sysctl hw.snd.default_unit${1:+\=$1} }
312 alias vol mixer
313
314 ## install port dependencies from pkg (like pkgsrc `bmake bin-install')
315 # XXX: should probably use package-depends where possible, breaks when
8a92a2c0 316 # port name is different to package name
317 # (eg. graphics/sdl20 == sdl2, devel/glib20 == glib2, etc)
43016843 318 function portpkg {
319 case "$1" {
320 build|run)
321 sudo pkg install -AU $(make ${1}-depends-list |
322 sed 's_/usr/ports/_ _' | tr -d '\n')
323 ;;
324 *) echo "Usage: \`portpkg <build|run>' in a port directory"
325 return 1;;
326 }
327 };;
328 netbsd)
329 ## sound
330 function s {
331 if [[ -z "$1" ]] {
332 ll /dev/mixer /dev/sound /dev/audio
333 return
334 }
335 for x in mixer sound audio; do
336 ln -sf /dev/$x"$1" /dev/$x
337 done
338 }
339 function vol {
340 if [[ -z "$1" ]] {
341 for x in $(mixerctl -a | grep 'outputs\.master'); do
342 echo $x
343 done
344 return
345 }
346 mixerctl -w outputs.master"$2"="$1"
347 };;
348 *)
349 ## sound
8d4a98e1 350 # TODO: test alsa/oss/sndio/portaudio/pulse/pipewire in order of importance
43016843 351 function s {}
352 function vol {}
353esac
354
43016843 355### prompt
356autoload -Uz promptinit && promptinit
357prompt arrows
358
8eb81f95 359### load site-specific
4ced48ed 360load-site-dotfile zshrc
This page took 0.164517 seconds and 4 git commands to generate.