diff --git a/zsh/.config/zsh/aliases.zsh b/zsh/.config/zsh/aliases.zsh index 494fe0e..8b962e5 100644 --- a/zsh/.config/zsh/aliases.zsh +++ b/zsh/.config/zsh/aliases.zsh @@ -1,58 +1,77 @@ -# General aliases +#!/usr/bin/env zsh +# Modern shell aliases and functions + +# Navigation shortcuts alias grep="grep --color=auto" alias ..="cd .." alias ...="cd ../.." alias ....="cd ../../.." alias .....="cd ../../../.." +alias -- -='cd -' +alias md='mkdir -p' +alias rd='rmdir' -# Use Neovim if available -if command -v nvim >/dev/null; then - alias v='nvim' +# Modern directory management +mkcd() { [[ -z "$1" ]] && { echo "Usage: mkcd "; return 1 }; mkdir -p "$1" && cd "$1" } +cd..() { local count="${1:-1}"; for ((i=0; i/dev/null; then +# Modern development tools +command -v nvim &>/dev/null && alias v='nvim' +command -v code &>/dev/null && alias vs='code .' +command -v lazydocker &>/dev/null && alias lzd='lazydocker' +command -v lazygit &>/dev/null && alias lzg='lazygit' +command -v kubectl &>/dev/null && alias k='kubectl' +command -v terraform &>/dev/null && alias tf='terraform' +command -v make &>/dev/null && alias m='make' + +# Docker aliases +if command -v docker &>/dev/null; then + alias d='docker' + alias dc='docker-compose' + alias dce='docker-compose exec' + alias dcb='docker-compose build' + alias dcd='docker-compose down' + alias dcu='docker-compose up' +fi + +# Enhanced ls (eza) +if command -v eza &>/dev/null; then alias ls='eza --group-directories-first --color=auto' alias la='eza -a --group-directories-first --color=auto' alias ll='eza -lh --group-directories-first --color=auto' alias lla='eza -la --group-directories-first --color=auto' - alias l='eza --classify' alias lt='eza -lt modified --sort newest' - alias lS='eza -lS --group-directories-first --color=auto' alias tree='eza --tree --level=5' - alias lg='eza --git' + alias lg='eza -lg --git --group-directories-first' +else + # Fallback to ls + alias ls='ls --color=auto' + alias la='ls -A --color=auto' + alias ll='ls -lh --color=auto' + alias lla='ls -lAh --color=auto' fi -# Bat for pretty `cat` and help -if command -v bat >/dev/null; then - # Define a function instead of aliasing inside same unit - function cat() { - command bat --paging=never "$@" - } - - function bathelp() { - bat --plain --language=help - } - - function help() { - "$@" --help 2>&1 | bathelp - } - - # Global aliases for help text +# Enhanced cat (bat) +if command -v bat &>/dev/null; then + cat() { command bat --paging=never "$@"; } + bathelp() { bat --plain --language=help; } + help() { "$@" --help 2>&1 | bathelp; } alias -g ':h'='-h 2>&1 | bat --language=help --style=plain' alias -g ':help'='--help 2>&1 | bat --language=help --style=plain' + alias catp='bat --style=plain' +else + # Fallback functions if bat not available + help() { "$@" --help 2>&1 | less; } + alias -g ':h'='-h 2>&1 | less' + alias -g ':help'='--help 2>&1 | less' fi -# Use trash instead of rm on non-Windows systems -if [[ "$(uname -s)" != MINGW* && "$(uname -s)" != CYGWIN* ]]; then - alias rm='trash' -fi - -# Dev tools -alias lzd='lazydocker' -alias v='nvim' # This can be overridden in check_aliases if nvim doesn't exist - -# Git aliases +# Modern Git aliases alias gs='git status' alias gc='git commit' alias gcm='git commit -m' @@ -63,4 +82,75 @@ alias gp='git push' alias gl='git log --oneline --graph --decorate' alias gi='git init' alias gcl='git clone' +alias ga='git add' +alias gaa='git add -A' +alias gd='git diff' +alias gds='git diff --staged' +alias gsh='git stash' +alias gsp='git stash pop' +alias gr='git restore' +alias grs='git restore --staged' +alias gclean='git clean -fd' +# Enhanced Git functions +clone() { + if [[ $# -eq 1 ]]; then + git clone "$1" + cd "$(basename "$1" .git)" 2>/dev/null || cd "$(basename "$1")" + else + git clone "$@" + fi +} + +# Safe rm with trash (when available) +if [[ "$_OS_TYPE" != MINGW* && "$_OS_TYPE" != CYGWIN* ]] && command -v trash &>/dev/null; then + alias rm='trash' + alias rrm='/bin/rm' +else + alias rrm='/bin/rm' +fi + +# Enhanced file operations with safety +alias cp='cp -i' +alias mv='mv -i' +alias ln='ln -i' + +# System utilities +alias df='df -h' +alias du='du -h' +alias dus='du -sh' +alias free='free -h' +alias ps='ps aux' +alias psg='ps aux | grep' +alias top='htop' 2>/dev/null || alias top='top' + +# Network utilities +alias ping='ping -c 4' +alias ports='netstat -tuln' 2>/dev/null || alias ports='netstat -an' +alias ipinfo='curl ipinfo.io' + +# Weather functions +alias wt='curl wttr.in' +wti() { + [[ -z "$1" ]] && { echo "Usage: wti "; return 1 } + curl "wttr.in/$1?format=3" 2>/dev/null || { echo "Failed to fetch weather for $1"; return 1 } +} + +# Modern archive extraction +extract() { + [[ ! -f "$1" ]] && { echo "'$1' is not a valid file"; return 1 } + case "$1" in + *.tar.bz2) tar xjf "$1" ;; + *.tar.gz) tar xzf "$1" ;; + *.bz2) bunzip2 "$1" ;; + *.rar) unrar x "$1" ;; + *.gz) gunzip "$1" ;; + *.tar) tar xf "$1" ;; + *.tbz2) tar xjf "$1" ;; + *.tgz) tar xzf "$1" ;; + *.zip) unzip "$1" ;; + *.Z) uncompress "$1" ;; + *.7z) 7z x "$1" ;; + *) echo "'$1' cannot be extracted via extract()" ;; + esac +} diff --git a/zsh/.config/zsh/completion.zsh b/zsh/.config/zsh/completion.zsh index 2b3f5fa..f85dfc3 100644 --- a/zsh/.config/zsh/completion.zsh +++ b/zsh/.config/zsh/completion.zsh @@ -1,22 +1,127 @@ -# Homebrew setup and completions -if command -v brew &>/dev/null; then - export HOMEBREW_PREFIX="$(brew --prefix)" - eval "$("${HOMEBREW_PREFIX}/bin/brew" shellenv)" +#!/usr/bin/env zsh +# Modern Zsh completion configuration - # Add site-functions to FPATH for completions - FPATH="${HOMEBREW_PREFIX}/share/zsh/site-functions:${FPATH}" +# Cache directories for performance +typeset -g cache_dir="${XDG_CACHE_HOME:-$HOME/.cache}/zsh" +typeset -g compdump="${ZDOTDIR:-$HOME}/.zsh/.zcompdump-${ZSH_VERSION}" + +# Create cache directory if needed +if [[ ! -d "$cache_dir" ]]; then + mkdir -p "$cache_dir" 2>/dev/null || { + cache_dir="/tmp/zsh-cache-$USER" + mkdir -p "$cache_dir" 2>/dev/null + } fi -# zcompdump cache -mkdir -p "$HOME/.zsh/cache" -ZSH_COMPDUMP="${ZDOTDIR:-$HOME}/.zcompdump" -zstyle ':completion::complete:*' use-cache on -zstyle ':completion::complete:*' cache-path "$HOME/.zsh/cache" - -# Load compinit safely -if [[ -z "$_compinit_done" ]]; then - autoload -Uz compinit - compinit -C -d "$ZSH_COMPDUMP" - _compinit_done=1 +# Add custom completion directories +if [[ -z "$_COMPLETION_PATHS_CACHED" ]]; then + [[ -d "${ZDOTDIR:-$HOME}/.zsh/completions" ]] && fpath=("${ZDOTDIR:-$HOME}/.zsh/completions" $fpath) + export _COMPLETION_PATHS_CACHED=1 fi +# Homebrew completion paths +if [[ -d "/opt/homebrew/share/zsh/site-functions" ]] || [[ "${HOMEBREW_PREFIX-}" == "/opt/homebrew" ]]; then + fpath=(${fpath:#/usr/local/share/zsh/site-functions}) +fi + +if [[ -n "${HOMEBREW_PREFIX-}" && -d "$HOMEBREW_PREFIX/share/zsh/site-functions" ]]; then + fpath=("$HOMEBREW_PREFIX/share/zsh/site-functions" $fpath) +fi + +# Silence completion warnings +ZSH_DISABLE_COMPFIX=true + +# Initialize completion system +autoload -Uz compinit + +# Ensure compdump parent directory exists +if [[ -n "$compdump" ]]; then + mkdir -p "${compdump:h}" 2>/dev/null +fi + +# Initialize completion using cached compdump; -C skips expensive security checks +compinit -i -C -d "$compdump" + +# Background compilation for performance +{ + [[ -s "$compdump" && ( ! -s "${compdump}.zwc" || "$compdump" -nt "${compdump}.zwc" ) ]] && \ + zcompile "$compdump" 2>/dev/null +} &! + +# Modern completion styles +zstyle ':completion:*' menu select # Interactive menu +zstyle ':completion:*' group-name '' # Group by type +zstyle ':completion:*' verbose no # Detailed descriptions +zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}" # Use LS_COLORS +zstyle ':completion:*' use-cache on # Enable caching +zstyle ':completion:*' cache-path "$cache_dir" # Cache location +zstyle ':completion:*' accept-exact '*(N)' # Accept exact matches +zstyle ':completion:*' use-compctl false # Disable deprecated system +zstyle ':completion:*' max-errors 2 # Error tolerance +zstyle ':completion:*' accept-exact-dirs true # Directory completion +zstyle ':completion:*' recent-dirs insert both # Recent directories +zstyle ':completion:*' squeeze-slashes true # Multiple slashes as one +zstyle ':completion:*' special-dirs true # Include . and .. +zstyle ':completion:*' file-patterns '%p(^-/):globbed-files *(-/):directories *:all-files' + +# Case-insensitive, partial-word, substring completion +zstyle ':completion:*' matcher-list \ + 'm:{a-zA-Z}={A-Za-z}' \ + 'r:|[._-]=* r:|=*' \ + 'l:|=* r:|=*' + +# fzf-tab configuration +zstyle ':fzf-tab:*' fzf-command fzf +zstyle ':fzf-tab:*' switch-group ',' '.' +zstyle ':fzf-tab:*' continuous-trigger '/' +zstyle ':fzf-tab:*' fzf-bindings 'tab:accept' +zstyle ':fzf-tab:*' accept-line enter + +# Disable default group colors that show format codes +zstyle ':fzf-tab:*' show-group full +zstyle ':fzf-tab:*' prefix '' + +# Preview for files and directories +zstyle ':fzf-tab:complete:cd:*' fzf-preview 'ls -1 --color=always $realpath 2>/dev/null' +zstyle ':fzf-tab:complete:ls:*' fzf-preview 'ls -1 --color=always $realpath 2>/dev/null' + +# Better fzf flags +zstyle ':fzf-tab:*' fzf-flags --height=50% --layout=reverse --info=inline + +# Process completion for kill commands +zstyle ':completion:*:*:*:*:processes' command "ps -u $USER -o pid,user,comm -w -w" +zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#) ([0-9a-z-]#)*=01;34=0=01' +zstyle ':completion:*:*:kill:*' menu yes select +zstyle ':completion:*:*:kill:*' force-list always +zstyle ':completion:*:*:kill:*' insert-ids single + +# Filter out system users and unwanted patterns +zstyle ':completion:*:*:*:users' ignored-patterns \ + adm amanda apache at avahi avahi-autoipd beaglidx bin cacti canna \ + clamav daemon dbus distcache dnsmasq dovecot fax ftp games gdm \ + gkrellmd gopher hacluster haldaemon halt hsqldb ident junkbust kdm \ + ldap lp mail mailman mailnull man messagebus mldonkey mysql nagios \ + named netdump news nfsnobody nobody nscd ntp nut nx obsrun openvpn \ + operator pcap polkitd postfix postgres privoxy pulse pvm quagga radvd \ + rpc rpcuser rpm rtkit scard shutdown squid sshd statd svn sync tftp \ + usbmux uucp vcsa wwwrun xfs '_*' + +zstyle ':completion:*:complete:-command-:*' ignored-patterns '*\~' +zstyle ':completion:*:functions' ignored-patterns '_*' +zstyle ':completion:*:parameters' ignored-patterns 'ZINIT*' +zstyle ':completion:*:variables' ignored-patterns 'ZINIT*' + +# Disable hostname completion and configure manual pages +zstyle ':completion:*:hosts' hosts off +zstyle ':completion:*:manuals' separate-sections true +zstyle ':completion:*:manuals.(^1*)' insert-sections true +zstyle ':completion:*:cd:*' ignore-parents parent pwd + +# Use faster process listing commands +zstyle ':completion:*:*:kill:*:processes' command 'ps -eo pid,user,comm --no-headers' +zstyle ':completion:*:processes' command 'ps -eo pid,user,comm --no-headers' + +# Include hidden files in completion +setopt globdots +_comp_options+=(globdots) + diff --git a/zsh/.config/zsh/external.zsh b/zsh/.config/zsh/external.zsh index 885d1b3..ac22fee 100644 --- a/zsh/.config/zsh/external.zsh +++ b/zsh/.config/zsh/external.zsh @@ -1,32 +1,131 @@ -# Starship prompt -export STARSHIP_CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}/starship.toml" -eval "$(starship init zsh)" +#!/usr/bin/env zsh +# Modern external tool integrations with optimized lazy loading -# zoxide init -if command -v eza &>/dev/null; then - export _ZO_FZF_OPTS="--preview='eza -a --color=always {} | head -30' --preview-window=down:30%" -else - export _ZO_FZF_OPTS="--preview='ls -la {} | head -30' --preview-window=down:30%" +# Vanilla mode for dumb terminals (IDEs, Windsurf, etc.) +if [ "$TERM" = "dumb" ]; then + # Clean, standard prompt for IDE environments + export PS1="%n@%m %1~ %# " + # Disable most shell features for maximum compatibility + unsetopt prompt_cr prompt_sp prompt_subst + setopt no_prompt_cr no_prompt_sp no_prompt_subst + # Skip loading external tools in vanilla mode + return 0 fi -eval "$(zoxide init --cmd cd zsh)" -# pyenv -if command -v pyenv 1>/dev/null 2>&1; then +# direnv (must be before starship) +if command -v direnv &>/dev/null; then + eval "$(direnv hook zsh)" +fi + +# starship +if command -v starship &>/dev/null; then + export STARSHIP_CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}/starship.toml" + eval "$(starship init zsh)" +fi + +# Lazy load zoxide for smart directory navigation +if command -v zoxide &>/dev/null; then + eval "$(zoxide init --cmd cd zsh)" +fi + +# Lazy load pyenv (Python version management) +if command -v pyenv &>/dev/null; then export PYENV_ROOT="$HOME/.pyenv" - [[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH" - eval "$(pyenv init -)" + pyenv() { + unset -f pyenv + eval "$(command pyenv init -)" + pyenv "$@" + } fi -# direnv -command -v direnv &>/dev/null && eval "$(direnv hook zsh)" +[[ -o interactive ]] || return 0 -# conda (OFFICIAL – preferred over manual conda.sh sourcing) -if [ -f "/opt/homebrew/Caskroom/miniforge/base/bin/conda" ]; then - eval "$(/opt/homebrew/Caskroom/miniforge/base/bin/conda shell.zsh hook)" +__safe_unset() { + for f in "$@"; do + whence -w "$f" &>/dev/null && unset -f "$f" + done +} - # Manually assign the conda completion function to mamba - if type mamba &>/dev/null && type _conda &>/dev/null; then - compdef _conda mamba - fi +if command -v micromamba &>/dev/null; then + micromamba() { + __safe_unset micromamba conda mamba + eval "$(command micromamba shell hook -s zsh)" || return 1 + micromamba "$@" + } +elif command -v mamba &>/dev/null; then + mamba() { + __safe_unset mamba conda + eval "$(command mamba shell hook --shell zsh)" || return 1 + mamba "$@" + } + + # conda is optional fallback + if command -v conda &>/dev/null; then + conda() { + __safe_unset conda mamba + eval "$(command conda shell.zsh hook)" || return 1 + conda "$@" + } + fi +elif command -v conda &>/dev/null; then + conda() { + __safe_unset conda + eval "$(command conda shell.zsh hook)" || return 1 + conda "$@" + } +fi + +# Node.js environment setup +if command -v node &>/dev/null; then + typeset -g node_path_cache="${XDG_CACHE_HOME:-$HOME/.cache}/zsh/node_path" + if [[ -r "$node_path_cache" ]]; then + export NODE_PATH="$(<"$node_path_cache")" + else + { + local npm_prefix + npm_prefix="$(npm config get prefix 2>/dev/null)" || return 0 + mkdir -p "${node_path_cache:h}" 2>/dev/null + print -r -- "${npm_prefix}/lib/node_modules" >| "$node_path_cache" + } &! + fi +fi + +# Modern Rust toolchain (if present) +if command -v rustc &>/dev/null; then + export CARGO_HOME="${CARGO_HOME:-$HOME/.cargo}" + path=("$CARGO_HOME/bin" $path) +fi + +# Go environment (modern setup) +if command -v go &>/dev/null; then + export GOPATH="${GOPATH:-$HOME/.go}" + path=("$GOPATH/bin" $path) +fi + +# Modern Ruby environment (if present) +if command -v ruby &>/dev/null && command -v gem &>/dev/null; then + export GEM_HOME="${GEM_HOME:-$HOME/.gem}" + path=("$GEM_HOME/bin" $path) +fi + +# Modern Java environment (if present) +if command -v java &>/dev/null; then + export JAVA_HOME="${JAVA_HOME:-$(/usr/libexec/java_home 2>/dev/null)}" +fi + +# Modern development environment variables +export EDITOR="${EDITOR:-nvim}" +export BROWSER="${BROWSER:-open}" +export PAGER="${PAGER:-less -i -N -S -R}" + +# Modern application-specific settings +if command -v fzf &>/dev/null; then + export FZF_DEFAULT_OPTS="--height 40% --layout=reverse --border --inline-info" + export FZF_DEFAULT_COMMAND="fd --type f --hidden --follow --exclude .git" +fi + +# Modern terminal integration +if [[ -n "$TMUX" ]]; then + export TERM="xterm-256color-italic" fi diff --git a/zsh/.config/zsh/plugins.zsh b/zsh/.config/zsh/plugins.zsh index 2be8ba7..57bc498 100644 --- a/zsh/.config/zsh/plugins.zsh +++ b/zsh/.config/zsh/plugins.zsh @@ -1,40 +1,78 @@ -# ~/.config/zsh/plugins.zsh +#!/usr/bin/env zsh +# Modern Zinit plugin manager configuration -# Zinit setup -ZINIT_HOME="${XDG_DATA_HOME:-${HOME}/.local/share}/zinit/zinit.git" -[[ ! -d "$ZINIT_HOME" ]] && git clone https://github.com/zdharma-continuum/zinit.git "$ZINIT_HOME" -source "${ZINIT_HOME}/zinit.zsh" +# Zinit installation and setup +local zinit_dir="${XDG_DATA_HOME:-${HOME}/.local/share}/zinit/zinit.git" -# Core plugins -zinit light zsh-users/zsh-completions +# Install Zinit if not present +if [[ ! -d "$zinit_dir" ]]; then + mkdir -p "$zinit_dir" 2>/dev/null || { + print -P "%F{red}Error: Cannot create zinit directory%f" >&2 + return 1 + } + git clone --depth 1 https://github.com/zdharma-continuum/zinit.git "$zinit_dir" 2>/dev/null || { + print -P "%F{red}Error: Failed to clone zinit%f" >&2 + return 1 + } +fi -# Ollama CLI completion -zinit ice as"completion" -zinit snippet https://raw.githubusercontent.com/Katrovsky/zsh-ollama-completion/main/_ollama +# Load Zinit +if [[ -f "$zinit_dir/zinit.zsh" ]]; then + source "$zinit_dir/zinit.zsh" + autoload -Uz _zinit + (( ${+_comps} )) && _comps[zinit]=_zinit +else + print -P "%F{red}Error: Zinit not found%f" >&2 + return 1 +fi -# Syntax highlighting -zinit ice wait lucid atinit"ZSH_HIGHLIGHT_HIGHLIGHTERS=(main brackets pattern)" -zinit load zsh-users/zsh-syntax-highlighting +# Modern plugin loading with optimized performance -# Autosuggestions -zinit ice wait lucid atload"zle-line-init() { zle autosuggest-enable }; zle -N zle-line-init" -zinit load zsh-users/zsh-autosuggestions +# Essential plugins - loaded immediately +zinit wait'0' lucid for \ + zsh-users/zsh-autosuggestions -# History search -zinit light zsh-users/zsh-history-substring-search -zinit load zdharma-continuum/history-search-multi-word +zinit wait'1' lucid atload' + bindkey "$terminfo[kcuu1]" history-search-multi-word + bindkey "$terminfo[kcud1]" history-search-multi-word +' for \ + zdharma-continuum/history-search-multi-word -# FZF and extras -zinit ice from"gh-r" as"program" pick"bin/fzf" -zinit light junegunn/fzf-bin -zinit light junegunn/fzf-git.sh +# FZF integration +zinit wait'2' lucid from"gh-r" as"program" pick"bin/fzf" for \ + junegunn/fzf-bin -zinit ice wait lucid blockf -zinit load Aloxaf/fzf-tab +zinit wait'2a' lucid for \ + junegunn/fzf-git.sh -zinit ice from"gh-r" as"program" pick"bin/zoxide" -zinit load ajeetdsouza/zoxide +zinit wait'2b' lucid for \ + Aloxaf/fzf-tab -# Update alias +zinit wait'0' lucid for \ + zdharma-continuum/fast-syntax-highlighting + + +# Modern terminal keybindings +if [[ "$TERM_PROGRAM" == "vscode" || "$TERM_PROGRAM" == "windsurf" ]]; then + # Simplified bindings for IDE terminals + bindkey '^[[A' history-search-backward + bindkey '^[[B' history-search-forward + bindkey '^?' backward-delete-char + bindkey '^W' backward-kill-word +else + # Full terminal application mode + [[ -n "$terminfo[kcuf1]" ]] && bindkey "$terminfo[kcuf1]" forward-char + [[ -n "$terminfo[kcub1]" ]] && bindkey "$terminfo[kcub1]" backward-char +fi + +# Zinit management aliases alias zupdate='zinit update --all' +alias zreport='zinit report' + +# Plugin management helper functions +zls() { zinit list --installed } +zreload() { + zinit reload + print -P "%F{green}Zsh configuration reloaded%f" +} diff --git a/zsh/.fzf.zsh b/zsh/.fzf.zsh index b3509b4..4261f1a 100755 --- a/zsh/.fzf.zsh +++ b/zsh/.fzf.zsh @@ -1,28 +1,44 @@ #!/usr/bin/env zsh +# FZF configuration -# Indicate the shell explicitly -export FZF_SHELL="zsh" +# Skip if already loaded +[[ -n "$_FZF_LOADED" ]] && return 0 -# Ensure fzf is installed and get its path -if command -v fzf >/dev/null; then - export FZF_PATH="$(dirname "$(command -v fzf)")" -else - export FZF_PATH="" +# Check if FZF is available +if ! command -v fzf &>/dev/null; then + return 0 fi -# Load fzf key bindings and completion for zsh -if command -v fzf >/dev/null; then - [ -f "$FZF_PATH/key-bindings.zsh" ] && . "$FZF_PATH/key-bindings.zsh"] - [ -f "$FZF_PATH/completion.zsh" ] && . "$FZF_PATH/completion.zsh"] +# Configure for VSCode/Windsurf integrated terminals +if [[ "$TERM_PROGRAM" == "vscode" || "$TERM_PROGRAM" == "windsurf" ]]; then + export FZF_DEFAULT_OPTS="--height 40% --reverse --border" + export _FZF_LOADED=1 + return 0 fi -# Load fzf theme if available -FZF_THEME_SCRIPT="$HOME/.local/bin/scripts/fzf_theme.sh" -if [[ -f "$FZF_THEME_SCRIPT" ]]; then - # If theme script is available, use it and add the default fzf options - export FZF_DEFAULT_OPTS="$($FZF_THEME_SCRIPT) --height 40% --layout=reverse --border" -else - # Set default options for fzf without any theme, with preview enabled for general use - export FZF_DEFAULT_OPTS="--height 40% --layout=reverse --border" +# Configure FZF options for regular terminals +export FZF_DEFAULT_OPTS="--height 40% --layout=reverse --border --cycle" + +# Use fd for faster file searching if available +if command -v fd &>/dev/null; then + export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git' + export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND" + export FZF_ALT_C_COMMAND='fd --type d --hidden --follow --exclude .git' fi +# Load FZF key bindings and completion +if [[ -n "${HOMEBREW_PREFIX}" && -d "${HOMEBREW_PREFIX}/opt/fzf/shell" ]]; then + source "${HOMEBREW_PREFIX}/opt/fzf/shell/key-bindings.zsh" 2>/dev/null + source "${HOMEBREW_PREFIX}/opt/fzf/shell/completion.zsh" 2>/dev/null +elif FZF_PATH="$(dirname "$(command -v fzf)" 2>/dev/null)"; then + [[ -f "$FZF_PATH/key-bindings.zsh" ]] && source "$FZF_PATH/key-bindings.zsh" + [[ -f "$FZF_PATH/completion.zsh" ]] && source "$FZF_PATH/completion.zsh" +fi + +# Apply custom theme if available +if [[ -f "$HOME/.local/bin/scripts/fzf_theme.sh" ]]; then + FZF_THEME="$($HOME/.local/bin/scripts/fzf_theme.sh)" + export FZF_DEFAULT_OPTS="$FZF_THEME $FZF_DEFAULT_OPTS" +fi + +export _FZF_LOADED=1 \ No newline at end of file diff --git a/zsh/.zprofile b/zsh/.zprofile index 7ae0fbc..eaf1528 100755 --- a/zsh/.zprofile +++ b/zsh/.zprofile @@ -1,37 +1,10 @@ #!/usr/bin/env zsh +# ~/.zprofile - Login shell configuration (runs once per login) -# ── Brew shellenv ─────────────────────────────────────── -if command -v brew &>/dev/null; then - export PATH="/opt/homebrew/bin:${PATH}" - eval "$(/opt/homebrew/bin/brew shellenv)" -fi - -# ── Add Homebrew curl to PATH if installed ───────────── -if command -v brew &>/dev/null && brew list curl &>/dev/null; then - CURL_PATH="$(brew --prefix curl)/bin" - [[ ":$PATH:" != *":$CURL_PATH:"* ]] && export PATH="$CURL_PATH:$PATH" -fi - -# ── Add FZF path to PATH ─────────────────────────────── -if command -v fzf &>/dev/null; then - if command -v brew &>/dev/null; then - FZF_PATH="$(brew --prefix fzf)/bin" - else - FZF_PATH="$(dirname "$(command -v fzf)")" - fi - [[ ":$PATH:" != *":$FZF_PATH:"* ]] && export PATH="$FZF_PATH:$PATH" -fi - -# ── Add TeX to PATH (macOS specific) ─────────────────── -[[ -d "/Library/TeX/texbin" ]] && export PATH="/Library/TeX/texbin:$PATH" - -# ── Zsh completion fpath for brew and other packages ── -# Add Homebrew’s zsh completions if they exist -BREW_ZSH_FUNCTIONS="$(brew --prefix 2>/dev/null)/share/zsh/site-functions" -if [[ -d "$BREW_ZSH_FUNCTIONS" ]]; then - fpath=("$BREW_ZSH_FUNCTIONS" $fpath) -fi - -# Optional: Add your own completions directory -[[ -d "$HOME/.zsh/site-functions" ]] && fpath=("$HOME/.zsh/site-functions" $fpath) +# Homebrew initialization is handled in .zshenv for VSCode/IDE compatibility +# This file is for login-specific configuration only +# Add custom completion directories to fpath +# Uncomment the directory that exists on your system: +# [[ -d "$HOME/.zsh/site-functions" ]] && fpath=("$HOME/.zsh/site-functions" $fpath) +# [[ -d "$HOME/.zsh/completions" ]] && fpath=("$HOME/.zsh/completions" $fpath) \ No newline at end of file diff --git a/zsh/.zshenv b/zsh/.zshenv index 5f37713..40a7166 100755 --- a/zsh/.zshenv +++ b/zsh/.zshenv @@ -1,93 +1,82 @@ #!/usr/bin/env zsh +# ~/.zshenv - Environment variables and PATH (loaded for all shells) -# ------------------ Environment Setup ------------------ +# XDG base directory specification export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}" export XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}" +# Default programs export PAGER="less -i -N -S -R" export EDITOR="nvim" -export BROWSER="/Applications/Zen.app/Contents/MacOS/zen" -# ------------------ Helper Functions ------------------ +# Ensure PATH entries are unique (use zsh's path array) +typeset -U path + +# Helper function to safely add directories to PATH safe_path_add() { - [[ -d "$1" && ":$PATH:" != *":$1:"* ]] && export PATH="$1:$PATH" + [[ -d "$1" ]] || return 0 + (( ${path[(Ie)$1]} )) || path=("$1" $path) } -# ------------------ Platform Detection ------------------ -OS_TYPE="$(uname -s)" -ARCH="$(uname -m)" +# Cache platform detection to avoid repeated uname calls +export _OS_TYPE="${_OS_TYPE:-$(uname -s)}" +export _ARCH="${_ARCH:-$(uname -m)}" -# ------------------ macOS Setup ------------------ -# macOS Homebrew and Toolchain Setup -if [[ "$OS_TYPE" == "Darwin" ]]; then - if [[ "$ARCH" == "arm64" ]]; then - export HOMEBREW_PREFIX="/opt/homebrew" - else - export HOMEBREW_PREFIX="/usr/local" - fi +# Homebrew prefix (cheap detection; no brew invocation) +if [[ "$_OS_TYPE" == "Darwin" ]]; then + if [[ -x "/opt/homebrew/bin/brew" ]]; then + export HOMEBREW_PREFIX="/opt/homebrew" + elif [[ -x "/usr/local/bin/brew" ]]; then + export HOMEBREW_PREFIX="/usr/local" + fi +fi - safe_path_add "$HOMEBREW_PREFIX/bin" - safe_path_add "$HOMEBREW_PREFIX/sbin" +# Homebrew shellenv (Option A: interactive shells only) +if [[ -o interactive ]] && [[ -z "$_HOMEBREW_INITIALIZED" ]]; then + if [[ -n "${HOMEBREW_PREFIX-}" && -x "$HOMEBREW_PREFIX/bin/brew" ]]; then + eval "$("$HOMEBREW_PREFIX/bin/brew" shellenv)" + elif command -v brew &>/dev/null; then + eval "$(brew shellenv)" + fi + export _HOMEBREW_INITIALIZED=1 +fi - for dir in \ - "$HOMEBREW_PREFIX/opt/coreutils/libexec/gnubin" \ - "$HOMEBREW_PREFIX/opt/openssl@1.1/bin" \ - "$HOMEBREW_PREFIX/opt/llvm/bin" \ - "/Library/TeX/texbin" \ - "$HOMEBREW_PREFIX/opt/rustup/bin"; do - safe_path_add "$dir" - done -# ------------------ Linux Setup ------------------ -elif [[ "$OS_TYPE" == "Linux" ]]; then - safe_path_add "$HOME/.local/bin" - safe_path_add "$HOME/.cargo/bin" - safe_path_add "$HOME/.local/share/flatpak/exports/bin" - safe_path_add "/var/lib/flatpak/exports/bin" - [[ -d "/nix" ]] && safe_path_add "/nix/var/nix/profiles/default/bin" +# Set default browser based on platform +if [[ -z "$BROWSER" ]]; then + if [[ "$_OS_TYPE" == "Darwin" ]]; then + if [[ -f "/Applications/Zen.app/Contents/MacOS/zen" ]]; then + export BROWSER="/Applications/Zen.app/Contents/MacOS/zen" + elif [[ -f "/Applications/Safari.app/Contents/MacOS/Safari" ]]; then + export BROWSER="/Applications/Safari.app/Contents/MacOS/Safari" + fi + else + export BROWSER="$(command -v firefox || command -v google-chrome || command -v chromium)" + fi +fi - # ------------------ WSL Detection ------------------ - if grep -qEi "microsoft|wsl" /proc/version &>/dev/null; then - export IS_WSL=1 - export BROWSER="wslview" - export DISPLAY="${DISPLAY:-:0}" - export WSL_HOST="$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}')" - export NO_AT_BRIDGE=1 - safe_path_add "/mnt/c/Windows/System32" # useful for calling Windows commands from WSL - fi +# Development tool paths +export PYENV_ROOT="${PYENV_ROOT:-$HOME/.pyenv}" +export GOPATH="${GOPATH:-$HOME/.go}" - # ------------------ Remote Development Detection ------------------ - if [[ -n "$SSH_CONNECTION" ]]; then +# Add user and development tool directories to PATH +if [[ -n "${HOMEBREW_PREFIX-}" ]]; then + safe_path_add "$HOMEBREW_PREFIX/bin" + safe_path_add "$HOMEBREW_PREFIX/sbin" +fi +safe_path_add "$HOME/.local/bin" +safe_path_add "$HOME/.local/bin/scripts" +safe_path_add "$HOME/.antigravity/antigravity/bin" +safe_path_add "/Applications/Windsurf.app/Contents/Resources/app/bin" +safe_path_add "$PYENV_ROOT/bin" +safe_path_add "$GOPATH/bin" + +# Detect remote development environments +if [[ -n "$SSH_CONNECTION" ]]; then export IS_REMOTE=1 - fi +fi - if [[ -n "$CODESPACES" ]] || [[ -d "/workspaces" ]]; then +if [[ -n "$CODESPACES" ]] || [[ -d "/workspaces" ]]; then export IS_CODESPACES=1 safe_path_add "/workspaces/bin" - fi -fi - -# ------------------ Common PATH ------------------ -safe_path_add "$HOME/.local/bin/scripts" - -# ------------------ Language Toolchains ------------------ - -# Python (pyenv) -export PYENV_ROOT="$HOME/.pyenv" - -safe_path_add "$PYENV_ROOT/bin" -safe_path_add "$PYENV_ROOT/shims" - -# Go -if command -v go &>/dev/null; then - export GOPATH="${GOPATH:-$HOME/.go}" - safe_path_add "$GOPATH/bin" -fi - -# NVM -if [[ -d "$HOME/.nvm" ]]; then - export NVM_DIR="$HOME/.nvm" - [[ -s "$NVM_DIR/nvm.sh" ]] && . "$NVM_DIR/nvm.sh" - [[ -s "$NVM_DIR/zsh_completion" ]] && . "$NVM_DIR/bash_completion" -fi - +fi \ No newline at end of file diff --git a/zsh/.zshrc b/zsh/.zshrc index 7d4c9e9..c61b290 100755 --- a/zsh/.zshrc +++ b/zsh/.zshrc @@ -1,20 +1,40 @@ #!/usr/bin/env zsh +# ~/.zshrc - Interactive shell configuration -# Optional profiling -[[ -n $ZSH_DEBUGRC ]] && zmodload zsh/zprof +# Vanilla mode for dumb terminals (IDEs, Windsurf, etc.) +if [ "$TERM" = "dumb" ]; then + # Keep IDE shells as vanilla as possible, but still set a simple prompt. + typeset -g zsh_config_dir="${XDG_CONFIG_HOME:-$HOME/.config}/zsh" + source "$zsh_config_dir/external.zsh" + return 0 +fi -# Path cleanup -typeset -U PATH +# Performance profiling (run with: ZSH_PROFILE=1 zsh) +if [[ -n $ZSH_PROFILE ]]; then + zmodload zsh/zprof +fi -# Core config -source ~/.config/zsh/completion.zsh -source ~/.config/zsh/plugins.zsh -source ~/.config/zsh/aliases.zsh -source ~/.config/zsh/external.zsh +# Ensure unique PATH entries +typeset -U PATH path cdpath fpath manpath -# Editor for SSH -[[ -n ${SSH_CONNECTION} ]] && export EDITOR='vim' +# Load configuration modules in optimized order +typeset -g zsh_config_dir="${XDG_CONFIG_HOME:-$HOME/.config}/zsh" +source "$zsh_config_dir/external.zsh" +source "$zsh_config_dir/completion.zsh" +source "$zsh_config_dir/plugins.zsh" +source "$zsh_config_dir/aliases.zsh" -# Show zprof results if debugging -[[ -n $ZSH_DEBUGRC ]] && zprof +# FZF integration (load last for keybindings) +if [[ -f "$HOME/.fzf.zsh" ]]; then + source "$HOME/.fzf.zsh" +fi +# SSH environment fallback +[[ -n "$SSH_CONNECTION" && -z "$EDITOR" ]] && export EDITOR='vim' + +# Show profiling results +if [[ -n $ZSH_PROFILE ]]; then + zprof +fi +# Zoxide FZF theme colors (managed by theme-switcher) +export _ZO_FZF_OPTS="--height 40% --layout=reverse --border --preview-window=down:3:wrap --color=fg:#f8f8f2,bg:#2a2f3b,hl:#f92672,fg+:#f8f8f2,bg+:#49483e,hl+:#f92672,info:#a6e22e,prompt:#66d9ef,pointer:#f92672,marker:#a6e22e,spinner:#a6e22e,header:#66d9ef"