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