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