points/.zshrc

504 lines
12 KiB
Bash
Raw Normal View History

2023-03-23 09:49:43 +01:00
#!/bin/zsh
###
### Zsh Configuration
###
# Customize spelling correction prompt.
SPROMPT='zsh: correct %F{red}%R%f to %F{green}%r%f [nyae]? '
2023-04-26 10:04:45 +02:00
# Characters considered part of a word by the line editor
WORDCHARS="*?_-.~$"
2023-03-23 09:49:43 +01:00
2024-01-30 11:32:43 +01:00
# Set the "main" keyboard so `bindkey` without `-M` will change the expected map
bindkey -A viins main
2023-03-23 09:49:43 +01:00
###
### Path
###
setopt nullglob
2023-04-27 10:49:07 +02:00
path=(
$HOME/bin
$HOME/dev_local/bin
$HOME/.local/bin
$HOME/.local/*/bin
$HOME/go/bin
2023-10-04 16:14:42 +02:00
/opt/*/bin
2023-04-27 10:49:07 +02:00
$path)
setopt nonullglob
#export LD_LIBRARY_PATH=$HOME/dev_local/lib
fpath=($fpath /usr/share/zsh/site-functions)
# Remove duplicates
typeset -U path fpath
2023-03-23 09:49:43 +01:00
###
### Modules
###
2024-02-22 18:37:43 +01:00
### ASDF & direnv
#
# asdf plugin add direnv
# asdf install direnv latest
# asdf direnv setup --version latest
# asdf global direnv latest
2023-03-23 09:49:43 +01:00
#
source "${XDG_CONFIG_HOME:-$HOME/.config}/asdf-direnv/zshrc"
### b4b4r07/enhancd
#
# See https://github.com/b4b4r07/enhancd
#
2023-07-28 09:47:24 +02:00
# Changes from default behaviour:
# - Use single-dot to show upper tree (default is sub-dir);
# (use Alt-C (provided by fzf) to go into sub-dir).
2023-03-23 09:49:43 +01:00
ENHANCD_DIR=$HOME/.zim
2023-07-28 09:47:24 +02:00
ENHANCD_ARG_DOUBLE_DOT='.'
ENHANCD_ENABLE_SINGLE_DOT=false
2023-03-23 09:49:43 +01:00
### fzf
2024-02-06 09:31:54 +01:00
#
# Scripts sourced by zvm_after_init()
#
# - https://github.com/junegunn/fzf#key-bindings-for-command-line
# - https://github.com/junegunn/fzf#fuzzy-completion-for-bash-and-zsh
2023-03-23 09:49:43 +01:00
#
# Adapted from https://github.com/zimfw/fzf
#
export FZF_DEFAULT_OPTS='--height 40% --layout=reverse'
if (( ${+commands[fd]} )); then
export FZF_DEFAULT_COMMAND='command fd --color=always --hidden --no-ignore-vcs --exclude=.git --type=file --strip-cwd-prefix'
export FZF_ALT_C_COMMAND='command fd --color=always --hidden --no-ignore-vcs --exclude=.git --type=directory --strip-cwd-prefix'
# Trigger for completion: "**"
# Commands using _dir: FZF_COMPLETION_DIR_COMMANDS
_fzf_compgen_path() {
command fd --color=always --hidden --no-ignore-vcs --exclude=.git --type=file . "${1}"
}
_fzf_compgen_dir() {
command fd --color=always --hidden --no-ignore-vcs --exclude=.git --type=directory . "${1}"
}
export FZF_DEFAULT_OPTS="--ansi ${FZF_DEFAULT_OPTS}"
elif (( ${+commands[rg]} )); then
export FZF_DEFAULT_COMMAND="command rg -uu -g '!.git' --files"
_fzf_compgen_path() {
command rg -uu -g '!.git' --files "${1}"
}
fi
if (( ${+commands[bat]} )); then
export FZF_CTRL_T_OPTS="\
--preview='command bat --color=always --line-range :100 --style=plain {}'\
--preview-window=border-left\
${FZF_CTRL_T_OPTS}"
fi
if (( ${+FZF_DEFAULT_COMMAND} )) export FZF_CTRL_T_COMMAND=${FZF_DEFAULT_COMMAND}
# fzf: Debian Specific
#
FZF_CTRL_R_OPTS="--no-sort --exact"
# fzf: Alternate history (Ctrl-Win-R)
#
if [[ -f $ALT_HISTORY_FILE ]]; then
fzf-alt-history-widget() {
local selected num
setopt localoptions noglobsubst noposixbuiltins pipefail no_aliases 2> /dev/null
selected=( $(cat ${ALT_HISTORY_FILE} |
FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} $FZF_DEFAULT_OPTS --tiebreak=index --bind=ctrl-r:toggle-sort,ctrl-z:ignore $FZF_CTRL_R_OPTS --query=${(qqq)LBUFFER} +m" $(__fzfcmd)) )
local ret=$?
BUFFER=$selected
zle reset-prompt
return $ret
}
zle -N fzf-alt-history-widget
bindkey -M vicmd '^[[114;13u' fzf-alt-history-widget
bindkey -M viins '^[[114;13u' fzf-alt-history-widget
fi
2024-01-15 15:25:44 +01:00
### ZVM — Zsh VI mode
2023-03-23 09:49:43 +01:00
#
# https://github.com/jeffreytse/zsh-vi-mode
function zvm_config() {
ZVM_LINE_INIT_MODE=$ZVM_MODE_INSERT
}
2023-03-23 09:49:43 +01:00
# bindkey for other modules
function zvm_after_init {
# fzf
source /usr/share/doc/fzf/examples/key-bindings.zsh
source /usr/share/doc/fzf/examples/completion.zsh
# Automatic expansion of global aliases
bindkey " " globalias
bindkey "^ " magic-space # control-space to bypass completion
bindkey -M isearch " " magic-space # normal space during searches
}
###
### Zim Framework
###
# Use degit instead of git as the default tool to install and update modules.
zstyle ':zim:zmodule' use 'degit'
ZIM_HOME=${ZDOTDIR:-${HOME}}/.zim
if [[ ! -e ${ZIM_HOME}/zimfw.zsh ]]; then
# Download zimfw script if missing.
if (( ${+commands[curl]} )); then
curl -fsSL --create-dirs -o ${ZIM_HOME}/zimfw.zsh https://github.com/zimfw/zimfw/releases/latest/download/zimfw.zsh
else
mkdir -p ${ZIM_HOME} && wget -nv -O ${ZIM_HOME}/zimfw.zsh https://github.com/zimfw/zimfw/releases/latest/download/zimfw.zsh
fi
fi
if [[ ! ${ZIM_HOME}/init.zsh -nt ${ZDOTDIR:-${HOME}}/.zimrc ]]; then
# Install missing modules, and update ${ZIM_HOME}/init.zsh if missing or outdated.
source ${ZIM_HOME}/zimfw.zsh init -q
fi
source ${ZIM_HOME}/init.zsh
###
2023-05-30 10:00:44 +02:00
### Aliases & Small Functions
2023-03-23 09:49:43 +01:00
###
#
2023-04-19 14:34:57 +02:00
# https://www.thorsten-hans.com/5-types-of-zsh-aliases
#
2023-04-19 14:34:57 +02:00
# https://unix.stackexchange.com/questions/250314/whats-the-intended-use-case-for-complete-aliases-in-zsh
# See also the Completion section below
2023-03-23 09:49:43 +01:00
alias cp='cp --interactive'
alias mv='mv --interactive'
alias rm='rm -I'
2023-05-30 10:00:44 +02:00
mkcd() { command mkdir -p "$@" && builtin cd "$@" }
2023-03-23 09:49:43 +01:00
autoload -U zmv
alias mmv='noglob zmv -W'
2023-04-19 16:17:03 +02:00
# https://github.com/lsd-rs/lsd
# ~/.config/lsd/config.yaml
alias ls='lsd'
2023-04-19 16:17:03 +02:00
alias l='lsd --total-size -l'
alias ll='lsd --total-size -lA'
2023-04-19 16:17:03 +02:00
alias lt='lsd -ltr'
alias llt='lsd -ltrA'
alias lx='lsd -l --blocks=permission,user,group,context,size,date,name'
2023-04-19 16:17:03 +02:00
alias llx='lx -A'
2023-11-17 19:58:38 +01:00
alias t='lsd --long --tree --depth=2 --no-symlink'
2023-04-19 16:17:03 +02:00
2023-04-19 14:34:57 +02:00
# Dev
#
alias make='colormake-short'
compdef colormake=make
compdef colormake-short=make
# Git
#
alias dotfiles='/usr/bin/git --git-dir=$HOME/.dotfiles --work-tree=$HOME'
2023-03-23 09:49:43 +01:00
lg()
{
2023-10-31 19:03:54 +01:00
export LAZYGIT_NEW_DIR_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/lazygit/cd-on-quit_$$"
2023-03-23 09:49:43 +01:00
lazygit "$@"
if [ -f $LAZYGIT_NEW_DIR_FILE ]; then
cd "$(cat $LAZYGIT_NEW_DIR_FILE)"
rm -f $LAZYGIT_NEW_DIR_FILE > /dev/null
fi
}
2023-04-19 14:34:57 +02:00
# Kitty
#
2023-05-30 10:00:44 +02:00
hg () { kitten hyperlinked_grep "$@" }
2023-04-19 14:34:57 +02:00
compdef hg=rg
# Neovim — nvim
#
# To choose an existing instance for nvr, use:
# `export NVIM=$(nvr --serverlist | fzf --exit-0 --select-1) && echo $NVIM`
2023-11-17 19:58:38 +01:00
# nnn - n³
#
# See https://github.com/jarun/nnn/wiki/Usage#configuration
2024-01-12 10:55:31 +01:00
export NNN_ARCHIVE='\.(7z|bz2|cbz|cbr|gz|tar|tbz|tgz|xz|zip|zst)$'
2023-11-28 15:51:17 +01:00
if (( ${+commands[fuse-archive]} )); then
export NNN_ARCHMNT='fuse-archive'
fi
2023-12-19 15:47:31 +01:00
export NNN_BMS="d:~/Downloads"
2023-11-28 15:51:17 +01:00
export NNN_OPENER="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins/nuke"
2024-01-12 10:55:31 +01:00
export NNN_OPTS='ABeGo'
2023-11-17 19:58:38 +01:00
export NNN_ORDER="t:$HOME/Downloads"
2024-02-23 15:48:08 +01:00
export NNN_PLUG=';:-!bat --paging=always "$nnn"*;d:fzcd;m:mimelist;o:-!mimeopen --ask "$nnn"*;O:-!mimeopen "$nnn"*;U:umounttree;z:fzopen'
2023-11-17 19:58:38 +01:00
if (( ${+commands[trash-put]} )); then
export NNN_TRASH=1
elif (( ${+commands[gio]} )); then
export NNN_TRASH=2
fi
n()
{
if [ ${NNNLVL:-0} -gt 0 ]; then
echo 'nnn is already running'
return
fi
2023-12-19 15:47:31 +01:00
export GUI=1 # plugins: nuke, xdgdefault
export LESS=${LESS/F}
export NNN_TMPFILE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/cd-on-quit"
2024-02-13 14:19:12 +01:00
export PATH=$HOME/.config/nnn/plugins:$PATH
2023-11-17 19:58:38 +01:00
command nnn "$@"
if [ -f $NNN_TMPFILE ]; then
2024-01-12 10:55:31 +01:00
# Tmp file contains a `cd` directive that will
# behave like a `pushd`, ignoring duplicates.
setopt autopushd pushdignoredups
2023-11-17 19:58:38 +01:00
. $NNN_TMPFILE
rm -f $NNN_TMPFILE > /dev/null
2024-01-12 10:55:31 +01:00
dirs -v
2023-11-17 19:58:38 +01:00
fi
}
2024-02-13 14:19:12 +01:00
compdef n=nnn
2023-04-19 14:34:57 +02:00
2023-12-19 15:47:31 +01:00
nnn-file-widget() {
2024-01-22 10:15:07 +01:00
# Extract "shell word" at cursor position (respecting quotes)
local _cursor=$CURSOR
zle .select-a-shell-word -N
# Helper
nnn-pick()
{
IFS=$'\n'
local items=( $(command nnn -p- $1 < "$TTY") )
if (( #items > 0 )); then
items=( ${(q-)items} )
print -n "${(j: :)items} "
fi
}
# Adapt behaviour to buffer content
if (($CURSOR < _cursor)); then
# Nothing at cursor, restore state before calling nnn
CURSOR=${_cursor}
REGION_ACTIVE=0
zle -U "$(nnn-pick)"
else
# Provide content under cursor to nnn
zle .kill-region
local result="$(nnn-pick ${CUTBUFFER## })"
if (( #result == 0 )); then
# Nothing selected, restore content
zle .yank
else
# Replace content with what nnn returned
zle -U " $result"
fi
fi
# TODO single-op undo
# TODO Handle vicmd properly
zle .redisplay
2023-12-19 15:47:31 +01:00
}
zle -N nnn-file-widget
bindkey -M vicmd '\en' nnn-file-widget
bindkey -M viins '\en' nnn-file-widget
2024-01-17 16:32:04 +01:00
# Whiptail helper
#
2024-01-18 19:54:07 +01:00
# see https://stackoverflow.com/questions/1970180/whiptail-how-to-redirect-output-to-environment-variable
whiptail_checklist() {
autoload zmathfunc; zmathfunc # min, max, sum
eval $(resize) # COLUMNS, LINES
2024-01-17 16:32:04 +01:00
local res title="$1" text="$2"
2024-01-18 19:54:07 +01:00
(( width=max(30, $#text) ))
2024-01-17 16:32:04 +01:00
shift 2
2024-01-18 19:54:07 +01:00
# Make tags compatible with whiptail
2024-01-17 16:32:04 +01:00
local -a tags
2024-01-18 19:54:07 +01:00
for tag; do
tags+=($tag $tag 0)
(( width=max(width, $#tag) ))
done
# Compute "best" width & height
(( list_height=min(20, ${#*}, LINES * .5) ))
(( height=min(list_height+8, LINES) ))
(( width=min(width + 9, COLUMNS * .75) ))
tag=$(whiptail --title $title \
--checklist $text $height $width $list_height $tags \
--separate-output --notags 3>&1 1>&2 2>&3 3>&-)
res=$?
# Use res=${(f)"$(whiptail_checklist...)"} to ignore spaces
echo $tag
return $res
}
whiptail_menu() {
autoload zmathfunc; zmathfunc # min, max, sum
eval $(resize) # COLUMNS, LINES
local res title="$1" text="$2"
(( width=max(30, $#text) ))
shift 2
2024-01-17 16:32:04 +01:00
2024-01-18 19:54:07 +01:00
# Make tags compatible with whiptail
local -a tags
for tag; do
tags+=($tag $tag)
(( width=max(width, $#tag) ))
done
# Compute "best" width & height
(( menu_height=min(20, ${#*}, LINES * .5) ))
(( height=min(menu_height+8, LINES) ))
(( width=min(width + 5, COLUMNS * .75) ))
tag=$(whiptail --title $title \
--menu $text $height $width $menu_height $tags \
--notags 3>&1 1>&2 2>&3 3>&-)
2024-01-17 16:32:04 +01:00
res=$?
echo $tag
return $res
}
2023-03-23 09:49:43 +01:00
###
### Aliases -- Global & automatic expansion
###
alias -g D='$(date +%Y-%m-%d_%H-%M-%S)'
alias -g E='2> /dev/null'
alias -g G='|& grep -i'
alias -g H='| head'
alias -g HL='--help |& less -r'
alias -g L='| less'
alias -g N='&> /dev/null'
alias -g P='| peco'
alias -g S='| sort'
alias -g T='| tail'
# Expand aliases inline - see http://blog.patshead.com/2012/11/automatically-expaning-zsh-global-aliases---simplified.html
globalias() {
if [[ $LBUFFER =~ ' [A-Z0-9]+$' ]]; then
zle _expand_alias
# If you want the content of the alias to be also expanded:
# zle expand-word
# (otherwise, <BS><Tab> do the job...)
fi
zle self-insert
}
zle -N globalias
###
### Colors
###
if [[ -r /etc/grc.zsh ]]; then
# ! Incompatible with P10K Transient
source /etc/grc.zsh
# I want the default behaviour for:
unset -f journalctl
unset -f ls
fi
###
### Exports
###
export BROWSER=firefox
2023-07-28 09:47:24 +02:00
export EDITOR=vi
2023-03-23 09:49:43 +01:00
export LESS=-iFRS
export SYSTEMD_LESS='iFRSXMK'
2024-02-23 15:48:08 +01:00
export VISUAL=bat
2023-03-23 09:49:43 +01:00
2023-11-08 11:21:34 +01:00
# KeePassXC SSH Agent
[[ -v SSH_AUTH_SOCK ]] || export SSH_AUTH_SOCK=$(echo /tmp/ssh-*/agent.*(U))
2023-03-23 09:49:43 +01:00
###
### History
###
setopt hist_ignore_all_dups
setopt hist_ignore_space
setopt hist_no_functions
setopt hist_reduce_blanks
setopt hist_save_no_dups
setopt hist_verify
setopt inc_append_history
HISTFILE=${ZDOTDIR:-${HOME}}/.zhistory
HISTSIZE=4000
SAVEHIST=3000
HISTORY_IGNORE="(?|??|???|cd [a-zA-Z]*|* --help|#*|builtin *|run-help *)"
###
### Key Binding
###
# `bindkey | grep -v self-insert` to print existing bindings
# `showkey -a` to print keys
# Undo (useful to cancel completion -- borrowed from emacs keymap)
2024-01-12 10:55:31 +01:00
bindkey -M vicmd "^_" undo
bindkey -M viins "^_" undo
2023-03-23 09:49:43 +01:00
###
### Zsh Options
###
2024-03-01 15:59:30 +01:00
## Changing Directories
setopt no_auto_cd
2023-03-23 09:49:43 +01:00
2024-03-01 15:59:30 +01:00
## Expansion and Globbing
setopt equals
2023-03-23 09:49:43 +01:00
2024-03-01 15:59:30 +01:00
## Input/Output
2023-03-23 09:49:43 +01:00
setopt no_clobber
2024-03-01 15:59:30 +01:00
setopt correct
setopt interactive_comments
setopt no_print_exit_value
2023-03-23 09:49:43 +01:00
## Job control
2024-03-01 15:59:30 +01:00
setopt auto_continue
2023-03-23 09:49:43 +01:00
setopt no_bg_nice
2024-03-01 15:59:30 +01:00
setopt check_jobs
2023-03-23 09:49:43 +01:00
setopt no_hup
2024-03-01 15:59:30 +01:00
# Remove path duplicates
2023-03-23 09:49:43 +01:00
typeset -U path fpath
###
### Completion Late Definitions
###
2024-02-13 14:19:12 +01:00
compdef locate=glocate
2023-05-30 10:00:44 +02:00
2023-03-23 09:49:43 +01:00
# Hide "parameters" (i.e. environment variables) when looking for a "command"
zstyle ':completion:*:-command-:*' tag-order '!parameters'