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