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