dotfiles

My personal shell configs and stuff
git clone git://git.alex.balgavy.eu/dotfiles.git
Log | Files | Refs | Submodules | README | LICENSE

zshrc (23625B)


      1 # -*- mode: shell-script; -*-
      2 # vim: foldmethod=marker foldlevel=0
      3 # zmodload zsh/zprof
      4 export DOTFILES="$HOME/.dotfiles"
      5 [ -f "$DOTFILES/shell/secret_env" ] && . "$DOTFILES/shell/secret_env"
      6 
      7 if [ -n "$VIM_TERMINAL" ]; then EDITOR=vimsend
      8 elif [ -n "$INSIDE_EMACS" ]; then EDITOR=emacsclient
      9 elif command -v nvim >/dev/null 2>&1; then EDITOR="$(command -v nvim)"
     10 else EDITOR="$(command -v vim)"; fi
     11 export EDITOR
     12 
     13 export CHOOSER=fzfchoose
     14 export MUSIC_DIR="/Volumes/HDD/Music/Libraries/Mine"
     15 export PAGER="less"
     16 export LESS="-RicX"
     17 
     18 export LANG="en_US.UTF-8"
     19 export LC_ALL="en_US.UTF-8"
     20 export LC_COLLATE="en_US.UTF-8"
     21 export LC_CTYPE="en_US.UTF-8"
     22 export LC_MESSAGES="en_US.UTF-8"
     23 export LC_MONETARY="en_US.UTF-8"
     24 export LC_NUMERIC="en_US.UTF-8"
     25 export LC_TIME="en_US.UTF-8"
     26 
     27 [ -z "$DISPLAY" ] && export DISPLAY=":0"
     28 
     29 export TTRV_BROWSER=~/.scripts/linkhandler
     30 if command -v brave >/dev/null 2>&1; then
     31   export BROWSER=brave
     32 else
     33   export BROWSER="open"
     34 fi
     35 
     36 export WWW_HOME="https://tab.alex.balgavy.eu"
     37 # Icons for lf {{{1
     38 export LF_ICONS="\
     39 bd=:\
     40 cd=:\
     41 di=:\
     42 st=:\
     43 tw=:\
     44 ow=:\
     45 pi=ﳣ:\
     46 fi=:\
     47 sg=:\
     48 su=:\
     49 so=杻:\
     50 ln=:\
     51 or=:\
     52 ex=:\
     53 *.vimrc=:\
     54 *.viminfo=:\
     55 *.gitignore=:\
     56 *.c=:\
     57 *.cc=:\
     58 *.clj=:\
     59 *.coffee=:\
     60 *.cpp=:\
     61 *.css=:\
     62 *.d=:\
     63 *.dart=:\
     64 *.erl=:\
     65 *.exs=:\
     66 *.fs=:\
     67 *.go=:\
     68 *.h=:\
     69 *.hh=:\
     70 *.hpp=:\
     71 *.hs=:\
     72 *.html=:\
     73 *.java=:\
     74 *.jl=:\
     75 *.js=:\
     76 *.json=:\
     77 *.lua=:\
     78 *.md=:\
     79 *.php=:\
     80 *.pl=:\
     81 *.pro=:\
     82 *.py=:\
     83 *.rb=:\
     84 *.rs=:\
     85 *.scala=:\
     86 *.ts=:\
     87 *.vim=:\
     88 *.cmd=:\
     89 *.ps1=:\
     90 *.sh=:\
     91 *.bash=:\
     92 *.zsh=:\
     93 *.fish=:\
     94 *.tar=:\
     95 *.tgz=:\
     96 *.arc=:\
     97 *.arj=:\
     98 *.taz=:\
     99 *.lha=:\
    100 *.lz4=:\
    101 *.lzh=:\
    102 *.lzma=:\
    103 *.tlz=:\
    104 *.txz=:\
    105 *.tzo=:\
    106 *.t7z=:\
    107 *.zip=:\
    108 *.z=:\
    109 *.dz=:\
    110 *.gz=:\
    111 *.lrz=:\
    112 *.lz=:\
    113 *.lzo=:\
    114 *.xz=:\
    115 *.zst=:\
    116 *.tzst=:\
    117 *.bz2=:\
    118 *.bz=:\
    119 *.tbz=:\
    120 *.tbz2=:\
    121 *.tz=:\
    122 *.deb=:\
    123 *.rpm=:\
    124 *.jar=:\
    125 *.war=:\
    126 *.ear=:\
    127 *.sar=:\
    128 *.rar=:\
    129 *.alz=:\
    130 *.ace=:\
    131 *.zoo=:\
    132 *.cpio=:\
    133 *.7z=:\
    134 *.rz=:\
    135 *.cab=:\
    136 *.wim=:\
    137 *.swm=:\
    138 *.dwm=:\
    139 *.esd=:\
    140 *.jpg=:\
    141 *.jpeg=:\
    142 *.mjpg=:\
    143 *.mjpeg=:\
    144 *.gif=:\
    145 *.bmp=:\
    146 *.pbm=:\
    147 *.pgm=:\
    148 *.ppm=:\
    149 *.tga=:\
    150 *.xbm=:\
    151 *.xpm=:\
    152 *.tif=:\
    153 *.tiff=:\
    154 *.png=:\
    155 *.svg=:\
    156 *.svgz=:\
    157 *.mng=:\
    158 *.pcx=:\
    159 *.mov=:\
    160 *.mpg=:\
    161 *.mpeg=:\
    162 *.m2v=:\
    163 *.mkv=:\
    164 *.webm=:\
    165 *.ogm=:\
    166 *.mp4=:\
    167 *.m4v=:\
    168 *.mp4v=:\
    169 *.vob=:\
    170 *.qt=:\
    171 *.nuv=:\
    172 *.wmv=:\
    173 *.asf=:\
    174 *.rm=:\
    175 *.rmvb=:\
    176 *.flc=:\
    177 *.avi=:\
    178 *.fli=:\
    179 *.flv=:\
    180 *.gl=:\
    181 *.dl=:\
    182 *.xcf=:\
    183 *.xwd=:\
    184 *.yuv=:\
    185 *.cgm=:\
    186 *.emf=:\
    187 *.ogv=:\
    188 *.ogx=:\
    189 *.aac=:\
    190 *.au=:\
    191 *.flac=:\
    192 *.m4a=:\
    193 *.mid=:\
    194 *.midi=:\
    195 *.mka=:\
    196 *.mp3=:\
    197 *.mpc=:\
    198 *.ogg=:\
    199 *.ra=:\
    200 *.wav=:\
    201 *.oga=:\
    202 *.opus=:\
    203 *.spx=:\
    204 *.xspf=:\
    205 *.pdf=:\
    206 *.nix=:\
    207 "
    208 # Force use of XDG Base Directory {{{1
    209 export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
    210 [ -d "$XDG_CONFIG_HOME" ] || mkdir -p "$XDG_CONFIG_HOME"
    211 export XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
    212 [ -d "$XDG_DATA_HOME" ] || mkdir -p "$XDG_DATA_HOME"
    213 export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
    214 [ -d "$XDG_CACHE_HOME" ] || mkdir -p "$XDG_CACHE_HOME"
    215 export XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
    216 [ -d "$XDG_STATE_HOME" ] || mkdir -p "$XDG_STATE_HOME"
    217 
    218 # Other env {{{1
    219 export GOPATH="$XDG_DATA_HOME"/go
    220 export JUPYTER_CONFIG_DIR="$XDG_CONFIG_HOME/jupyter"
    221 export BUNDLE_USER_HOME="$XDG_CONFIG_HOME/bundle"
    222 export BUNDLE_USER_CACHE="$XDG_CACHE_HOME/bundle"
    223 export _Z_DATA="$XDG_CACHE_HOME/z/z-data"
    224 export HTTPIE_CONFIG_DIR="$XDG_CONFIG_HOME/httpie"
    225 export CABAL_DIR="$XDG_CONFIG_HOME/cabal"
    226 export GHCUP_INSTALL_BASE_PREFIX="$XDG_CONFIG_HOME"
    227 export ZDOTDIR="$XDG_CONFIG_HOME/zsh"
    228 # export GEM_SPEC_CACHE="$XDG_CACHE_HOME/gem"
    229 export NOTMUCH_CONFIG="$XDG_CONFIG_HOME/notmuch/config"
    230 export GNUPGHOME="$XDG_CONFIG_HOME/gnupg"
    231 export R_PROFILE_USER="$XDG_CONFIG_HOME/R/Rprofile"
    232 export MAILCAPS="$XDG_CONFIG_HOME/mailcap"
    233 eval "$(perl -I$XDG_DATA_HOME/perl5/lib/perl5 -Mlocal::lib=$XDG_DATA_HOME/perl5)"
    234 alias glow='glow --config "$XDG_CONFIG_HOME/glow/glow.yml"'
    235 export RUSTUP_HOME="$XDG_DATA_HOME/rustup"
    236 export CARGO_HOME="$XDG_DATA_HOME/cargo"
    237 export RBENV_ROOT="$XDG_DATA_HOME/rbenv"
    238 export ANDROID_HOME="$XDG_DATA_HOME/android"
    239 export DOCKER_CONFIG="$XDG_CONFIG_HOME/docker"
    240 export ELECTRUMDIR="$XDG_DATA_HOME/electrum"
    241 alias gdb='gdb -n -x $XDG_CONFIG_HOME/gdb/init'
    242 export GDBHISTFILE="$XDG_CONFIG_HOME"/gdb/.gdb_history
    243 export SCREENRC="$XDG_CONFIG_HOME"/screen/screenrc
    244 export IPYTHONDIR="${XDG_CONFIG_HOME}/ipython"
    245 export LESSHISTFILE="$XDG_CACHE_HOME"/less/history
    246 export STACK_ROOT="$XDG_DATA_HOME"/stack
    247 export VAGRANT_HOME="$XDG_DATA_HOME"/vagrant
    248 export RIPGREP_CONFIG_PATH="$XDG_CONFIG_HOME/ripgrep/config"
    249 export ZDOTDIR=$HOME/.config/zsh
    250 export HISTFILE=$ZDOTDIR/.zsh_history
    251 export GEM_HOME=$XDG_DATA_HOME/.gems
    252 export CARGO_TARGET_DIR=$XDG_CACHE_HOME/cargo/target/
    253 # }}}
    254 
    255 # Paths {{{1
    256 [ -x /usr/libexec/path_helper ] && unset PATH && eval "$(/usr/libexec/path_helper -s)"
    257 
    258 [ -d "$HOME/.local/bin" ] || [ -L "$HOME/.local/bin" ]                           && [ -n "${PATH##*"$HOME/.local/bin"*}" ]                  && PATH="$HOME/.local/bin:$PATH"
    259 [ -d "$GOPATH/bin" ] || [ -L "$GOPATH/bin" ]                                     && [ -n "${PATH##*"$GOPATH/bin"*}" ]                       && PATH="$GOPATH/bin:$PATH"
    260 [ -d "/usr/local/opt/util-linux/bin" ] || [ -L "/usr/local/opt/util-linux/bin" ] && [ -n "${PATH##*"/usr/local/opt/util-linux/bin"*}" ]     && PATH="/usr/local/opt/util-linux/bin:$PATH"
    261 [ -d "$XDG_CONFIG_HOME/.ghcup/bin" ] || [ -L "$XDG_CONFIG_HOME/.ghcup/bin" ]     && [ -n "${PATH##*"$XDG_CONFIG_HOME/.ghcup/bin"*}" ]       && PATH="$XDG_CONFIG_HOME/.ghcup/bin:$PATH"
    262 [ -d "/usr/local/sbin" ] || [ -L "/usr/local/sbin" ]                             && [ -n "${PATH##*"/usr/local/sbin"*}" ]                   && PATH="/usr/local/sbin:$PATH"
    263 [ -d "$HOME/.local/gnat/bin" ] || [ -L "$HOME/.local/gnat/bin" ]                 && [ -n "${PATH##*"$HOME/.local/gnat/bin"*}" ]             && PATH="$HOME/.local/gnat/bin:$PATH"
    264 [ -d "$HOME/bin" ] || [ -L "$HOME/bin" ]                                         && [ -n "${PATH##*"$HOME/bin"*}" ]                         && PATH="$HOME/bin:$PATH"
    265 [ -d "$HOME/.bin" ] || [ -L "$HOME/.bin" ]                                       && [ -n "${PATH##*"$HOME/.bin"*}" ]                        && PATH="$HOME/.bin:$PATH"
    266 [ -d "$DOTFILES/scripts" ] || [ -L "$DOTFILES/scripts" ]                               && [ -n "${PATH##*"$DOTFILES/scripts"*}" ]                    && PATH="$DOTFILES/scripts:$PATH"
    267 [ -d "$XDG_DATA_HOME/gem/bin" ] || [ -L "$XDG_DATA_HOME/gem/bin" ]               && [ -n "${PATH##*"$XDG_DATA_HOME/gem/bin"*}" ]            && PATH="$XDG_DATA_HOME/gem/bin:$PATH"
    268 [ -d "$HOME/.elan/bin" ]                                                         && [ -n "${PATH##*"$HOME/.elan/bin"*}" ]                   && PATH="$HOME/.elan/bin:$PATH"
    269 [ -d /usr/local/opt/man-db/libexec/bin ]                                         && [ -n "${PATH##*"/usr/local/opt/man-db/libexec/bin"*}" ] && PATH="/usr/local/opt/man-db/libexec/bin:$PATH"
    270 [ -d "$DOTFILES/tools/shfm" ]                                                    && [ -n "${PATH##*"$DOTFILES/tools/shfm"*}" ]              && PATH="$DOTFILES/tools/shfm:$PATH"
    271 [ -d "$DOTFILES/tools/pfetch" ]                                                  && [ -n "${PATH##*"$DOTFILES/tools/pfetch"*}" ]            && PATH="$DOTFILES/tools/pfetch:$PATH"
    272 [ -d "$DOTFILES/tools/tuxi" ]                                                    && [ -n "${PATH##*"$DOTFILES/tools/tuxi"*}" ]              && PATH="$DOTFILES/tools/tuxi:$PATH"
    273 [ -d "$DOTFILES/tools/speedread" ]                                               && [ -n "${PATH##*"$DOTFILES/tools/speedread"*}" ]         && PATH="$DOTFILES/tools/speedread:$PATH"
    274 [ -d "$DOTFILES/tools/fzf/bin" ]                                                 && [ -n "${PATH##*"$DOTFILES/tools/fzf/bin"*}" ]           && PATH="$DOTFILES/tools/fzf/bin:$PATH"
    275 [ -d "$DOTFILES/tools/solvitaire" ]                                              && [ -n "${PATH##*"$DOTFILES/tools/solvitaire"*}" ]        && PATH="$DOTFILES/tools/solvitaire:$PATH"
    276 [ -d "$XDG_DATA_HOME/perl5/bin" ]                                                && [ -n "${PATH##*"$XDG_DATA_HOME/perl5/bin"*}" ]          && PATH="$XDG_DATA_HOME/perl5/bin:$PATH"
    277 [ -d "$HOME/.jenv/bin" ]                                                         && [ -n "${PATH##*"$HOME/.jenv/bin"*}" ]                   && PATH="$HOME/.jenv/bin:$PATH"
    278 [ -d "$XDG_DATA_HOME/cargo/bin" ]                                                && [ -n "${PATH##*"$XDG_DATA_HOME/cargo/bin"*}" ]          && PATH="$XDG_DATA_HOME/cargo/bin:$PATH"
    279 [ -d "/usr/local/go/bin" ] || [ -L "/usr/local/go/bin" ]                         && [ -n "${PATH##*"/usr/local/go/bin"*}" ]                 && PATH="/usr/local/go/bin:$PATH"
    280 [ -d "/usr/local/opt/ruby/bin" ] || [ -L "/usr/local/opt/ruby/bin" ]             && [ -n "${PATH##*"/usr/local/opt/ruby/bin"*}" ]           && PATH="/usr/local/opt/ruby/bin:$PATH"
    281 [ -d "/usr/local/opt/sqlite" ]                                                   && [ -n "${PATH##*"/usr/local/opt/sqlite/bin"*}" ]         && PATH="/usr/local/opt/sqlite/bin:$PATH"
    282 [ -d "$HOME/.rvm/bin" ]                                                   && [ -n "${PATH##*"$HOME/.rvm/bin"*}" ]         && PATH="$HOME/.rvm/bin:$PATH"
    283 [ -d "$GEM_HOME/bin" ]                                                   && [ -n "${PATH##*"$GEM_HOME/bin"*}" ]         && PATH="$GEM_HOME/bin:$PATH"
    284 [ -d "/run/current-system/sw/bin" ]                                                   && [ -n "${PATH##*"/run/current-system/sw/bin "*}" ]         && PATH="/run/current-system/sw/bin:$PATH"
    285 
    286 export PATH
    287 # }}}
    288 
    289 # ZSH-specific inits
    290 if command -v startx >/dev/null 2>&1 && [ "$(tty)" = "/dev/tty1" ]; then
    291   pgrep dwm || startx
    292 fi
    293 [ -n "$DOTFILES" ] || { printf '$DOTFILES not set, press enter to quit' && read -r && exit 1; }
    294 
    295 (cat ~/.cache/wal/sequences &)
    296 . ~/.cache/wal/colors-tty.sh
    297 
    298 # Enable custom aliases and functions
    299 alias irssi='irssi --config="$XDG_CONFIG_HOME"/irssi/config --home="$XDG_CONFIG_HOME"/irssi'
    300 alias tmux='tmux -f $XDG_CONFIG_HOME/tmux/tmux.conf'
    301 alias w3m='w3m -config $XDG_CONFIG_HOME/w3m/config -bookmark $XDG_CONFIG_HOME/w3m/bookmark.html'
    302 alias monero-wallet-cli='monero-wallet-cli --config-file ~/.config/bitmonero/monero-wallet-cli.conf'
    303 alias docker='sudo -E docker'
    304 alias fucking="sudo"                                                            # Because sometimes I'm frustrated
    305 alias cp='cp -ivR'                                                              # Prompt if overwrite, verbose
    306 alias grep='grep --color=auto'
    307 alias mv='mv -iv'                                                               # Prompt if overwrite, verbose
    308 alias lynx='lynx -vikeys'
    309 alias mkdir='mkdir -pv'                                                         # Create intermediate dirs, verbose
    310 alias ls="command ls -lh"                                                       # List in long format, human-readable sizes
    311 alias l="command ls -lah"                                                       # Ls but with all files
    312 alias ll="command ls -FGlAhpO@"                                                 # Ls but show everything you can
    313 alias l.="command ls -a | grep '^\.'"                                           # Ls but only dotfiles
    314 alias less='less -RicX'                                                         # Search ig case, fix ANSI colors, don't send init strings, clear screen
    315 alias du="du -sh"                                                              # Show entry for each file, human-readable sizes
    316 alias df="df -h"                                                                # Show human-readable sizes
    317 alias bc="bc -ql"                                                               # Don't print welcome message, use the standard math lib
    318 alias jobs="jobs -l"                                                            # Show everything including PIDs
    319 alias g='git'                                                                   # Make git easier to type
    320 alias wheredef='type -a'                                                        # Where is a function defined?
    321 alias j='joplin'
    322 alias tree="tree -CAFa -I 'CVS|*.*.package|.svn|.git|node_modules' --dirsfirst" # Colorize, ANSI graphics hack, indicate ft with appendices, print all files, ignore certain patterns, list dirs first
    323 alias lsblk="lsblk -o NAME,LABEL,PARTLABEL,TYPE,FSTYPE,SIZE,MOUNTPOINT,STATE"   # The columns I want to see in lsblk
    324 alias confucius="curl confucius-quote.herokuapp.com"                            # A joke curl service I made
    325 alias tx="tmuxinator"
    326 alias mpva="mpv --no-audio-display --no-video --volume=50"
    327 alias irrsi="irssi --home=~/.config/irssi"
    328 # alias irssi="ssh -t vps 'screen -r irssi'"
    329 alias scim="sc-im"
    330 alias mbsync='mbsync -c $HOME/.config/mbsync/mbsyncrc'
    331 alias mutt="neomutt"
    332 alias gotop='sudo gotop -C $XDG_CONFIG_HOME/gotop/gotop.conf'
    333 alias vim=nvim
    334 [ -n "$VIM_TERMINAL" ] && alias vim=vimsend
    335 [ -f "$DOTFILES"/docs/pbib/README.md ] && alias pbib='vim +$(nl -b a '$DOTFILES"/docs/pbib/README.md | fzf --with-nth 2.. -e -q '^# ' | sed 's/[^0-9]//g') "$DOTFILES"/docs/pbib/README.md"
    336 command -v scrcpy >/dev/null 2>&1 && alias scrcpy='scrcpy --no-audio --shortcut-mod=ralt -b2M -S'
    337 command -v lazydocker >/dev/null 2>&1 && alias lzd=lazydocker
    338 cd() { builtin cd -P "$@" || return; }                                  # list contents after cding
    339 mkcd() { mkdir -p -- "$1" && cd -P -- "$1" || return; }                 # make dir and cd at the same time
    340 procinfo() { pgrep -f "$1"; }                                           # get info about a process (by name)
    341 rmempty() { find "${1-.}"  -type d -empty -depth -delete; }             # remove empty directories
    342 hr() { : $((i=0)); while [ $((i<$(tput cols))) -ne 0 ]; do printf "#"; _=$((i=i+1)); done; echo; }  # insert a <hr> in the terminal
    343 history() { builtin fc $@ -l 1 -1; }
    344 vimq() { vim -q <(eval "$(fc -nl -1 | sed 's/^rg\b/rgv/')"); }                                  # load results of last command (often ag) in vim quickfix. eval necessary to handle escaped quotes.
    345 nls() { printf $((`ls -l | wc -l | xargs echo` - 1)); }                        # Count the number of files in the directory
    346 reload-completions() { rm $ZDOTDIR/.zcompdump && compinit; }
    347 reload() {
    348   local START_TIME=$SECONDS
    349   if [[ $SHELL = *"zsh"* ]]; then
    350     source "$HOME"/.zshrc
    351   elif [[ $SHELL = *"bash"* ]]; then
    352     source "$HOME"/.bash_profile
    353   fi
    354   echo "Reloaded config ($(( SECONDS-START_TIME )) sec)."
    355 }
    356 extract () {
    357   if [ -f "$1" ] ; then
    358     case $1 in
    359       *.tar.bz2)   tar xjf "$1"     ;;
    360       *.tar.gz)    tar xzf "$1"     ;;
    361       *.bz2)       bunzip2 "$1"     ;;
    362       *.rar)       unrar e "$1"     ;;
    363       *.gz)        gunzip "$1"      ;;
    364       *.tar)       tar xf "$1"      ;;
    365       *.tbz2)      tar xjf "$1"     ;;
    366       *.tgz)       tar xzf "$1"     ;;
    367       *.zip)       unzip "$1"       ;;
    368       *.Z)         uncompress "$1"  ;;
    369       *.7z)        7z x "$1"        ;;
    370       *)     echo "'$1' cannot be extracted via extract()" ;;
    371     esac
    372   else
    373     echo "'$1' is not a valid file"
    374   fi
    375 }
    376 
    377 # Docker functions
    378 if command -v docker &>/dev/null; then
    379   eslint_here() {
    380     docker run -it --rm -v $(pwd):/data cytopia/eslint . -f unix;
    381   }
    382 fi
    383 
    384 # Applescript-reliant functions
    385 if command -v osascript &> /dev/null; then
    386   # cd to current Finder directory
    387   cdf() {
    388     target="$(osascript -e 'tell application "Finder" to if (count of Finder windows) > 0 then get POSIX path of (target of front Finder window as text)')"
    389     if [ -n "$target" ]; then
    390       cd "$target" || printf "Could not cd to %s.\n" >&2
    391       pwd
    392     else
    393       printf 'No Finder window found.\n' >&2
    394     fi
    395   }
    396 
    397   # echo current Finder directory
    398   gdf() {
    399     osascript -e 'tell application "Finder" to if (count of Finder windows) > 0 then get POSIX path of (target of front Finder window as text)'
    400   }
    401   # echo selected Finder file
    402   gsf() {
    403     osascript -e 'tell application "Finder" to return POSIX path of (first item of (get selection as alias list) as alias)' | rev | sed 's/^\///' | rev;
    404   }
    405 fi
    406 
    407 if command -v qlmanage &> /dev/null; then
    408   qlf() { qlmanage -p "$@" &> /dev/null; }
    409 fi
    410 
    411 # fzf-reliant functions
    412 if command -v fzf >/dev/null 2>&1; then
    413   { [ -f ~/.config/dark-theme ] && export BAT_THEME='1337'; } || export BAT_THEME='GitHub'
    414   export FZF_DEFAULT_OPTS="--preview-window right:100:hidden:wrap --bind '?:toggle-preview' --preview='(bat --style=numbers --theme=$BAT_THEME --color=always {} || cat {}) 2>/dev/null | head -500'"
    415   export FZF_DEFAULT_COMMAND="rg -l -H \"\""
    416   # script edit
    417   se() {
    418     local files
    419     IFS=$'\n' files=($(command find "$DOTFILES/scripts" -type f -or -type l -not -ipath "*/.git/*" | fzf -m --inline-info --prompt="edit> " --height=40 --reverse))
    420     [[ -n "$files" ]] && ${EDITOR:-vim} "${files[@]}"
    421   }
    422   # script create
    423   sc() {
    424     [ -z "$1" ] && echo "Filename must be passed as an argument." && return 1
    425     vim $DOTFILES/scripts/"$1" && chmod +x $DOTFILES/scripts/"$1"
    426   }
    427 
    428   # script find
    429   sf() {
    430     local f
    431     IFS=$'\n' f=($(command find "$DOTFILES"/scripts -type f -not -ipath "*/.git/*" | fzf +m --prompt="find> " --height=40 --reverse --cycle))
    432     [[ -n "$f" ]] && printf "$f"
    433   }
    434 
    435   # config edit
    436   ce() {
    437     local files
    438     IFS=$'\n' files=($(command find "$DOTFILES" -type f ! -ipath "*/scripts/*" ! -ipath "*/.git/*" ! -ipath "*/bin/*" ! -ipath "*/oh-my-zsh/*" ! -name ".DS_Store" | fzf -m --inline-info --prompt="edit> " --height=40 --reverse))
    439     [[ -n "$files" ]] && ${EDITOR:-vim} "${files[@]}"
    440   }
    441 
    442   # config find
    443   cf() {
    444     local f
    445     IFS=$'\n' f=($(command find "$DOTFILES" -type f ! -ipath "*/.git/*" ! -ipath "*/bin/*" ! -ipath "*/oh-my-zsh/*" ! -name ".DS_Store" | fzf +m --prompt="find> " --height=40 --reverse --cycle))
    446     [[ -n "$f" ]] && printf "$f"
    447   }
    448 
    449   # vim setting edit
    450   ve() {
    451     local files
    452     IFS=$'\n' files=($(command find ~/.dotfiles/vim -type f -not -ipath "*/.git/*" | fzf -m --inline-info --prompt="edit (vim)> " --height=40 --reverse))
    453     [[ -n "$files" ]] && ${EDITOR:-vim} "${files[@]}"
    454   }
    455   # run python
    456   rp() {
    457     fzf --print-query --preview-window=right:50% --preview 'python -c {q}' <<<''
    458   }
    459   # Run ruby
    460   rr() {
    461     fzf --print-query --preview-window=right:50% --preview 'ruby -e {q}' <<<''
    462   }
    463   # run bash
    464   rb() {
    465     fzf --print-query --preview-window=right:50% --preview 'bash -c {q}' <<<''
    466   }
    467   # run json
    468   rj() {
    469     fzf --preview "cat $1 | jq {q}"
    470   }
    471 
    472   # list man pages
    473   mans() {
    474     sec="${1:-1|4}"
    475     # (sorry, couldn't be arsed to deal with escaping parentheses for variable passing in awk)
    476     manlist=$(man -k . 2>/dev/null | awk "$(printf 'BEGIN {FS=OFS="- "} /\([%s]\)/ {gsub(/\([0-9]\)/, "", $1); if (!seen[$0]++) { print }}' "$sec")" | fzf) \
    477       && man "$(echo "$manlist" | awk -F' |,' '{print $1}')" \
    478       && unset manlist
    479   }
    480 
    481   # list env variables
    482   envs() {
    483     var=$(printenv | cut -d= -f1 | fzf) \
    484       && echo "$var=$(printenv "$var")" \
    485       && unset var
    486   }
    487 fi
    488 
    489 if command -v rg >/dev/null 2>&1; then
    490   alias rgv='rg --vimgrep'
    491 fi
    492 # lf-reliant functions
    493 if command -v lf >/dev/null 2>&1; then
    494   lfcd() {
    495     tmp="$(mktemp)"
    496     lf -last-dir-path="$tmp" "$@"
    497     if [ -f "$tmp" ]; then
    498       dir="$(cat "$tmp")"
    499       rm "$tmp"
    500       [ -d "$dir" ] && [ "$dir" != "$(pwd)" ] && cd "$dir" || return
    501     fi
    502   }
    503 fi
    504 
    505 # Options
    506 if [ -n "$VIMRUNTIME" ]; then set -o vi
    507 else set -o emacs; fi
    508 
    509 setopt alwaystoend         # On completion, move cursor to end of word
    510 setopt autocd              # If I forget 'cd' before a path
    511 setopt autopushd           # Make cd push old directory onto stack
    512 setopt completeinword      # Completion from both ends of word
    513 setopt interactivecomments # Allow comments
    514 setopt monitor             # Allow job control
    515 setopt nocaseglob          # Globs should be case insensitive
    516 setopt noflowcontrol       # Disable ^S and ^Q
    517 setopt promptsubst         # Parameter expansion, command subst, arithmetic expansion done in prompt
    518 setopt pushdignoredups     # Don't pushd duplicate directories
    519 setopt pushdminus          # Exchange meanings of + and - on directory stack
    520 
    521 # History options
    522 ## History file configuration
    523 HISTSIZE=100000
    524 SAVEHIST=100000
    525 setopt extendedhistory     # Save timestamp and duration of commands in histfile
    526 setopt sharehistory        # Import commands from histfile and append typed to histfile
    527 setopt appendhistory       # Append to history
    528 setopt incappendhistory    # Append immediately, not at shell exit
    529 setopt histignoredups      # Don't save command into history if duplicate of previous
    530 setopt histignorespace     # Don't save command into history if starts with space
    531 setopt histfindnodups      # Ignore duplicates when searching
    532 setopt histreduceblanks    # Remove blank lines from history
    533 setopt histverify          # Show expansion first before executing
    534 setopt histexpiredupsfirst # Expire duplicates first when trimming
    535 
    536 # Enable extra completions
    537 # fpath=($DOTFILES/shell/zsh-completions/src $DOTFILES/shell/osx-zsh-completions/ $DOTFILES/shell/zsh-completions-mine/ $fpath)
    538 # fpath=($DOTFILES/shell/zsh-completions-mine/ $fpath)
    539 # Smarter completion initialization
    540 autoload -Uz compinit
    541 if [ "$(date +'%j')" != "$(stat -f '%Sm' -t '%j' $ZDOTDIR/.zcompdump 2>/dev/null)" ]; then
    542     compinit
    543 else
    544     compinit -C
    545 fi
    546 . $DOTFILES/shell/oh-my-zsh-defaults/completion.zsh
    547 . $DOTFILES/shell/oh-my-zsh-defaults/directories.zsh
    548 . $DOTFILES/shell/oh-my-zsh-defaults/keys.zsh
    549 
    550 # Allow pasting bare URLs
    551 autoload -Uz url-quote-magic
    552 zle -N self-insert url-quote-magic
    553 autoload -Uz bracketed-paste-magic
    554 zle -N bracketed-paste bracketed-paste-magic
    555 
    556 # Auto correct commands, with exceptions (from oh-my-zsh)
    557 alias g='nocorrect git'
    558 alias git='nocorrect git'
    559 alias man='nocorrect man'
    560 alias sudo='nocorrect sudo'
    561 setopt correct
    562 setopt correct_all
    563 
    564 # Built-in Tetris (because why not)
    565 alias tetris="autoload -Uz tetriscurses && tetriscurses"
    566 
    567 # FZF for fuzzy finding
    568 . "$DOTFILES"/tools/fzf/shell/completion.zsh
    569 . "$DOTFILES"/tools/fzf/shell/key-bindings.zsh
    570 . "${XDG_CONFIG_HOME:-$HOME/.config}"/fzf/fzf.zsh
    571 
    572 insert-arg-of-prev-cmd() {
    573 : ${NUMERIC:-1}
    574 (( NUMERIC++ ))
    575 words=($(fc -ln -1))
    576 RBUFFER+="$words[$NUMERIC] "
    577 zle end-of-line
    578 }
    579 zle -N insert-arg-of-prev-cmd
    580 bindkey "\e^y" insert-arg-of-prev-cmd
    581 
    582 bindkey '\e#' pound-insert
    583 bindkey '^]' vi-find-next-char
    584 bindkey '\e^]' vi-find-prev-char
    585 bindkey -s '\el' '\C-e| less'
    586 bindkey -s '\e&' '\C-e&>/dev/null'
    587 
    588 # Bind lfcd (lf with cd) to ctrl-o
    589 bindkey -s '^o' '^ulfcd\n'
    590 
    591 # Ctrl-Z to fg
    592 _zsh_cli_fg() { fg; }
    593 zle -N _zsh_cli_fg
    594 bindkey '^Z' _zsh_cli_fg
    595 
    596 . $DOTFILES/shell/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
    597 
    598 # Zoxide
    599 command -v zoxide &>/dev/null && eval "$(zoxide init zsh)"
    600 
    601 # Nix
    602 if [ -e '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' ]; then
    603   # if PATH does *not* contain `~/.nix-profile/bin`
    604   if [ -n "${PATH##*.nix-profile/bin*}" ]; then
    605 
    606     # If this flag is set, `nix-daemon.sh` returns early
    607     # https://github.com/NixOS/nix/issues/5298
    608     unset __ETC_PROFILE_NIX_SOURCED
    609     . '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh'
    610   fi
    611 fi
    612 # End Nix
    613 
    614 
    615 . "$XDG_DATA_HOME/cargo/env"
    616 eval "$(starship init zsh)"
    617 # zprof