# ===================== # Dotfiles Zshrc: conventions, device profiles, plugins, workflow # ===================== # - Modular, idempotent, and device-aware (laptop/desktop via $DOTFILES_DEVICE) # - All plugins managed via Zinit for speed and maintainability # - Developer/power user aliases, functions, and keybinds # - Device-specific fragments: ~/.zshrc.laptop, ~/.zshrc.desktop (auto-sourced) # - Commit after each logical change with descriptive message # - See AGENTS.md for full conventions # ===================== # Environment settings # ===================== # Do Not Track for CLI tools export DO_NOT_TRACK=1 # Preferred editor export EDITOR='nvim' # ===================== # Device profile sourcing (laptop/desktop) # ===================== if [[ -n "$DOTFILES_DEVICE" ]]; then if [[ "$DOTFILES_DEVICE" == "laptop" && -f "$HOME/.zshrc.laptop" ]]; then source "$HOME/.zshrc.laptop" elif [[ "$DOTFILES_DEVICE" == "desktop" && -f "$HOME/.zshrc.desktop" ]]; then source "$HOME/.zshrc.desktop" fi fi # ===================== # Zinit plugin manager setup # ===================== ZINIT_HOME="${XDG_DATA_HOME:-$HOME/.local/share}/zinit/zinit.git" if [[ ! -d $ZINIT_HOME ]]; then mkdir -p "$(dirname $ZINIT_HOME)" git clone https://github.com/zdharma-continuum/zinit.git "$ZINIT_HOME" fi source "$ZINIT_HOME/zinit.zsh" # ===================== # Zinit auto-update logic (updates Zinit and plugins once per week) # ===================== ZINIT_UPDATE_STAMP="$HOME/.cache/zinit-last-update" ZINIT_UPDATE_INTERVAL=$((7*24*60*60)) # 7 days (weekly) in seconds zinit_auto_update() { local now=$(date +%s) local last=0 if [[ -f "$ZINIT_UPDATE_STAMP" ]]; then last=$(cat "$ZINIT_UPDATE_STAMP" 2>/dev/null) fi if (( now - last > ZINIT_UPDATE_INTERVAL )); then echo "[zinit] Auto-updating Zinit and plugins..." zinit self-update && zinit update --all echo $now > "$ZINIT_UPDATE_STAMP" fi } # Run auto-update on shell startup (fast if already up-to-date) zinit_auto_update # Manual update alias alias zinit-update-now='zinit self-update && zinit update --all && date +%s > "$ZINIT_UPDATE_STAMP" && echo "[zinit] Manual update complete."' # ===================== # Prompt and UI # ===================== # --- Zinit plugin loading --- # All plugins are loaded via Zinit for modularity and speed zinit light zsh-users/zsh-autosuggestions zinit light zsh-users/zsh-syntax-highlighting zinit light Aloxaf/fzf-tab zinit light zsh-users/zsh-completions zinit light zsh-users/zsh-history-substring-search zinit snippet OMZP::git # Starship prompt initialization export STARSHIP_CONFIG="$HOME/.config/starship.toml" if command -v starship >/dev/null; then eval "$(starship init zsh)" fi # --- Starship prompt --- # Starship prompt is now used exclusively. See https://starship.rs for config. # Device profile info can be added via Starship config if needed. # ===================== # fzf integration # ===================== # fzf key bindings and completion if [ -f /usr/share/fzf/key-bindings.zsh ]; then source /usr/share/fzf/key-bindings.zsh fi if [ -f /usr/share/fzf/completion.zsh ]; then source /usr/share/fzf/completion.zsh fi # ===================== # Aliases & Functions (Developer Workflow) # ===================== # Modern replacements for coreutils alias cat="bat" alias ls="exa --icons" alias ll="exa -l --icons" alias la="exa -la --icons" # Developer tools alias lg="lazygit" alias gs="git status" alias ga="git add" alias gc="git commit" alias gco="git checkout" alias gcm="git commit -m" alias glog="git log --oneline --graph --decorate" alias gpull="git pull" alias gpush="git push" alias gdiff="git diff" alias gbr="git branch" alias gsw="git switch" alias gcl="git clone" # Navigation alias ..="cd .." alias ...="cd ../.." # ===================== # Robust keybinds for navigation and editing (support most terminals) # ===================== # Use terminfo for portability typeset -g -A key key[Home]="${terminfo[khome]}" key[End]="${terminfo[kend]}" key[Insert]="${terminfo[kich1]}" key[Delete]="${terminfo[kdch1]}" key[Up]="${terminfo[kcuu1]}" key[Down]="${terminfo[kcud1]}" key[Left]="${terminfo[kcub1]}" key[Right]="${terminfo[kcuf1]}" key[PageUp]="${terminfo[kpp]}" key[PageDown]="${terminfo[knp]}" key[Shift-Tab]="${terminfo[kcbt]}" [[ -n "${key[Home]}" ]] && bindkey -- "${key[Home]}" beginning-of-line [[ -n "${key[End]}" ]] && bindkey -- "${key[End]}" end-of-line [[ -n "${key[Insert]}" ]] && bindkey -- "${key[Insert]}" overwrite-mode [[ -n "${key[Delete]}" ]] && bindkey -- "${key[Delete]}" delete-char [[ -n "${key[Up]}" ]] && bindkey -- "${key[Up]}" up-line-or-history [[ -n "${key[Down]}" ]] && bindkey -- "${key[Down]}" down-line-or-history [[ -n "${key[Left]}" ]] && bindkey -- "${key[Left]}" backward-char [[ -n "${key[Right]}" ]] && bindkey -- "${key[Right]}" forward-char [[ -n "${key[PageUp]}" ]] && bindkey -- "${key[PageUp]}" beginning-of-buffer-or-history [[ -n "${key[PageDown]}" ]] && bindkey -- "${key[PageDown]}" end-of-buffer-or-history [[ -n "${key[Shift-Tab]}" ]] && bindkey -- "${key[Shift-Tab]}" reverse-menu-complete # Common escape sequences for Ctrl/Alt + Arrow keys (Alacritty, xterm, etc.) bindkey '^[[1;5D' backward-word # Ctrl+Left bindkey '^[[1;5C' forward-word # Ctrl+Right bindkey '^[Od' backward-word # Ctrl+Left (alternate) bindkey '^[Oc' forward-word # Ctrl+Right (alternate) bindkey '^[[1;3D' backward-word # Alt+Left bindkey '^[[1;3C' forward-word # Alt+Right # Already present: Alt+b/f for word movement # bindkey '^[b' backward-word # bindkey '^[f' forward-word # Optionally, Alt+Up/Down for directory navigation (custom widgets can be added) # Ensure terminal is in application mode for terminfo keycodes if (( ${+terminfo[smkx]} && ${+terminfo[rmkx]} )); then autoload -Uz add-zle-hook-widget function zle_application_mode_start { echoti smkx } function zle_application_mode_stop { echoti rmkx } add-zle-hook-widget -Uz zle-line-init zle_application_mode_start add-zle-hook-widget -Uz zle-line-finish zle_application_mode_stop fi # Quick edit .zshrc alias ezrc="nvim ~/.zshrc" # Function: reload zsh config reload-zsh() { source ~/.zshrc && echo 'Reloaded .zshrc'; } # ===================== # Zsh history settings # ===================== HISTFILE=~/.zsh_history HISTSIZE=10000 SAVEHIST=10000 setopt append_history setopt inc_append_history setopt share_history setopt hist_ignore_dups setopt hist_reduce_blanks # ===================== # Zsh plugin integrations # ===================== # Autosuggestions if [ -f /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh ]; then source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh # Accept autosuggestion with Ctrl+F or Right Arrow bindkey '^F' autosuggest-accept bindkey '^[[C' autosuggest-accept fi # Syntax highlighting if [ -f /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh ]; then source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh fi # Additional completions fpath+=/usr/share/zsh/site-functions autoload -Uz compinit && compinit # ===================== # Keybinds (Navigation, Editing, FZF, Completion) # ===================== # Emacs mode by default (comment out for vi mode) bindkey -e # Uncomment below for vi mode # bindkey -v # History search bindkey '^R' fzf-history-widget # fzf history search (fzf-tab) bindkey '^S' history-incremental-search-forward bindkey '^H' history-substring-search-backward # substring search (plugin) bindkey '^P' history-substring-search-forward # substring search (plugin) # Navigation bindkey '^A' beginning-of-line bindkey '^E' end-of-line bindkey '^[b' backward-word bindkey '^[f' forward-word # Editing bindkey '^U' kill-whole-line bindkey '^W' backward-kill-word bindkey '^K' kill-line bindkey '^Y' yank # Completion bindkey '^I' expand-or-complete bindkey '^ ' menu-complete # fzf keybinds (if fzf is loaded) if [ -n "$FZF_TMUX" ] || [ -f /usr/share/fzf/key-bindings.zsh ]; then # Ctrl+T: fzf file search bindkey '^T' fzf-file-widget # Alt+C: fzf cd widget bindkey '^[c' fzf-cd-widget fi # FZF-tab completion (tab for fuzzy completion) # fzf-tab plugin handles completion menu automatically # Documented: All keybinds above are for fast navigation, editing, history, and fuzzy search # ===================== # Command-not-found handler (Arch/pkgfile) # ===================== if [ -f /usr/share/doc/pkgfile/command-not-found.zsh ]; then source /usr/share/doc/pkgfile/command-not-found.zsh fi # ===================== # End of .zshrc # =====================