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