dotfiles

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

zshrc (23516B)


      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_HOME="$XDG_DATA_HOME/gem"
    229 # export GEM_SPEC_CACHE="$XDG_CACHE_HOME/gem"
    230 export NOTMUCH_CONFIG="$XDG_CONFIG_HOME/notmuch/config"
    231 export GNUPGHOME="$XDG_CONFIG_HOME/gnupg"
    232 export R_PROFILE_USER="$XDG_CONFIG_HOME/R/Rprofile"
    233 export MAILCAPS="$XDG_CONFIG_HOME/mailcap"
    234 eval "$(perl -I$XDG_DATA_HOME/perl5/lib/perl5 -Mlocal::lib=$XDG_DATA_HOME/perl5)"
    235 alias glow='glow --config "$XDG_CONFIG_HOME/glow/glow.yml"'
    236 export RUSTUP_HOME="$XDG_DATA_HOME/rustup"
    237 export CARGO_HOME="$XDG_DATA_HOME/cargo"
    238 export RBENV_ROOT="$XDG_DATA_HOME/rbenv"
    239 export ANDROID_HOME="$XDG_DATA_HOME/android"
    240 export DOCKER_CONFIG="$XDG_CONFIG_HOME/docker"
    241 export ELECTRUMDIR="$XDG_DATA_HOME/electrum"
    242 alias gdb='gdb -n -x $XDG_CONFIG_HOME/gdb/init'
    243 export GDBHISTFILE="$XDG_CONFIG_HOME"/gdb/.gdb_history
    244 export SCREENRC="$XDG_CONFIG_HOME"/screen/screenrc
    245 export IPYTHONDIR="${XDG_CONFIG_HOME}/ipython"
    246 export LESSHISTFILE="$XDG_CACHE_HOME"/less/history
    247 export STACK_ROOT="$XDG_DATA_HOME"/stack
    248 export VAGRANT_HOME="$XDG_DATA_HOME"/vagrant
    249 export RIPGREP_CONFIG_PATH="$XDG_CONFIG_HOME/ripgrep/config"
    250 export ZDOTDIR=$HOME/.config/zsh
    251 export HISTFILE=$ZDOTDIR/.zsh_history
    252 # }}}
    253 
    254 # Paths {{{1
    255 [ -x /usr/libexec/path_helper ] && unset PATH && eval "$(/usr/libexec/path_helper -s)"
    256 
    257 [ -d "$HOME/.local/bin" ] || [ -L "$HOME/.local/bin" ]                           && [ -n "${PATH##*"$HOME/.local/bin"*}" ]                  && PATH="$HOME/.local/bin:$PATH"
    258 [ -d "$GOPATH/bin" ] || [ -L "$GOPATH/bin" ]                                     && [ -n "${PATH##*"$GOPATH/bin"*}" ]                       && PATH="$GOPATH/bin:$PATH"
    259 [ -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"
    260 [ -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"
    261 [ -d "/usr/local/sbin" ] || [ -L "/usr/local/sbin" ]                             && [ -n "${PATH##*"/usr/local/sbin"*}" ]                   && PATH="/usr/local/sbin:$PATH"
    262 [ -d "$HOME/.local/gnat/bin" ] || [ -L "$HOME/.local/gnat/bin" ]                 && [ -n "${PATH##*"$HOME/.local/gnat/bin"*}" ]             && PATH="$HOME/.local/gnat/bin:$PATH"
    263 [ -d "$HOME/bin" ] || [ -L "$HOME/bin" ]                                         && [ -n "${PATH##*"$HOME/bin"*}" ]                         && PATH="$HOME/bin:$PATH"
    264 [ -d "$HOME/.bin" ] || [ -L "$HOME/.bin" ]                                       && [ -n "${PATH##*"$HOME/.bin"*}" ]                        && PATH="$HOME/.bin:$PATH"
    265 [ -d "$DOTFILES/scripts" ] || [ -L "$DOTFILES/scripts" ]                               && [ -n "${PATH##*"$DOTFILES/scripts"*}" ]                    && PATH="$DOTFILES/scripts:$PATH"
    266 [ -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"
    267 [ -d "$HOME/.elan/bin" ]                                                         && [ -n "${PATH##*"$HOME/.elan/bin"*}" ]                   && PATH="$HOME/.elan/bin:$PATH"
    268 [ -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"
    269 [ -d "$DOTFILES/tools/shfm" ]                                                    && [ -n "${PATH##*"$DOTFILES/tools/shfm"*}" ]              && PATH="$DOTFILES/tools/shfm:$PATH"
    270 [ -d "$DOTFILES/tools/pfetch" ]                                                  && [ -n "${PATH##*"$DOTFILES/tools/pfetch"*}" ]            && PATH="$DOTFILES/tools/pfetch:$PATH"
    271 [ -d "$DOTFILES/tools/tuxi" ]                                                    && [ -n "${PATH##*"$DOTFILES/tools/tuxi"*}" ]              && PATH="$DOTFILES/tools/tuxi:$PATH"
    272 [ -d "$DOTFILES/tools/speedread" ]                                               && [ -n "${PATH##*"$DOTFILES/tools/speedread"*}" ]         && PATH="$DOTFILES/tools/speedread:$PATH"
    273 [ -d "$DOTFILES/tools/fzf/bin" ]                                                 && [ -n "${PATH##*"$DOTFILES/tools/fzf/bin"*}" ]           && PATH="$DOTFILES/tools/fzf/bin:$PATH"
    274 [ -d "$DOTFILES/tools/solvitaire" ]                                              && [ -n "${PATH##*"$DOTFILES/tools/solvitaire"*}" ]        && PATH="$DOTFILES/tools/solvitaire:$PATH"
    275 [ -d "$XDG_DATA_HOME/perl5/bin" ]                                                && [ -n "${PATH##*"$XDG_DATA_HOME/perl5/bin"*}" ]          && PATH="$XDG_DATA_HOME/perl5/bin:$PATH"
    276 [ -d "$HOME/.jenv/bin" ]                                                         && [ -n "${PATH##*"$HOME/.jenv/bin"*}" ]                   && PATH="$HOME/.jenv/bin:$PATH"
    277 [ -d "$XDG_DATA_HOME/cargo/bin" ]                                                && [ -n "${PATH##*"$XDG_DATA_HOME/cargo/bin"*}" ]          && PATH="$XDG_DATA_HOME/cargo/bin:$PATH"
    278 [ -d "/usr/local/go/bin" ] || [ -L "/usr/local/go/bin" ]                         && [ -n "${PATH##*"/usr/local/go/bin"*}" ]                 && PATH="/usr/local/go/bin:$PATH"
    279 [ -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"
    280 [ -d "/usr/local/opt/sqlite" ]                                                   && [ -n "${PATH##*"/usr/local/opt/sqlite/bin"*}" ]         && PATH="/usr/local/opt/sqlite/bin:$PATH"
    281 [ -d "$HOME/.rvm/bin" ]                                                   && [ -n "${PATH##*"$HOME/.rvm/bin"*}" ]         && PATH="$HOME/.rvm/bin:$PATH"
    282 [ -d "$HOME/.local/share/gem/bin" ]                                                   && [ -n "${PATH##*"$HOME/.local/share/gem/bin"*}" ]         && PATH="$HOME/.local/share/gem/bin:$PATH"
    283 [ -d "/run/current-system/sw/bin" ]                                                   && [ -n "${PATH##*"/run/current-system/sw/bin "*}" ]         && PATH="/run/current-system/sw/bin:$PATH"
    284 
    285 export PATH
    286 # }}}
    287 
    288 # ZSH-specific inits
    289 if command -v startx >/dev/null 2>&1 && [ "$(tty)" = "/dev/tty1" ]; then
    290   pgrep dwm || startx
    291 fi
    292 [ -n "$DOTFILES" ] || { printf '$DOTFILES not set, press enter to quit' && read -r && exit 1; }
    293 
    294 (cat ~/.cache/wal/sequences &)
    295 . ~/.cache/wal/colors-tty.sh
    296 
    297 # Enable custom aliases and functions
    298 alias irssi='irssi --config="$XDG_CONFIG_HOME"/irssi/config --home="$XDG_CONFIG_HOME"/irssi'
    299 alias tmux='tmux -f $XDG_CONFIG_HOME/tmux/tmux.conf'
    300 alias w3m='w3m -config $XDG_CONFIG_HOME/w3m/config -bookmark $XDG_CONFIG_HOME/w3m/bookmark.html'
    301 alias monero-wallet-cli='monero-wallet-cli --config-file ~/.config/bitmonero/monero-wallet-cli.conf'
    302 alias docker='sudo -E docker'
    303 alias fucking="sudo"                                                            # Because sometimes I'm frustrated
    304 alias cp='cp -ivR'                                                              # Prompt if overwrite, verbose
    305 alias grep='grep --color=auto'
    306 alias mv='mv -iv'                                                               # Prompt if overwrite, verbose
    307 alias lynx='lynx -vikeys'
    308 alias mkdir='mkdir -pv'                                                         # Create intermediate dirs, verbose
    309 alias ls="command ls -lh"                                                       # List in long format, human-readable sizes
    310 alias l="command ls -lah"                                                       # Ls but with all files
    311 alias ll="command ls -FGlAhpO@"                                                 # Ls but show everything you can
    312 alias l.="command ls -a | grep '^\.'"                                           # Ls but only dotfiles
    313 alias less='less -RicX'                                                         # Search ig case, fix ANSI colors, don't send init strings, clear screen
    314 alias du="du -sh"                                                              # Show entry for each file, human-readable sizes
    315 alias df="df -h"                                                                # Show human-readable sizes
    316 alias bc="bc -ql"                                                               # Don't print welcome message, use the standard math lib
    317 alias jobs="jobs -l"                                                            # Show everything including PIDs
    318 alias g='git'                                                                   # Make git easier to type
    319 alias wheredef='type -a'                                                        # Where is a function defined?
    320 alias j='joplin'
    321 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
    322 alias lsblk="lsblk -o NAME,LABEL,PARTLABEL,TYPE,FSTYPE,SIZE,MOUNTPOINT,STATE"   # The columns I want to see in lsblk
    323 alias confucius="curl confucius-quote.herokuapp.com"                            # A joke curl service I made
    324 alias tx="tmuxinator"
    325 alias mpva="mpv --no-audio-display --no-video --volume=50"
    326 alias irrsi="irssi --home=~/.config/irssi"
    327 # alias irssi="ssh -t vps 'screen -r irssi'"
    328 alias scim="sc-im"
    329 alias mbsync='mbsync -c $HOME/.config/mbsync/mbsyncrc'
    330 alias mutt="neomutt"
    331 alias gotop='sudo gotop -C $XDG_CONFIG_HOME/gotop/gotop.conf'
    332 alias vim=nvim
    333 [ -n "$VIM_TERMINAL" ] && alias vim=vimsend
    334 [ -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"
    335 command -v scrcpy >/dev/null 2>&1 && alias scrcpy='scrcpy --no-audio --shortcut-mod=ralt -b2M -S'
    336 command -v lazydocker >/dev/null 2>&1 && alias lzd=lazydocker
    337 cd() { builtin cd -P "$@" || return; }                                  # list contents after cding
    338 mkcd() { mkdir -p -- "$1" && cd -P -- "$1" || return; }                 # make dir and cd at the same time
    339 procinfo() { pgrep -f "$1"; }                                           # get info about a process (by name)
    340 rmempty() { find "${1-.}"  -type d -empty -depth -delete; }             # remove empty directories
    341 hr() { : $((i=0)); while [ $((i<$(tput cols))) -ne 0 ]; do printf "#"; _=$((i=i+1)); done; echo; }  # insert a <hr> in the terminal
    342 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.
    343 nls() { printf $((`ls -l | wc -l | xargs echo` - 1)); }                        # Count the number of files in the directory
    344 reload-completions() { rm $ZDOTDIR/.zcompdump && compinit; }
    345 reload() {
    346   local START_TIME=$SECONDS
    347   if [[ $SHELL = *"zsh"* ]]; then
    348     source "$HOME"/.zshrc
    349   elif [[ $SHELL = *"bash"* ]]; then
    350     source "$HOME"/.bash_profile
    351   fi
    352   echo "Reloaded config ($(( SECONDS-START_TIME )) sec)."
    353 }
    354 extract () {
    355   if [ -f "$1" ] ; then
    356     case $1 in
    357       *.tar.bz2)   tar xjf "$1"     ;;
    358       *.tar.gz)    tar xzf "$1"     ;;
    359       *.bz2)       bunzip2 "$1"     ;;
    360       *.rar)       unrar e "$1"     ;;
    361       *.gz)        gunzip "$1"      ;;
    362       *.tar)       tar xf "$1"      ;;
    363       *.tbz2)      tar xjf "$1"     ;;
    364       *.tgz)       tar xzf "$1"     ;;
    365       *.zip)       unzip "$1"       ;;
    366       *.Z)         uncompress "$1"  ;;
    367       *.7z)        7z x "$1"        ;;
    368       *)     echo "'$1' cannot be extracted via extract()" ;;
    369     esac
    370   else
    371     echo "'$1' is not a valid file"
    372   fi
    373 }
    374 
    375 # Docker functions
    376 if command -v docker &>/dev/null; then
    377   eslint_here() {
    378     docker run -it --rm -v $(pwd):/data cytopia/eslint . -f unix;
    379   }
    380 fi
    381 
    382 # Applescript-reliant functions
    383 if command -v osascript &> /dev/null; then
    384   # cd to current Finder directory
    385   cdf() {
    386     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)')"
    387     if [ -n "$target" ]; then
    388       cd "$target" || printf "Could not cd to %s.\n" >&2
    389       pwd
    390     else
    391       printf 'No Finder window found.\n' >&2
    392     fi
    393   }
    394 
    395   # echo current Finder directory
    396   gdf() {
    397     osascript -e 'tell application "Finder" to if (count of Finder windows) > 0 then get POSIX path of (target of front Finder window as text)'
    398   }
    399   # echo selected Finder file
    400   gsf() {
    401     osascript -e 'tell application "Finder" to return POSIX path of (first item of (get selection as alias list) as alias)' | rev | sed 's/^\///' | rev;
    402   }
    403 fi
    404 
    405 if command -v qlmanage &> /dev/null; then
    406   qlf() { qlmanage -p "$@" &> /dev/null; }
    407 fi
    408 
    409 # fzf-reliant functions
    410 if command -v fzf >/dev/null 2>&1; then
    411   { [ -f ~/.config/dark-theme ] && export BAT_THEME='1337'; } || export BAT_THEME='GitHub'
    412   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'"
    413   export FZF_DEFAULT_COMMAND="rg -l -H \"\""
    414   # script edit
    415   se() {
    416     local files
    417     IFS=$'\n' files=($(command find "$DOTFILES/scripts" -type f -or -type l -not -ipath "*/.git/*" | fzf -m --inline-info --prompt="edit> " --height=40 --reverse))
    418     [[ -n "$files" ]] && ${EDITOR:-vim} "${files[@]}"
    419   }
    420   # script create
    421   sc() {
    422     [ -z "$1" ] && echo "Filename must be passed as an argument." && return 1
    423     vim $DOTFILES/scripts/"$1" && chmod +x $DOTFILES/scripts/"$1"
    424   }
    425 
    426   # script find
    427   sf() {
    428     local f
    429     IFS=$'\n' f=($(command find "$DOTFILES"/scripts -type f -not -ipath "*/.git/*" | fzf +m --prompt="find> " --height=40 --reverse --cycle))
    430     [[ -n "$f" ]] && printf "$f"
    431   }
    432 
    433   # config edit
    434   ce() {
    435     local files
    436     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))
    437     [[ -n "$files" ]] && ${EDITOR:-vim} "${files[@]}"
    438   }
    439 
    440   # config find
    441   cf() {
    442     local f
    443     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))
    444     [[ -n "$f" ]] && printf "$f"
    445   }
    446 
    447   # vim setting edit
    448   ve() {
    449     local files
    450     IFS=$'\n' files=($(command find ~/.dotfiles/vim -type f -not -ipath "*/.git/*" | fzf -m --inline-info --prompt="edit (vim)> " --height=40 --reverse))
    451     [[ -n "$files" ]] && ${EDITOR:-vim} "${files[@]}"
    452   }
    453   # run python
    454   rp() {
    455     fzf --print-query --preview-window=right:50% --preview 'python -c {q}' <<<''
    456   }
    457   # Run ruby
    458   rr() {
    459     fzf --print-query --preview-window=right:50% --preview 'ruby -e {q}' <<<''
    460   }
    461   # run bash
    462   rb() {
    463     fzf --print-query --preview-window=right:50% --preview 'bash -c {q}' <<<''
    464   }
    465   # run json
    466   rj() {
    467     fzf --preview "cat $1 | jq {q}"
    468   }
    469 
    470   # list man pages
    471   mans() {
    472     sec="${1:-1|4}"
    473     # (sorry, couldn't be arsed to deal with escaping parentheses for variable passing in awk)
    474     manlist=$(man -k . 2>/dev/null | awk "$(printf 'BEGIN {FS=OFS="- "} /\([%s]\)/ {gsub(/\([0-9]\)/, "", $1); if (!seen[$0]++) { print }}' "$sec")" | fzf) \
    475       && man "$(echo "$manlist" | awk -F' |,' '{print $1}')" \
    476       && unset manlist
    477   }
    478 
    479   # list env variables
    480   envs() {
    481     var=$(printenv | cut -d= -f1 | fzf) \
    482       && echo "$var=$(printenv "$var")" \
    483       && unset var
    484   }
    485 fi
    486 
    487 if command -v rg >/dev/null 2>&1; then
    488   alias rgv='rg --vimgrep'
    489 fi
    490 # lf-reliant functions
    491 if command -v lf >/dev/null 2>&1; then
    492   lfcd() {
    493     tmp="$(mktemp)"
    494     lf -last-dir-path="$tmp" "$@"
    495     if [ -f "$tmp" ]; then
    496       dir="$(cat "$tmp")"
    497       rm "$tmp"
    498       [ -d "$dir" ] && [ "$dir" != "$(pwd)" ] && cd "$dir" || return
    499     fi
    500   }
    501 fi
    502 
    503 # Options
    504 if [ -n "$VIMRUNTIME" ]; then set -o vi
    505 else set -o emacs; fi
    506 
    507 setopt alwaystoend         # On completion, move cursor to end of word
    508 setopt autocd              # If I forget 'cd' before a path
    509 setopt autopushd           # Make cd push old directory onto stack
    510 setopt completeinword      # Completion from both ends of word
    511 setopt extendedhistory     # Save timestamp and duration of commands in histfile
    512 setopt interactivecomments # Allow comments
    513 setopt monitor             # Allow job control
    514 setopt nocaseglob          # Globs should be case insensitive
    515 setopt noflowcontrol       # Disable ^S and ^Q
    516 setopt promptsubst         # Parameter expansion, command subst, arithmetic expansion done in prompt
    517 setopt pushdignoredups     # Don't pushd duplicate directories
    518 setopt pushdminus          # Exchange meanings of + and - on directory stack
    519 
    520 # History options
    521 setopt sharehistory        # Import commands from histfile and append typed to histfile
    522 setopt appendhistory       # Append to history
    523 setopt incappendhistory    # Append immediately, not at shell exit
    524 setopt histexpiredupsfirst # When trimming history, remove duplicates first
    525 setopt histignoredups      # Don't save command into history if duplicate of previous
    526 setopt histignorespace     # Don't save command into history if starts with space
    527 setopt histfindnodups      # Ignore duplicates when searching
    528 setopt histreduceblanks    # Remove blank lines from history
    529 setopt histverify          # Show expansion first before executing
    530 
    531 # Enable extra completions
    532 # fpath=($DOTFILES/shell/zsh-completions/src $DOTFILES/shell/osx-zsh-completions/ $DOTFILES/shell/zsh-completions-mine/ $fpath)
    533 # Smarter completion initialization
    534 autoload -Uz compinit
    535 if [ "$(date +'%j')" != "$(stat -f '%Sm' -t '%j' $ZDOTDIR/.zcompdump 2>/dev/null)" ]; then
    536     compinit
    537 else
    538     compinit -C
    539 fi
    540 . $DOTFILES/shell/oh-my-zsh-defaults/completion.zsh
    541 . $DOTFILES/shell/oh-my-zsh-defaults/directories.zsh
    542 . $DOTFILES/shell/oh-my-zsh-defaults/history.zsh
    543 . $DOTFILES/shell/oh-my-zsh-defaults/keys.zsh
    544 
    545 # Allow pasting bare URLs
    546 autoload -Uz url-quote-magic
    547 zle -N self-insert url-quote-magic
    548 autoload -Uz bracketed-paste-magic
    549 zle -N bracketed-paste bracketed-paste-magic
    550 
    551 # Auto correct commands, with exceptions (from oh-my-zsh)
    552 alias g='nocorrect git'
    553 alias git='nocorrect git'
    554 alias man='nocorrect man'
    555 alias sudo='nocorrect sudo'
    556 setopt correct
    557 setopt correct_all
    558 
    559 # Built-in Tetris (because why not)
    560 alias tetris="autoload -Uz tetriscurses && tetriscurses"
    561 
    562 # FZF for fuzzy finding
    563 . "$DOTFILES"/tools/fzf/shell/completion.zsh
    564 . "$DOTFILES"/tools/fzf/shell/key-bindings.zsh
    565 . "${XDG_CONFIG_HOME:-$HOME/.config}"/fzf/fzf.zsh
    566 
    567 insert-arg-of-prev-cmd() {
    568 : ${NUMERIC:-1}
    569 (( NUMERIC++ ))
    570 words=($(fc -ln -1))
    571 RBUFFER+="$words[$NUMERIC] "
    572 zle end-of-line
    573 }
    574 zle -N insert-arg-of-prev-cmd
    575 bindkey "\e^y" insert-arg-of-prev-cmd
    576 
    577 bindkey '\e#' pound-insert
    578 bindkey '^]' vi-find-next-char
    579 bindkey '\e^]' vi-find-prev-char
    580 bindkey -s '\el' '\C-e| less'
    581 bindkey -s '\e&' '\C-e&>/dev/null'
    582 
    583 # Bind lfcd (lf with cd) to ctrl-o
    584 bindkey -s '^o' '^ulfcd\n'
    585 
    586 # Ctrl-Z to fg
    587 _zsh_cli_fg() { fg; }
    588 zle -N _zsh_cli_fg
    589 bindkey '^Z' _zsh_cli_fg
    590 
    591 . $DOTFILES/shell/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
    592 
    593 # Zoxide
    594 command -v zoxide &>/dev/null && eval "$(zoxide init zsh)"
    595 
    596 # Nix
    597 if [ -e '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' ]; then
    598   # if PATH does *not* contain `~/.nix-profile/bin`
    599   if [ -n "${PATH##*.nix-profile/bin*}" ]; then
    600 
    601     # If this flag is set, `nix-daemon.sh` returns early
    602     # https://github.com/NixOS/nix/issues/5298
    603     unset __ETC_PROFILE_NIX_SOURCED
    604     . '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh'
    605   fi
    606 fi
    607 # End Nix
    608 
    609 
    610 . "$XDG_DATA_HOME/cargo/env"
    611 eval "$(starship init zsh)"
    612 # zprof