# Main zsh config file # Enable completions autoload -U compinit && compinit # Some utility stuff ZSH_PLUGIN_DIR="${ZSH_CONFIG_DIR}/plugins" # load_plugin function load_plugin { source "${ZSH_PLUGIN_DIR}/${1}/${1}.plugin.zsh" } # cmd_exists function cmd_exists { hash "${1}" >/dev/null 2>&1 } # source_user_file function source_user_file { local machine_specific="${ZSH_CONFIG_DIR}/${1}.${HOST}.zsh" local default="${ZSH_CONFIG_DIR}/${1}.zsh" if [ -e "${machine_specific}" ]; then source "${machine_specific}" elif [ -e "${default}" ]; then source "${default}" fi } # Load user early init file source_user_file "early-init" # Some options setopt autocd extendedglob rm_star_silent completealiases rc_quotes histignorespace unsetopt beep notify # Some general, random configuration # History stuff [ -v HISTFILE ] || HISTFILE="${HOME}/.cache/zsh/history" [ ! -d "$(dirname "${HISTFILE}")" ] && mkdir -p "$(dirname "${HISTFILE}")" HISTSIZE=1000 SAVEHIST=10000 # Tools for graphical sessions export BROWSER=mullvad-browser export READER=zathura if [[ -v WAYLAND_DISPLAY ]]; then function clip { (( ${#} >= 1 )) && (cat "${@}" | wl-copy) || wl-copy } else alias clip="xclip -selection clipboard" fi # I mess this up a lot alias cd..="cd .." # Make xargs, sudo, etc. understand aliases alias xargs='xargs ' cmd_exists sudo && alias sudo='sudo ' cmd_exists doas && alias doas='doas ' # Emacs and Neovim stuff if [[ -v NVIM ]]; then export EDITOR=nvr alias n=nvr alias nvim=nvr alias e=nvr alias emacs=nvr elif [[ -v INSIDE_EMACS ]]; then export EDITOR='emacsclient' alias e='emacsclient ' alias emacs='emacsclient ' alias n='emacsclient ' alias dired='emacsclient ' alias d='emacsclient ' else export EDITOR='emacsclient -a nvim -nw' # Because I keep using n by mistake alias emacs='emacsclient -a nvim -nw ' alias n=emacs alias e=emacs function dired() { if (( ${#} == 0 )); then emacsclient -nw --eval '(dired ".")' else args=() for arg; do args+=(--eval "(dired \"${arg:gs#\\#\\\\#:gs#\"#\\\"#}\")") done emacsclient -nw ${args} fi } alias d=dired fi export VISUAL="${EDITOR}" alias se=sudoedit # Safer file functions alias cp="cp -i" alias mv="mv -i" # Ledger stuff alias ldg='ledger -f "${HOME}/finance/finances.ledger"' # Trash put for safety if cmd_exists trash-put; then alias rm='echo "rm: I''m unsafe! Don''t use me."; false' alias tp=trash-put alias trr=trash-restore alias trl=trash-list alias tre=trash-empty alias trm=trash-rm else local rm_confirm_flag='-i' uname | grep -i linux >/dev/null && rm_confirm_flag='-I' alias rm="rm ${rm_confirm_flag}" fi # Enable mouse support in less export LESS="--mouse" # Bat configuration if cmd_exists bat; then # Pager export PAGER="bat --paging=always" # Less syntax highlighting in interactive shells alias less="bat --paging=always" # Use bat instead of cat alias cat="bat --paging=never" alias pcat="bat -pp" alias ncat="bat -pp --color=never" # Bat as man pager export MANPAGER="zsh -c 'col -bx | bat -l man --paging=always --style=plain'" export MANROFFOPT="-c" fi # Eza configuration if cmd_exists eza; then alias ls="eza --git -F" alias la="ls -a" alias l="ls -l" alias ll="ls -al" fi # Delta configuration if cmd_exists delta; then export DELTA_FEATURES='unobtrusive-line-numbers decorations side-by-side' export DELTA_PAGER='bat -p' export GIT_PAGER='delta' fi # Git aliases alias ga="git add" alias gaa="git add -A" alias gco="git commit" gcm() { git commit -m "${${@}}" } alias gca="git commit -a" gcam() { git commit -am "${${@}}" } alias gp="git push" alias gu="git pull" alias gf="git fetch" alias gt="git status" # Sudo last line with sudo-command-line() { [[ -z $BUFFER ]] && zle up-history if [[ $BUFFER == sudo\ * ]]; then LBUFFER="${LBUFFER#sudo }" elif [[ $BUFFER == $EDITOR\ * ]]; then LBUFFER="${LBUFFER#$EDITOR }" LBUFFER="sudoedit $LBUFFER" elif [[ $BUFFER == sudoedit\ * ]]; then LBUFFER="${LBUFFER#sudoedit }" LBUFFER="$EDITOR $LBUFFER" else LBUFFER="sudo $LBUFFER" fi } zle -N sudo-command-line bindkey -M vicmd "^f" sudo-command-line bindkey -M viins "^f" sudo-command-line # Autosuggestions load_plugin zsh-autosuggestions ZSH_AUTOSUGGEST_STRATEGY=(history completion) bindkey '^ ' autosuggest-accept # Use vi mode bindkey -v # Fast switch of modes KEYTIMEOUT=1 # Implement a replace mode bindkey -N virep viins bindkey -M vicmd "R" overwrite-mode function overwrite-mode { zle -K virep zle .overwrite-mode } zle -N overwrite-mode # Fancy prompt (starship) eval "$(starship init zsh)" # Change cursor shape for different vi modes. function __zsh_vim_key_prompt_handler { SPACESHIP_CHAR_SYMBOL="❮" local _shape=0 case "${KEYMAP}" in main) _shape=6 ;; # vi insert: line viins) _shape=6 ;; # vi insert: line isearch) _shape=6 ;; # inc search: line virep) _shape=4 ;; # vi replace: underscore command) _shape=4 ;; # read a command: underscore vicmd) _shape=2 ;; # vi cmd: block visual) _shape=2 ;; # vi visual mode: block viopp) _shape=1 ;; # vi operation pending: blinking block *) _shape=0 ;; esac zle reset-prompt printf '\e[%d q' "${_shape}" } function zle-keymap-select { __zsh_vim_key_prompt_handler } function zle-line-init { printf '\e[6 q' } zle -N zle-keymap-select zle -N zle-line-init # Clear scrollback on ^l __zsh_clear_screen_and_scrollback() { echoti civis >"$TTY" printf '%b' '\e[H\e[2J' >"$TTY" printf '%b' '\e[3J' >"$TTY" echoti cnorm >"$TTY" zle .reset-prompt zle -R } zle -N __zsh_clear_screen_and_scrollback bindkey '^L' __zsh_clear_screen_and_scrollback # Direnv if cmd_exists direnv; then eval "$(direnv hook zsh)" fi # Bookmarks [ -v ZSH_BOOKMARK_DIR ] || ZSH_BOOKMARK_DIR="${HOME}/.cache/zsh/bookmarks" [ -v ZSH_BOOKMARK_LS ] || ZSH_BOOKMARK_LS=true source "${ZSH_CONFIG_DIR}/bookmark.zsh" # Platform specific stuff [ -f /usr/bin/pacman ] && source "${ZSH_CONFIG_DIR}/arch.zsh" # FZF Integration load_plugin fzf-tab # Disable sort when completing `git checkout` zstyle ':completion:*:git-checkout:*' sort false # Set descriptions format to enable group support zstyle ':completion:*:descriptions' format '[%d]' # Set list-colors to enable filename colorizing zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS} # Preview directory's content with eza when completing cd zstyle ':fzf-tab:complete:cd:*' fzf-preview 'eza -1 --color=always $realpath' # Remove the '.' prefix at the start of every completion zstyle ':fzf-tab:*' prefix '' # Switch groups zstyle ':fzf-tab:*' switch-group 'ctrl-h' 'ctrl-l' # Toggle selected for all visible entries zstyle ':fzf-tab:*' fzf-bindings 'ctrl-a:toggle-all' # Load user init file source_user_file 'local' # THE FOLLOWING PLUGINS MUST COME LAST # More completions load_plugin zsh-completions # Syntax highlighting load_plugin zsh-syntax-highlighting # History substring search load_plugin zsh-history-substring-search bindkey '^[[A' history-substring-search-up bindkey '^[[B' history-substring-search-down #bindkey '^k' history-substring-search-up #bindkey '^j' history-substring-search-down #bindkey -M vicmd '^k' history-substring-search-up #bindkey -M vicmd '^j' history-substring-search-down bindkey -M vicmd 'k' history-substring-search-up bindkey -M vicmd 'j' history-substring-search-down bindkey -M emacs '^P' history-substring-search-up bindkey -M emacs '^N' history-substring-search-down # Only match at the beginning of the line HISTORY_SUBSTRING_SEARCH_PREFIXED="true" HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND="" setopt histignoredups # Clean up internal functions unfunction load_plugin unfunction cmd_exists unfunction source_user_file # Run fortune and cowsay if we are not in nvim [[ -v NVIM ]] || fortune | cowsay -felephant-in-snake -n