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