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