# Don't run on non-interactive shells. [[ $- != *i* ]] && return # ----------------------------- # User config # ----------------------------- export EDITOR="${EDITOR:-nvim}" export VISUAL="${VISUAL:-$EDITOR}" export PAGER="${PAGER:-less}" export LESS="-R -F -X -S" export CLICOLOR=1 export LSCOLORS="${LSCOLORS:-GxFxCxDxBxegedabagaced}" export LANG="${LANG:-en_US.UTF-8}" export LC_ALL="${LC_ALL:-en_US.UTF-8}" export EDITOR=nvim export VISUAL=nvim # ----------------------------- # Shell behavior / safety # ----------------------------- shopt -s globstar nullglob dotglob 2>/dev/null || true shopt -s histappend 2>/dev/null || true shopt -s cdspell 2>/dev/null || true shopt -s checkwinsize 2>/dev/null || true set -o notify set -o noclobber # ----------------------------- # History # ----------------------------- export HISTSIZE=100000 export HISTFILESIZE=200000 export HISTCONTROL=ignoreboth:erasedups export HISTIGNORE="ls:ll:la:pwd:cd:cd -:exit:clear" export HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S " PROMPT_COMMAND="history -a; history -n; ${PROMPT_COMMAND:-true}" # ----------------------------- # Path helpers # ----------------------------- path_prepend() { [[ -d "$1" ]] || return 0 case ":$PATH:" in *":$1:"*) ;; *) PATH="$1:$PATH" ;; esac } path_append() { [[ -d "$1" ]] || return 0 case ":$PATH:" in *":$1:"*) ;; *) PATH="$PATH:$1" ;; esac } # Common user bins path_prepend "$HOME/.local/bin" # ----------------------------- # Homebrew (macOS) # ----------------------------- eval "$(brew shellenv)" 2>/dev/null || true # ----------------------------- # bash-completion@2 (macOS / Homebrew) # ----------------------------- # Homebrew path varies by arch. if [[ -r "$(brew --prefix 2>/dev/null)/etc/profile.d/bash_completion.sh" ]]; then # shellcheck source=/dev/null source "$(brew --prefix)/etc/profile.d/bash_completion.sh" elif [[ -r "/usr/local/etc/profile.d/bash_completion.sh" ]]; then # shellcheck source=/dev/null source "/usr/local/etc/profile.d/bash_completion.sh" elif [[ -r "/opt/homebrew/etc/profile.d/bash_completion.sh" ]]; then # shellcheck source=/dev/null source "/opt/homebrew/etc/profile.d/bash_completion.sh" fi # ----------------------------- # mise (tool versions) # ----------------------------- if command -v mise >/dev/null 2>&1; then eval "$(mise activate bash)" 2>/dev/null || true fi # ----------------------------- # direnv (per-directory envs) # ----------------------------- if command -v direnv >/dev/null 2>&1; then eval "$(direnv hook bash)" 2>/dev/null || true fi # ----------------------------- # Git-friendly defaults # ----------------------------- export GIT_PAGER="${GIT_PAGER:-less -FRX}" export GIT_TERMINAL_PROMPT=1 # Better diff highlighting if installed if command -v delta >/dev/null 2>&1; then export GIT_PAGER="delta" fi # ----------------------------- # Prompt # ----------------------------- if command -v starship >/dev/null 2>&1; then # Initialize Starship eval "$(starship init bash)" else # Fallback: Simple native prompt if starship is missing PS1='\[\033[01;34m\]\w\[\033[00m\] \$ ' fi # ----------------------------- # Quality-of-life aliases # ----------------------------- alias ..='cd ..' alias ...='cd ../..' alias ....='cd ../../..' # Safer rm/mv/cp prompts alias rm='rm -i' alias mv='mv -i' alias cp='cp -i' # Better ls if command -v eza >/dev/null 2>&1; then alias ls='eza --group-directories-first' alias ll='eza -lah --git --group-directories-first' alias la='eza -a --group-directories-first' else alias ls='ls -G' alias ll='ls -lahG' alias la='ls -aG' fi command -v rg >/dev/null 2>&1 && alias grep='rg' command -v fd >/dev/null 2>&1 && alias find='fd' # ----------------------------- # Functions # ----------------------------- # extract: one command to unpack many formats extract() { [[ -f "$1" ]] || { echo "extract: '$1' is not a file" >&2; return 2; } case "$1" in *.tar.bz2) tar xjf "$1" ;; *.tar.gz) tar xzf "$1" ;; *.tar.xz) tar xJf "$1" ;; *.tar) tar xf "$1" ;; *.zip) unzip "$1" ;; *.gz) gunzip "$1" ;; *.bz2) bunzip2 "$1" ;; *.xz) unxz "$1" ;; *) echo "extract: don't know how to extract '$1'" >&2; return 3 ;; esac } # copy: copy to clipboard copy() { if [[ $# -gt 0 ]]; then pbcopy < "$1" else pbcopy fi }