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