summaryrefslogtreecommitdiff
path: root/config/zshrc
diff options
context:
space:
mode:
authorIgor Soarez <igor@soarez.org>2026-09-17 19:45:23 +0100
committerIgor Soarez <igor@soarez.org>2026-09-17 19:45:23 +0100
commit13cc065ec014b86369dfe4ad60d1a43fa06fd251 (patch)
tree684690c61b7b59758c2aac132c65b81c86de0608 /config/zshrc
dotfiles
Shell, editor and terminal configuration, the tools that go with them, and szecret, an age-based secret manager whose store lives elsewhere. History restarts here. What came before was not written to be read by anyone else, and carried machine names, addresses and an encrypted secret store; it is kept privately instead. What is left is meant to be safe on any machine, including one whose owner is not me: see CLAUDE.md for the rule it is written to.
Diffstat (limited to 'config/zshrc')
-rwxr-xr-xconfig/zshrc167
1 files changed, 167 insertions, 0 deletions
diff --git a/config/zshrc b/config/zshrc
new file mode 100755
index 0000000..f211999
--- /dev/null
+++ b/config/zshrc
@@ -0,0 +1,167 @@
+# Emacs style
+bindkey -e
+zle -N edit-command-line
+bindkey '^xe' edit-command-line
+bindkey '^x^e' edit-command-line
+# Vi style:
+# zle -N edit-command-line
+# bindkey -M vicmd v edit-command-line
+
+bindkey \^U backward-kill-line
+
+# Enable Ctrl-x-e to edit command line
+autoload -U edit-command-line
+
+# completions
+fpath=(/usr/local/share/zsh-completions $fpath)
+
+# fix delete
+bindkey "^[[3~" delete-char
+bindkey "^[3;5~" delete-char
+
+# chpwd() { ls -A; } # Auto ls after changing directory.
+
+CDPATH=~ # Check ~ for directories after checking . (`c/d/` matches `./c*/d*/`, then tries `~/c*/d*/`).
+
+setopt no_auto_menu # don't complete on ambiguous cases
+setopt interactive_comments # Allow comments in the terminal.
+setopt BANG_HIST # Treat the '!' character specially during expansion.
+setopt EXTENDED_HISTORY # Write the history file in the ":start:elapsed;command" format.
+setopt INC_APPEND_HISTORY # Write to the history file immediately, not when the shell exits.
+setopt SHARE_HISTORY # Share history between all sessions.
+setopt HIST_EXPIRE_DUPS_FIRST # Expire duplicate entries first when trimming history.
+setopt HIST_IGNORE_DUPS # Don't record an entry that was just recorded again.
+setopt HIST_IGNORE_ALL_DUPS # Delete old recorded entry if new entry is a duplicate.
+setopt HIST_FIND_NO_DUPS # Do not display a line previously found.
+setopt HIST_IGNORE_SPACE # Don't record an entry starting with a space.
+setopt HIST_SAVE_NO_DUPS # Don't write duplicate entries in the history file.
+setopt HIST_REDUCE_BLANKS # Remove superfluous blanks before recording entry.
+# setopt HIST_VERIFY # Don't execute immediately upon history expansion.
+# setopt HIST_BEEP # Beep when accessing nonexistent history.
+
+# don't fret if globbing patterns can't be expanded, just
+# use them as is. useful for curl commands with '?'
+# https://superuser.com/questions/982110/how-can-i-disable-globbing-for-url-arguments-in-zsh
+setopt NO_NOMATCH
+
+# disable case sensitivity
+zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}'
+
+# don't ask "do you wish to see all NNN possibilities"
+export LISTMAX=0
+
+# if command -v startship
+# then
+# eval "$(starship init zsh)"
+local pure_src="$HOME/src/sindresorhus/pure"
+if [[ -d "$pure_src" ]]
+then
+ fpath=("$pure_src" "$fpath[@]")
+ autoload -U promptinit
+ promptinit
+ prompt pure
+ # PURE_PROMPT_SYMBOL='∴'
+else
+ # PROMPT="$SUPLEMENT%F{8}%1~%f ∴ "
+ PROMPT="%F{244}%1~%f ∴ "
+fi
+
+# Use modern completion system
+autoload -Uz compinit
+compinit -u
+zstyle ':completion:*' auto-description 'specify: %d'
+zstyle ':completion:*' completer _expand _complete _correct _approximate
+zstyle ':completion:*' format 'Completing %d'
+zstyle ':completion:*' group-name ''
+zstyle ':completion:*' menu select=2
+command -v dircolors >/dev/null 2>&1 && eval "$(dircolors -b)"
+zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS}
+zstyle ':completion:*' list-colors ''
+zstyle ':completion:*' list-prompt %SAt %p: Hit TAB for more, or the character to insert%s
+zstyle ':completion:*' matcher-list '' 'm:{a-z}={A-Z}' 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=* l:|=*'
+zstyle ':completion:*' menu select=long
+zstyle ':completion:*' select-prompt %SScrolling active: current selection at %p%s
+zstyle ':completion:*' use-compctl false
+zstyle ':completion:*' verbose true
+zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#)*=0=01;31'
+zstyle ':completion:*:kill:*' command 'ps -u $USER -o pid,%cpu,tty,cputime,cmd'
+
+# Recommended by Docker autocompletion
+# https://docs.docker.com/compose/completion/
+# fpath=(~/.zsh/completion $fpath)
+# autoload -Uz compinit && compinit -i
+
+autoload run-help
+HELPDIR=/usr/local/share/zsh/help
+
+# function that sources the given file if it exists
+source_if_exists() {
+ if [[ -f "$1" ]]
+ then
+ source "$1"
+ fi
+}
+
+source "$HOME/.profile"
+
+# fzf setup (must come after .profile which sets up PATH for brew)
+brew_prefix="$(brew --prefix 2>/dev/null || true)"
+if [[ -n "$brew_prefix" ]]
+then
+ # Setup fzf
+ if [[ ! "$PATH" == *opt/fzf/bin* ]]; then
+ export PATH="$PATH:$brew_prefix/opt/fzf/bin"
+ fi
+
+ # Auto-completion
+ [[ $- == *i* ]] && source "$brew_prefix/opt/fzf/shell/completion.zsh" 2> /dev/null
+
+ # Key bindings
+ source "$brew_prefix/opt/fzf/shell/key-bindings.zsh"
+elif [[ "$(uname)" == "Linux" ]] && command -v fzf > /dev/null
+then
+ # check if file exists before sourcing with zsh
+ source_if_exists /usr/share/doc/fzf/examples/key-bindings.zsh
+ source_if_exists /usr/share/doc/fzf/examples/completion.zsh
+ source_if_exists /usr/share/fzf/shell/key-bindings.zsh
+fi
+
+export FZF_COMPLETION_OPTS="--border --info=inline ${FZF_COMPLETION_OPTS:-}"
+
+setup_dir_hashes() {
+ local src="$HOME/src"
+ if [ -d /Volumes/Sense/src ]
+ then
+ src=/Volumes/Sense/src
+ fi
+ # Named directories for the checkouts this account works in, ~dot and the
+ # rest. Only those that exist: zsh prints a warning for a hash -d to a
+ # missing path, and which projects a machine has is the machine's business.
+ # Not `local path`: in zsh that is tied to $PATH, and assigning to it in the
+ # loop would blank PATH for the rest of this function, sourced fragment
+ # included.
+ local name dir
+ for name dir in \
+ dot "$src/soarez/dot" \
+ cs "$src/soarez/cloud-setup"
+ do
+ [ -d "$dir" ] && hash -d "$name=$dir"
+ done
+ # More of them, for whatever this machine works on, from a file another layer
+ # links in. Same shape: `hash -d name=path`, one per line, zsh syntax.
+ local extra="${XDG_CONFIG_HOME:-$HOME/.config}/shell/dir-hashes.zsh"
+ [ -r "$extra" ] && source "$extra"
+}
+setup_dir_hashes
+
+# ~/bin is prepended to PATH in config/env (which, unlike the line that used to
+# be here, skips it when the directory doesn't exist).
+
+export COURSIER_CREDENTIALS=~/.config/coursier/credentials.properties
+
+
+# ## Support .envrc files: https://direnv.net/docs/hook.html
+# eval "$(direnv hook zsh)"
+
+# ## https://www.jenv.be
+# eval \"$( jenv init - )\"