]> git.sev.monster Git - dotfiles.git/blob - etc/zsh/.zshrc
zsh: remove some pointless code and comments
[dotfiles.git] / etc / zsh / .zshrc
1 ### options
2 setopts=(
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   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
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 )
24 setopt $setopts
25 unset setopts
26
27 ### exports
28 ## common
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}
31 ## grep
32 # XXX: deprecated in GNU
33 export GREP_OPTIONS=--color=auto
34 ## histfile
35 export HISTFILE=~/.histfile
36 export HISTSIZE=10000
37 export SAVEHIST=$HISTSIZE
38 ## python
39 export PYTHONSTARTUP=${XDG_CONFIG_HOME:-~/.config}/pythonrc
40 ## vim
41 export VIMINIT='let$MYVIMRC=($XDG_CONFIG_HOME??($HOME."/.config"))."/vim/.vimrc"|execute"source"$MYVIMRC'
42
43 ### imports
44 autoload -Uz zmv
45 autoload -Uz zmathfunc && zmathfunc
46
47 ## vcs
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
52 autoload -Uz vcs_info
53
54 ## compinit
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
69 autoload -Uz compinit
70 cache=${XDG_CACHE_HOME:-~/.cache}/zsh
71 [[ -d $cache ]] || mkdir -p $cache
72 compinit -d $cache/.zcompdump
73 unset cache
74
75 ### keys
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
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]") {
147             echo
148             {
149                 autoload -Uz zkbd && zkbd
150             } always {
151                 TRY_BLOCK_ERROR=0
152                 unfunction zkbd
153             }
154             find_keymap
155         }
156         echo
157     }
158     if [[ -n $keymap ]] {
159         source $keymap
160     } else {
161         echo -E "Failed to source keymap file $keymap" >&2
162     }
163     unfunction find_keymap; unset keymap
164 }
165
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
170
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
175 typeset -A a
176 a=(
177     #key       viins                         vicmd
178     Backspace 'backward-delete-char          vi-backward-char'
179     Insert    'overwrite-mode                vi-insert'
180     Home      'beginning-of-line'
181     PageUp    'up-history                    -'
182     Delete    'delete-char'
183     End       'end-of-line'
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'
187     Left      'backward-char'
188     Right     'forward-char'
189 )
190 for k v (${(kv)a}) {
191     k=$key[$k]
192     if [[ -z $k ]] { continue }
193     v=($=v)
194     bindkey -- $k $v[1]
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]
201     } else {
202         # copy viins to vicmd and prepend vi- to it
203         bindkey -a -- $k vi-$v[1]
204     }
205 }
206 unset a k v
207
208 ## fzf
209 # bash-style reverse-search-history (i.e. reverse-i-search)
210 if [[ -v commands[fzf] ]] {
211     function _history-incremental-pattern-search-fzf {
212         fc -AI
213         # XXX: this shit is cursed and sometimes doesn't work
214         # TODO: remove doesn't work over newlines, fzf replaces them with \n,
215         #       and sed of course hates newlines and would need to be massaged
216         # TODO: interactive history refresh... can't get zsh to load histfile:
217         # +reload(HISTFILE='"$h HISTSIZE=$HISTSIZE SAVEHIST=$SAVEHIST \$0 +Z -dfimc 'setopt EXTENDED_HISTORY;fc -R \$HISTFILE;$c' </dev/null 2>&1)" \
218         local c='fc -lt%F -1 0'
219         local h="'${HISTFILE//\'/\'\\\'\'}'"
220         local l=(${(f)"$($=c | fzf \
221             --scheme=history -e -n 1,3.. \
222             +s \
223             -m --bind 'ctrl-d:execute-silent(sed -i -f <(
224                 sed -Ee '\''s/[$*.[\^/]/\\&/g;s~.*~/^\\(: [0-9]\\+:[0-9]\\+;\\)\\?&$/d~'\'' {+f3..}
225               ) '$h')+abort' \
226             --preview-window=hidden --height=20% \
227             --with-shell "${0:a} -dfc" \
228             ${BUFFER:+-q $BUFFER})"})
229         # XXX: this sucks, I hate this. no other way to flush internal history?
230         HISTFILE= HISTSIZE=0 fc -p $HISTFILE $HISTSIZE $SAVEHIST
231         l=$(for x ("${l[@]}") { echo ${${=x}:3}; })
232         BUFFER="$l"
233         zle reset-prompt
234     }
235     zle -N _history-incremental-pattern-search-fzf
236     bindkey '^R' _history-incremental-pattern-search-fzf
237 } else {
238     bindkey '^R' history-incremental-pattern-search-backward
239 }
240
241 ### aliases
242 ## builtins
243 alias rehash='_sev_setpath; rehash'
244 ## utils
245 alias h='fc -l -25'
246 alias j='jobs -l'
247 alias l='ls -AF'
248 if [[ "$OSTYPE" =~ '^(free|net)bsd' ]] {
249     alias ll='ls -lAFho'
250 } else {
251     alias ll='ls -lAFh'
252 }
253 alias p=\$PAGER
254 alias e=\$EDITOR
255 alias se=sudoedit
256 alias syncwatch='sync & watch -d grep -Fe Dirty: -e Writeback: /proc/meminfo'
257 if [[ -v commands[grep] ]] {
258     [[ -v commands[fgrep] ]] || alias fgrep='grep -F'
259     [[ -v commands[egrep] ]] || alias fgrep='grep -E'
260 }
261 for x (cat cmp diff grep test update) {
262     [[ -v commands[zutils-z$x] ]] || alias z$x=zutils-z$x
263 }
264 # be paranoid
265 alias cp='cp -ip'
266 alias mv='mv -i'
267 # zsh zmv with noglob wildcards
268 alias zm='noglob zmv -WiM'
269 alias zc='noglob zmv -WiC'
270 alias zl='noglob zmv -WiL'
271 alias sm='noglob zmv -Wip"sudo mv"'
272 alias sc='noglob zmv -Wip"sudo cp"'
273 alias sl='noglob zmv -Wip"sudo ln"'
274 if [[ "$OSTYPE" =~ '^freebsd' ]] {
275     # don't confirm if only a few files are deleted
276     alias rm='rm -I'
277 } else {
278     # TODO: similar behavior for non-freebsd, or impliment in zsh
279     alias rm='rm -i'
280 }
281 [[ -v commands[trash-put] ]] && alias t=trash-put
282 # ps
283 if [[ -v commands[pstree] && $commands[pstree]:A:t != busybox ]] {
284     # use pstree, but NOT busybox pstree because it kinda sucks
285     ps='pstree -wg3'
286 } elif [[ "$OSTYPE" =~ '^freebsd' ]] {
287     ps='ps -aSdfxwwouser=USR -ogroup=GRP -opid,nice=NI \
288        -o%cpu,%mem,tty,stat,start=START -oetime,command'
289 } elif [[ $commands[ps]:A:t == busybox ]] {
290     # busybox compatible
291     ps="ps -eouser='USR     ' -ogroup='GRP     ' \
292        -opid='  PID' -onice=' NI' -ovsz=' MEM' \
293        -otty,stat,etime,comm"
294 } else {
295     # XXX: untested, posix
296     # TODO: support gnu ps
297     ps='ps -eouser=USR -ogroup=GRP -opid,nice=NI \
298        -opcpu=CPU -ovsz=MEM -otty,stat,etime,comm'
299 }
300 if [[ "$(basename "$PAGER")" = "less" ]] {
301     ps="$ps | less -S"
302 } else {
303     ps="$ps | \"${PAGER:-more}\""
304 }
305 alias pa=$ps
306 alias spa="sudo $ps"
307 unset ps
308 ## py venv
309 alias va='source bin/activate'
310 alias vd=deactivate
311 alias vu="python3 -mvenv --upgrade"
312 alias svu="sudo python3 -mvenv --upgrade"
313 ## git
314 alias g=git
315 alias gd='git diff'
316 alias gdh='git diff HEAD'
317 alias gdp='git diff HEAD\^'
318 alias gds='git diff --staged'
319 alias ga='git add'
320 alias ga.='git add .'
321 alias gai='git add -i'
322 alias gap='git add -p'
323 alias gc='git commit'
324 alias gca='git commit --amend'
325 alias gp='git push'
326 alias gu='git pull'
327 alias gl='git log'
328 alias gt='git tree' # from gitconfig
329 alias gsh='git show'
330 alias gshn='git show --name-status'
331 alias gst='git status'
332 alias gsts='git status --short'
333 alias gs='git stash'
334 alias gsp='git stash pop'
335 alias gsd='git stash drop'
336 alias gss='git stash show -p'
337 alias grc='git rebase --continue'
338 ## cd/zoxide
339 function up {
340     \cd $(printf '../%.0s' {1..${1:-1}})
341 }
342 alias u=up
343 if [[ -v commands[zoxide] ]] {
344     # https://github.com/ajeetdsouza/zoxide/issues/513
345     eval "${$(zoxide init zsh):s#_files -/#_cd#}"
346     alias cd=z
347     alias z-='z -'
348 }
349 alias cd..=up
350 ## dotfiles
351 alias dfu='function {
352     pushd -q ${$(echo -E - ~/.zshenv):P:h:h}
353     git pull &&
354     git submodule init &&
355     git submodule sync &&
356     git submodule update
357     popd -q
358 }'
359 ## nocorrect
360 # zsh doesnt really handle sudo very well, so ignore it
361 alias sudo='nocorrect sudo'
362 ## docker compose
363 alias dcp='sudo docker compose pull'
364 alias dcu='sudo docker compose up -d'
365 alias dcr='sudo docker compose restart'
366 alias dcl='sudo docker compose logs -f'
367
368 ### hooks
369 autoload -Uz add-zsh-hook
370 typeset -gi _sev_exectime
371 function sev_preexec {
372     # change terminal title to show command
373     print -n "\e]2;$(print -P '%#')${SSH_CLIENT+$USER@$HOST:}$1\e\\"
374     # save last exec time for bell
375     # XXX: does not run for blank cmdline
376     _sev_exectime=$SECONDS
377     # update gpg forward, to always have unique filename and avoid clashes
378     if [[ -v _GNUPG_SOCK_DEST_EXT ]] {
379         export _GNUPG_SOCK_DEST_EXT=$(date +%s).$RANDOM
380         export _GNUPG_SOCK_DEST=$_GNUPG_SOCK_DEST_BASE.$_GNUPG_SOCK_DEST_EXT
381     }
382 }
383 add-zsh-hook preexec sev_preexec
384 function sev_precmd {
385     # change terminal title
386     # TODO: update and send BEL when job status changes
387     print -Pn "\e]2;%(1j,%j,)%#${SSH_CLIENT+$USER@$HOST:}%~\e\\"
388     # bell if exec takes 5s
389     if (( SECONDS - _sev_exectime >= 5 )) print "\a"
390     # we could update vcs_info here, but let prompt take care of it
391     # if it doesn't use vcs, it can be ignored safely
392 }
393 add-zsh-hook precmd sev_precmd
394 function sev_chpwd {
395     # echo dir on cwd change
396     ls -AF
397 }
398 add-zsh-hook chpwd sev_chpwd
399
400 ### prompt
401 autoload -Uz promptinit && promptinit
402 prompt arrows
403
404 ### plugins
405 load-plugins zshrc
406
407 ### load site-specific
408 load-site-dotfile zshrc
This page took 0.063118 seconds and 4 git commands to generate.