]>
Commit | Line | Data |
---|---|---|
43016843 | 1 | ### options |
1795d46e | 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. | |
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 | ) | |
24 | setopt $setopts | |
25 | unset setopts | |
43016843 | 26 | |
79d4a356 | 27 | ### exports |
28 | ## common | |
8d4a98e1 | 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} | |
79d4a356 | 31 | ## grep |
32 | # XXX: deprecated in GNU | |
33 | export GREP_OPTIONS=--color=auto | |
34 | ## histfile | |
35 | export HISTFILE=~/.histfile | |
1795d46e | 36 | export HISTSIZE=10000 |
37 | export SAVEHIST=$HISTSIZE | |
79d4a356 | 38 | ## python |
8d4a98e1 | 39 | export PYTHONSTARTUP=${XDG_CONFIG_HOME:-~/.config}/pythonrc |
40 | ## vim | |
e69caf64 | 41 | export VIMINIT='let$MYVIMRC=($XDG_CONFIG_HOME??($HOME."/.config"))."/vim/.vimrc"|execute"source"$MYVIMRC' |
79d4a356 | 42 | |
2bf94bab | 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 | ||
43016843 | 75 | ### keys |
b484bab8 | 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 | |
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 |
388772f1 | 148 | { |
149 | autoload -Uz zkbd && zkbd | |
150 | } always { | |
151 | TRY_BLOCK_ERROR=0 | |
152 | unfunction zkbd | |
153 | } | |
43016843 | 154 | find_keymap |
3cebacf8 | 155 | } |
43016843 | 156 | echo |
157 | } | |
158 | if [[ -n $keymap ]] { | |
159 | source $keymap | |
160 | } else { | |
294ed44e | 161 | echo -E "Failed to source keymap file $keymap" >&2 |
43016843 | 162 | } |
163 | unfunction find_keymap; unset keymap | |
43016843 | 164 | } |
2bf94bab | 165 | |
5b9a654a | 166 | ## load history search |
43016843 | 167 | autoload -Uz up-line-or-beginning-search down-line-or-beginning-search |
168 | zle -N up-line-or-beginning-search | |
43016843 | 169 | zle -N down-line-or-beginning-search |
43016843 | 170 | |
5b9a654a | 171 | ## bind keys in both viins and vicmd modes |
b484bab8 | 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 | |
5b9a654a | 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 | ) | |
b484bab8 | 190 | for k v (${(kv)a}) { |
5b9a654a | 191 | k=$key[$k] |
b484bab8 | 192 | if [[ -z $k ]] { continue } |
5b9a654a | 193 | v=($=v) |
194 | bindkey -- $k $v[1] | |
b484bab8 | 195 | if [[ $v[2] == - ]] { |
5b9a654a | 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 | } | |
b484bab8 | 205 | } |
5b9a654a | 206 | unset a k v |
207 | ||
e45f1c99 | 208 | ## fzf |
d928d58f | 209 | # bash-style reverse-search-history (i.e. reverse-i-search) |
e45f1c99 | 210 | if [[ -v commands[fzf] ]] { |
211 | function _history-incremental-pattern-search-fzf { | |
da38ca4b | 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 | |
e45f1c99 | 231 | l=$(for x ("${l[@]}") { echo ${${=x}:3}; }) |
232 | BUFFER="$l" | |
da38ca4b | 233 | zle reset-prompt |
e45f1c99 | 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 | } | |
d928d58f | 240 | |
8a92a2c0 | 241 | ### aliases |
242 | ## builtins | |
243 | alias rehash='_sev_setpath; rehash' | |
244 | ## utils | |
8d4a98e1 | 245 | alias h='fc -l -25' |
5b9a654a | 246 | alias j='jobs -l' |
247 | alias l='ls -AF' | |
43016843 | 248 | if [[ "$OSTYPE" =~ '^(free|net)bsd' ]] { |
5b9a654a | 249 | alias ll='ls -lAFho' |
43016843 | 250 | } else { |
5b9a654a | 251 | alias ll='ls -lAFh' |
43016843 | 252 | } |
b053a418 | 253 | alias p=\$PAGER |
254 | alias e=\$EDITOR | |
43016843 | 255 | alias se=sudoedit |
44bf4f6c | 256 | alias syncwatch='sync & watch -d grep -Fe Dirty: -e Writeback: /proc/meminfo' |
b7e624f5 | 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 | } | |
5b9a654a | 264 | # be paranoid |
43016843 | 265 | alias cp='cp -ip' |
266 | alias mv='mv -i' | |
4ab73520 | 267 | # zsh zmv with noglob wildcards |
bfbd0519 | 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"' | |
43016843 | 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 | } | |
8d4a98e1 | 281 | [[ -v commands[trash-put] ]] && alias t=trash-put |
4ab73520 | 282 | # ps |
c0bfd3fe | 283 | if [[ -v commands[pstree] && $commands[pstree]:A:t != busybox ]] { |
43016843 | 284 | # use pstree, but NOT busybox pstree because it kinda sucks |
dd6dcbd4 | 285 | ps='pstree -wg3' |
c0bfd3fe | 286 | } elif [[ "$OSTYPE" =~ '^freebsd' ]] { |
dd6dcbd4 | 287 | ps='ps -aSdfxwwouser=USR -ogroup=GRP -opid,nice=NI \ |
288 | -o%cpu,%mem,tty,stat,start=START -oetime,command' | |
c0bfd3fe | 289 | } elif [[ $commands[ps]:A:t == busybox ]] { |
43016843 | 290 | # busybox compatible |
291 | ps="ps -eouser='USR ' -ogroup='GRP ' \ | |
292 | -opid=' PID' -onice=' NI' -ovsz=' MEM' \ | |
293 | -otty,stat,etime,comm" | |
c0bfd3fe | 294 | } else { |
43016843 | 295 | # XXX: untested, posix |
296 | # TODO: support gnu ps | |
dd6dcbd4 | 297 | ps='ps -eouser=USR -ogroup=GRP -opid,nice=NI \ |
298 | -opcpu=CPU -ovsz=MEM -otty,stat,etime,comm' | |
c0bfd3fe | 299 | } |
43016843 | 300 | if [[ "$(basename "$PAGER")" = "less" ]] { |
109fad20 | 301 | ps="$ps | less -S" |
43016843 | 302 | } else { |
303 | ps="$ps | \"${PAGER:-more}\"" | |
304 | } | |
79d4a356 | 305 | alias pa=$ps |
43016843 | 306 | alias spa="sudo $ps" |
307 | unset ps | |
4ab73520 | 308 | ## py venv |
309 | alias va='source bin/activate' | |
310 | alias vd=deactivate | |
a03b8371 | 311 | alias vu="python3 -mvenv --upgrade" |
b3d00f21 | 312 | alias svu="sudo python3 -mvenv --upgrade" |
2bf94bab | 313 | ## git |
390f6e67 | 314 | alias g=git |
4851c231 | 315 | alias gd='git diff' |
2bf94bab | 316 | alias gdh='git diff HEAD' |
5052ea51 | 317 | alias gdp='git diff HEAD\^' |
57f9ed7a | 318 | alias gds='git diff --staged' |
2bf94bab | 319 | alias ga='git add' |
0ca7cf36 | 320 | alias ga.='git add .' |
57f9ed7a | 321 | alias gai='git add -i' |
322 | alias gap='git add -p' | |
2bf94bab | 323 | alias gc='git commit' |
324 | alias gca='git commit --amend' | |
325 | alias gp='git push' | |
4851c231 | 326 | alias gu='git pull' |
390f6e67 | 327 | alias gl='git log' |
328 | alias gt='git tree' # from gitconfig | |
1e14973b | 329 | alias gsh='git show' |
5052ea51 | 330 | alias gshn='git show --name-status' |
1e14973b | 331 | alias gst='git status' |
5052ea51 | 332 | alias gsts='git status --short' |
1e14973b | 333 | alias gs='git stash' |
57f9ed7a | 334 | alias gsp='git stash pop' |
d2204ed1 | 335 | alias gsd='git stash drop' |
336 | alias gss='git stash show -p' | |
5052ea51 | 337 | alias grc='git rebase --continue' |
2bf94bab | 338 | ## cd/zoxide |
5b9a654a | 339 | function up { |
b053a418 | 340 | \cd $(printf '../%.0s' {1..${1:-1}}) |
5b9a654a | 341 | } |
79d4a356 | 342 | alias u=up |
b053a418 | 343 | if [[ -v commands[zoxide] ]] { |
8a92a2c0 | 344 | # https://github.com/ajeetdsouza/zoxide/issues/513 |
345 | eval "${$(zoxide init zsh):s#_files -/#_cd#}" | |
6c74cef6 | 346 | alias cd=z |
692a75d3 | 347 | alias z-='z -' |
b053a418 | 348 | } |
0ca7cf36 | 349 | alias cd..=up |
4851c231 | 350 | ## dotfiles |
7ed1509a | 351 | alias dfu='function { |
352 | pushd -q ${$(echo -E - ~/.zshenv):P:h:h} | |
4ab73520 | 353 | git pull && |
354 | git submodule init && | |
355 | git submodule sync && | |
356 | git submodule update | |
7ed1509a | 357 | popd -q |
8ec56e91 | 358 | }' |
4ab73520 | 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' | |
5b9a654a | 367 | |
43016843 | 368 | ### hooks |
369 | autoload -Uz add-zsh-hook | |
5437a0d2 | 370 | typeset -gi _sev_exectime |
43016843 | 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 | |
1ef46e01 | 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 | } | |
43016843 | 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 | ||
43016843 | 400 | ### prompt |
401 | autoload -Uz promptinit && promptinit | |
402 | prompt arrows | |
403 | ||
d3e867c0 | 404 | ### plugins |
405 | load-plugins zshrc | |
406 | ||
8eb81f95 | 407 | ### load site-specific |
4ced48ed | 408 | load-site-dotfile zshrc |