My user config prefs
1# Filename : ~/.zshrc
2# Purpose : setup file for zsh
3# Author : Jeffrey Serio <hyperreal@moonshadow.dev>
4# Homepage : https://hyperreal.coffee
5#
6# Zsh Manual - https://zsh-manual.hyperreal.coffee
7# Zsh Guide - https://zsh-guide.hyperreal.coffee
8
9# Plugins
10if ! test -f "${HOME}/.zplug/init.zsh"; then
11 export ZPLUG_HOME="${HOME}/.zplug"
12 git clone https://github.com/zplug/zplug $ZPLUG_HOME
13fi
14
15source "${HOME}/.zplug/init.zsh"
16
17# Use autosuggestions when typing commands
18zplug "zsh-users/zsh-autosuggestions"
19
20# Use fast-syntax-highlighting
21zplug "zdharma-continuum/fast-syntax-highlighting"
22
23# Use syntax highlighting when typing commands
24#zplug "zsh-users/zsh-syntax-highlighting", defer:2
25
26# Press escape twice to prepend `sudo` to the command line
27zplug "plugins/sudo", from:oh-my-zsh
28
29# extract archives
30zplug "plugins/extract", from:oh-my-zsh
31
32# systemd aliases
33zplug "plugins/systemd", from:oh-my-zsh
34
35if ! zplug check; then
36 zplug install;
37 exec $SHELL "$SHELL_ARGS" "$@"
38fi
39
40zplug load
41
42### ENVIRONMENT VARS
43export PAGER="less -FRX"
44export MANWIDTH="88"
45export MANROFFOPT="-c"
46export MANPAGER="less -FRX"
47export BAT_PAGER="less -FRX"
48export BAT_STYLE="plain"
49export EDITOR="nvim"
50
51# Have less display colours
52# from: https://wiki.archlinux.org/index.php/Color_output_in_console#man
53export LESS_TERMCAP_mb=$'\e[1;31m' # begin bold
54export LESS_TERMCAP_md=$'\e[1;34m' # begin blink
55export LESS_TERMCAP_so=$'\e[01;0;33m' # begin reverse video
56export LESS_TERMCAP_us=$'\e[01;31m' # begin underline
57export LESS_TERMCAP_me=$'\e[0m' # reset bold/blink
58export LESS_TERMCAP_se=$'\e[0m' # reset reverse video
59export LESS_TERMCAP_ue=$'\e[0m' # reset underline
60export GROFF_NO_SGR=1 # for konsole and gnome-terminal
61
62# HISTSIZE is the number of lines of history that is kept within any given
63# running zsh instance. SAVEHIST is the number of lines of history that is
64# written out to the HISTFILE when that event occurs. If you use the
65# HIST_EXPIRE_DUPS_FIRST option, setting this value larger than the SAVEHIST
66# size will give you the difference as a cushion for saving duplicated history
67# events.
68HISTSIZE=100000
69SAVEHIST=65536
70
71# Name of the file used to store command history
72HISTFILE="${HOME}/.zsh_history"
73
74# Language
75export LANG="en_US.UTF-8"
76
77# Manpages
78export MANPATH="${MANPATH:-/usr/share/man:/usr/local/share/man}"
79
80# Set PATH
81export PATH="/bin:/sbin:/usr/local/bin"
82
83# Add ~/.local/bin to PATH
84export PATH="${HOME}/.local/bin:${PATH}"
85
86# Add ~/bin to PATH
87export PATH="${HOME}/bin:${PATH}"
88
89# Add ~/go/bin to PATH
90export PATH="${HOME}/go/bin:${PATH}"
91
92# Add ~/.cargo/bin to PATH
93if test -d "${HOME}/.cargo/bin"; then
94 export PATH="${HOME}/.cargo/bin:${PATH}"
95fi
96
97# Add homebrew to shell env if it exists
98test -d /home/linuxbrew/.linuxbrew && \
99 eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
100
101# Automatically remove duplicates from these arrays
102typeset -gU path cdpath manpath fpath
103
104# fzf
105source <(fzf --zsh)
106
107# starship.rs
108eval "$(starship init zsh)"
109
110# quickinfo
111/home/jas/bin/quickinfo || true
112
113### ALIASES
114
115# Change directory using xplr
116alias xcd='cd "$(xplr --print-pwd-as-result)"'
117
118if command -v batcat >/dev/null; then
119 alias bat='batcat'
120fi
121
122# The ls family
123if test -f /bin/lsd; then
124 alias ls='lsd'
125 alias la='lsd -a'
126 alias ll='lsd -l'
127 alias lal='lsd -al'
128else
129 alias ls='ls --color=auto'
130 alias la='ls -a'
131 alias ll='ls -l'
132 alias lal='ls -al'
133fi
134
135# grep
136alias grep='grep --color'
137
138# Prompt user before overwriting files
139alias cp='cp -i'
140alias mv='mv -i'
141alias rm='rm -i'
142
143# convert just recipes into aliases
144for recipe in $(just --justfile ~/.justfile --summary); do
145 alias $recipe="just --justfile ~/.justfile --working-directory . $recipe"
146done
147
148# Assorted global aliases
149if command -v bat >/dev/null; then
150 alias -g B='| bat'
151fi
152alias -g H='| head'
153alias -g T='| tail'
154alias -g G='| grep'
155alias -g L='| less -FRX'
156alias -g CC='| xclip -selection clipboard'
157
158# firewalld
159if test -x "$(command -v firewall-cmd)"; then
160 alias fw='sudo firewall-cmd'
161 alias fwp='sudo firewall-cmd --permanent'
162 alias fwr='sudo firewall-cmd --reload'
163 alias fwrp='sudo firewall-cmd --runtime-to-permanent'
164fi
165
166# git
167alias ga='git add'
168alias gcl='git clone'
169alias gcmsg='git commit -m'
170alias gd='git diff'
171alias gl='git pull'
172alias gp='git push'
173alias gr='git remote'
174alias grbi='git rebase -i'
175alias grm='git rm'
176alias grv='git remote -v'
177alias gst='git status'
178
179# todo.txt
180if test -x "$(command -v todo.sh)"; then
181 alias todo="todo.sh"
182fi
183
184### BINDINGS
185typeset -g -A key
186
187key[Home]="${terminfo[khome]}"
188key[End]="${terminfo[kend]}"
189
190[[ -n "${key[Home]}" ]] && bindkey -- "${key[Home]}" beginning-of-line
191[[ -n "${key[End]}" ]] && bindkey -- "${key[End]}" end-of-line
192
193if (( ${+terminfo[smkx]} && ${+terminfo[rmkx]} )); then
194 autoload -Uz add-zle-hook-widget
195 function zle_application_mode_start {
196 echoti smkx
197 }
198 function zle_application_mode_stop {
199 echoti rmkx
200 }
201 add-zle-hook-widget -Uz zle-line-init zle_application_mode_start
202 add-zle-hook-widget -Uz zle-line-finish zle_application_mode_stop
203fi
204
205## keybinding for convenient viewing of man pages
206if test -x "${HOME}/bin/split_man"; then
207 split-man-widget() {
208 "${HOME}/bin/split_man"
209 }
210 zle -N split-man-widget
211
212 bindkey '^[m' split-man-widget
213fi
214
215## keybind for convenient viewing of definitions
216if test -x "${HOME}/bin/split_dict"; then
217 split-dict-widget() {
218 "${HOME}/bin/split_dict"
219 }
220 zle -N split-dict-widget
221
222 bindkey '^[d' split-dict-widget
223fi
224
225## gumssh
226if test -x "$(command -v gumssh)"; then
227 bindkey -s '^[s' 'gumssh^M'
228fi
229
230## yazi
231if test -x "$(command -v yazi)"; then
232 bindkey -s '^[f' 'yazi^M'
233fi
234
235### FUNCTIONS
236
237# Command checker helper
238function check_cmd() {
239 test -x "$(command -v $1)"
240}
241
242## Nushell and jc functions
243
244# nushell: df
245function nudf() {
246 nu -c 'jc df | from json'
247}
248
249# nushell: free
250function numem() {
251 nu -c 'jc free | from json'
252}
253
254# nushell: lsof -i
255function netcons() {
256 nu -c 'jc lsof -i | from json'
257}
258
259# nushell: nutulp
260function tulp() {
261 nu -c 'jc ss -tulp | from json'
262}
263
264# nushell: openports
265function openports() {
266 nu -c 'sudo jc lsof -i | from json | find "LISTEN"'
267}
268
269# nushell: list sockets in use
270function lsock() {
271 nu -c 'sudo jc lsof -i -P | from json'
272}
273
274# nushell: ping
275function nuping() {
276 nu -c 'jc ping -c 3 $1 | from json'
277}
278
279# nushell: pong
280function pong() {
281 nu -c 'jc ping -c 3 www.google.com | from json'
282}
283
284# nushell: uptime
285function nuptime() {
286 nu -c 'jc uptime | from json'
287}
288
289# nushell: os-release
290function os-release() {
291 cat /etc/os-release | nu -c 'jc --os-release | from json'
292}
293
294# nushell: timestamp Z
295function nutsz() {
296 nu -c 'date now | format date "%FT%T%:z"'
297}
298
299# watch directory listing, update every 0.1s
300function watchdir() {
301 watch -n0,1 "ls -lh $1/ | tail"
302}
303
304# get time in timezone
305function timein() {
306 continent=$(find /usr/share/zoneinfo -maxdepth 1 -mindepth 1 -type d -not -name "posix" -not -name "right" -exec basename {} \; | gum choose --limit=1)
307 city=$(find "/usr/share/zoneinfo/$continent" -type f -exec basename {} \; | gum choose --limit=1)
308 TZ="$continent/$city" date
309}
310
311# Ansible playbook
312function ansplay() {
313 ansible-playbook -i inventory.yml "$@"
314}
315
316# Create a bookmark.
317function mark() {
318
319 if ! test -f "${HOME}/.shellmarks"; then
320 touch "${HOME}/.shellmarks"
321 fi
322
323 mark_to_add="$(pwd)"
324
325 if grep -qxFe "${mark_to_add}" "${HOME}/.shellmarks"; then
326 gum style \
327 --foreground 210 \
328 --margin "1 2" \
329 "This bookmark already exists: ${mark_to_add}"
330 else
331 echo "${mark_to_add}" >> "${HOME}/.shellmarks"
332 gum style \
333 --foreground "#73F59F" \
334 --margin "1 2" \
335 "${mark_to_add} added to shellmarks file"
336 fi
337
338 /bin/cat "${HOME}/.shellmarks" | sort | tee "${HOME}/.shellmarks" >/dev/null
339
340 return 0
341}
342
343# List bookmarks.
344function lsmarks() {
345 echo "# Shellmarks" | gum format
346
347 while IFS= read -r line; do
348 echo "- $line"
349 done < "${HOME}/.shellmarks" | gum format
350}
351
352# Remove bookmarks.
353function delmark() {
354 selection=$(cat "${HOME}/.shellmarks" | gum choose --no-limit)
355
356 if test -n "${selection}"; then
357 while read -r line; do
358 perl -n -i -e "print unless /^\\Q${line//\//\\/}\\E\$/" "${HOME}/.shellmarks"
359 done <<< "${selection}"
360 else
361 return 0
362 fi
363
364 gum format -t markdown -- \
365 "# The following bookmarks were deleted:" \
366 "$(printf "%s\n" "${selection}")"
367
368 return 0
369}
370
371# Goto a bookmark.
372function gotomark() {
373 if ! test -f "${HOME}/.shellmarks"; then
374 echo "No bookmarks exist yet. Add some!"
375 return 1
376 fi
377
378 echo
379 builtin cd "$(cat "${HOME}/.shellmarks" | gum choose --limit=1 --height=20)" || exit
380
381 local precmd
382 for precmd in $precmd_functions; do
383 $precmd
384 done
385 zle && zle reset-prompt
386}
387zle -N gotomark
388bindkey '^[g' gotomark
389
390# Choose a directory from the directory stack.
391function dstack() {
392 echo "# Choose a directory" | gum format -t markdown
393 selection=$(dirs -lp | gum choose --limit=1)
394 cd "$selection" || exit
395}
396
397# Print timestamp as %Y-%m-%d %H:%M:%S.
398function tstamp() {
399 emulate -L zsh
400 date '+%Y-%m-%d %H:%M:%S' | tr -d '\n'
401}
402
403# Print timestamp as %Y-%m-%dT%H:%M:%S%:z
404function tstampz() {
405 emulate -L zsh
406 date '+%Y-%m-%dT%H:%M:%S%:z' | tr -d '\n'
407}
408
409# Invoke this every time you change .zshrc to recompile it.
410function src() {
411 autoload -U zrecompile
412 [ -f ~/.zshrc ] && zrecompile -p ~/.zshrc
413 [ -f ~/.zcompdump ] && zrecompile -p ~/.zcompdump
414 [ -f ~/.zcompdump ] && zrecompile -p ~/.zcompdump
415 [ -f ~/.zshrc.zwc.old ] && command rm -f ~/.zshrc.zwc.old
416 [ -f ~/.zcompdump.zwc.old ] && command rm -f ~/.zcompdump.zwc.old
417 source ~/.zshrc
418}
419
420# Do an ls after cd.
421function cd() { builtin cd "$@" && ls; }
422
423# Create new directory and enter it.
424function mkd() { mkdir -p "$@" && cd "$_" || exit; }
425
426# Display pids of commands.
427function pids() { pgrep -a "$@"; }
428
429# Restart zsh.
430function restart() {
431 exec $SHELL $SHELL_ARGS "$@";
432}
433
434# cd to ~, clear screen, and restart zsh.
435function rsrc() {
436 cd && clear && restart;
437}
438
439### FZF
440
441# Everforest Hard colorscheme
442export FZF_DEFAULT_OPTS=" \
443--color=bg+:#2f383e,bg:#272E33,spinner:#DFA000,hl:#E67E80 \
444--color=fg:#D3C6AA,header:#E67E80,info:#E69875,pointer:#D699B6 \
445--color=marker:#7FBBB3,fg+:#D3C6AA,prompt:#35A77C,hl+:#E67E80 \
446--color=selected-bg:#414B50 \
447--color=border:#E67E80,label:#D3C6AA"
448
449## completion trigger
450export FZF_COMPLETION_TRIGGER="~~"
451
452## default source for fzf
453export FZF_DEFAULT_COMMAND="fd --type f --hidden --follow --exclude .git"
454
455# CTRL-R
456# CTRL-Y to copy the command into clipboard using wl-copy
457export FZF_CTRL_R_OPTS="
458 --bind 'ctrl-y:execute-silent(echo -n {2..} | wl-copy)+abort'
459 --color header:italic
460 --header 'Press CTRL-Y to copy command into clipboard'"
461
462
463### OPTIONS
464
465## General shell options
466# See https://zsh-manual.netlify.app/options
467
468# This is a multiple move based on zsh pattern matching (like "mmv").
469# Read ``less ${^fpath}/zmv(N)'' for more details.
470autoload zmv
471
472# A builtin that can clone a running shell onto another terminal.
473zmodload -e zsh/clone
474
475# When listing options (by 'setopt', 'unsetopt', 'set -o', or 'set +o'),
476# those turned on by default appear in the list prefixed with 'no'.
477# Hence (unless KSH_OPTION_PRINT is set), 'setopt' shows all options whose
478# settings are changed from default.
479#
480# Report the status of background jobs immediately, rather than waiting until
481# just before printing a prompt.
482setopt notify
483
484# Allow comments even in interactive shells.
485setopt interactivecomments
486
487# Send *not* a HUP signal to running jobs when the shell exits.
488setopt nohup
489
490# If a pattern for filename generation has no matches, delete the pattern from
491# the argument list instead of reporting an error.
492# Overrides NOMATCH
493setopt nullglob
494
495# Perform =filename access
496# $ setopt EQUALS
497# $ echo =ls
498# /bin/ls
499# $ unsetopt EQUALS
500# $ echo =ls
501# =ls
502# NOTE: It's not really needed because zsh sets the per default.
503setopt equals
504
505# Try to make completion list smaller by printing the matches in columns with
506# different widths.
507setopt list_packed
508
509# Expands single letters and ranges of letters between braces
510# $ print 1{abw-z}2
511# $ 1a2 1b2 1w2 1y2 1z2
512setopt braceccl
513
514# If the argument to a cd command (or an implied cd with the AUTO_CD option
515# set) is not a directory, and does not begin with a slash, try to expand the
516# expression as if it were preceded by a '~' (See section 14.7 Filename
517# Expansion).
518setopt cdablevars
519
520# Report the status of background and suspended jobs before exiting a shell
521# with job control; a second attempt to exit the shell will succeed.
522setopt checkjobs
523
524# Make cd push the old directory onto the directory stack.
525setopt autopushd
526
527# Change to directory without cd
528setopt autocd
529
530# Query the user before executing 'rm *' or 'rm path/*'
531setopt normstarsilent
532setopt no_rm_star_wait
533
534# Shaddapa you face
535setopt nobeep
536
537# When writing out the history file, older commands that duplicate newer ones
538# are omitted.
539set histsavenodups
540
541# When searching for history entries in the line editor, do not display
542# duplicates of a line previously found, even if the duplicates are not
543# contiguous.
544setopt histfindnodups
545
546# If the internal history needs to be trimmed to add the current command line,
547# setting this option will cause the oldest history event that has a duplicate
548# to be lost before losing a unique event from the list.
549setopt hist_expire_dups_first
550
551# If a new command line being added to the history list duplicates an older
552# one, the older command is removed from the list (even if it is not the
553# previous event).
554setopt hist_ignore_all_dups
555
556# Do not enter command lines into the history list if they are duplicates of
557# the previous event.
558setopt hist_ignore_dups
559
560# Remove superfluous blanks from each command line being added to history.
561setopt hist_reduce_blanks
562
563# Whenever the user enters a line with history expansion, don't execute the
564# line directly; instead, perform history expansion and reload the line into
565# the editing buffer.
566setopt hist_verify
567
568# Do not remove function definitions from the history list.
569unsetopt hist_no_functions
570
571# Remove the history (fc -l) command from the history list when invoked.
572# Note that the command lingers in the internal history until the next command
573# is entered before it vanishes, allowing you to briefly reuse or edit the
574# line.
575setopt hist_no_store
576
577# If this is set, zsh sessions will append their history list to the history
578# file, rather than overwrite it. Thus, multiple parallel zsh sessions will all
579# have their history lists added to the history file, in the order they are
580# killed.
581setopt appendhistory
582
583# If unset, the cursor is set to the end of the word if completion is started.
584# Otherwise, it stays there and completion is done from both ends.
585unsetopt completeinword
586
587# When listing files that are possible completions, show the type of each file
588# with a trailing identifying mark.
589setopt listtypes
590
591# Do not require a leading '.' in a filename to be matched explicitly.
592setopt globdots
593
594# List jobs in long format by default
595setopt longlistjobs
596
597# Don't push multiple copies of the same directory onto the directory staack.
598setopt pushdignoredups
599
600# This option both imports new commands from the history file, and also causes
601# your typed commands to be appended to the history file (the latter is like
602# specifying INC_APPEND_HISTORY).
603# The history lines are also output with timestamps ala EXTENDED_HISTORY
604# (which makes it easier to find the spot where we left off reading the file
605# after it gets re-written).
606setopt sharehistory
607
608# Save each command's beginning timestamp (in seconds since the epoch)
609# and the duration (in seconds) to the history file. The format of this
610# prefixed data is:
611# ':<beginning time>:<elapsed seconds>;<command>'
612setopt extendedhistory
613
614# Do *not* run all background jobs at a lower nice priority
615unsetopt bgnice
616