]>
Commit | Line | Data |
---|---|---|
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 : |