# Officer — default shell configuration.
#
# Written when your Linux account was created. It is yours: edit it freely. Officer only ever writes this
# file if it is missing or still byte-for-byte identical to the template, so your changes survive every
# reprovision.
#
# Deliberately depends on nothing but zsh. Starship, eza, nvim and bun are each used only if present, so
# this same file works on a minimal server and on a fully equipped one.

# ── PATH ──
# $HOME-relative throughout. Anything hard-coded to one person's home is a template that only works for
# them, which is how the owner's own .zshrc grew three absolute paths.
export PATH="$HOME/bin:$HOME/.local/bin:/usr/local/bin:$PATH"
[ -d "$HOME/.bun/bin" ] && export PATH="$HOME/.bun/bin:$PATH"
[ -d "$HOME/.deno/bin" ] && export PATH="$HOME/.deno/bin:$PATH"
[ -d "$HOME/.cargo/bin" ] && export PATH="$HOME/.cargo/bin:$PATH"
[ -d "$HOME/.opencode/bin" ] && export PATH="$HOME/.opencode/bin:$PATH"
[ -d /opt/nvim-linux-x86_64/bin ] && export PATH="$PATH:/opt/nvim-linux-x86_64/bin"

# ── History ──
# The bits oh-my-zsh would otherwise be pulled in to provide. Shared across concurrent shells, which
# matters here: a browser tab and an SSH session are often the same person in the same directory.
HISTFILE="$HOME/.zsh_history"
HISTSIZE=50000
SAVEHIST=50000
setopt SHARE_HISTORY          # write and read as you go, not only at exit
setopt HIST_IGNORE_ALL_DUPS   # keep one copy of a repeated command
setopt HIST_IGNORE_SPACE      # a leading space keeps it out of history
setopt HIST_REDUCE_BLANKS
setopt EXTENDED_HISTORY       # timestamps

# ── Directories and globbing ──
setopt AUTO_CD                # `..` and bare directory names change directory
setopt AUTO_PUSHD             # every cd pushes, so `cd -<TAB>` is a menu
setopt PUSHD_IGNORE_DUPS
setopt EXTENDED_GLOB
setopt INTERACTIVE_COMMENTS   # `#` works when pasting a commented command

# ── Completion ──
autoload -Uz compinit
# Cache the dump in the account's own home; -C skips the security check on a dump written today, which is
# the difference between an instant prompt and a visible pause on every new shell.
compinit -d "$HOME/.zcompdump"
zstyle ':completion:*' menu select
zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}'   # case-insensitive
zstyle ':completion:*' list-colors ''
setopt COMPLETE_IN_WORD
setopt ALWAYS_TO_END

# ── Keys ──
# Emacs bindings explicitly: with EDITOR=nvim zsh would otherwise pick vi mode, which surprises anyone who
# did not ask for it.
bindkey -e
autoload -Uz up-line-or-beginning-search down-line-or-beginning-search
zle -N up-line-or-beginning-search
zle -N down-line-or-beginning-search
bindkey '^[[A' up-line-or-beginning-search    # Up: history matching what is already typed
bindkey '^[[B' down-line-or-beginning-search
bindkey '^[[1;5C' forward-word                # ctrl-arrow by word
bindkey '^[[1;5D' backward-word
bindkey '^[[3~' delete-char
bindkey '^[[H' beginning-of-line
bindkey '^[[F' end-of-line

# ── Editor ──
if command -v nvim >/dev/null 2>&1; then
  export EDITOR=nvim VISUAL=nvim SUDO_EDITOR=nvim
  alias n='nvim'
  alias vim='nvim'
elif command -v vim >/dev/null 2>&1; then
  export EDITOR=vim VISUAL=vim
fi

# ── Aliases ──
if command -v eza >/dev/null 2>&1; then
  alias ls='eza --group-directories-first'
  alias ll='eza -l --group-directories-first --git'
  alias la='eza -la --group-directories-first --git'
  alias lt='eza --tree --level=2'
else
  alias ls='ls --color=auto --group-directories-first'
  alias ll='ls -lh'
  alias la='ls -lah'
fi
alias grep='grep --color=auto'
alias ..='cd ..'
alias ...='cd ../..'
alias sz='source "$HOME/.zshrc"'
command -v duf >/dev/null 2>&1 && alias duf='duf --only local'
command -v lazygit >/dev/null 2>&1 && alias lg='lazygit'

# ── Prompt ──
# Starship if it is installed; zsh's own prompt with the same information if not. The fallback exists
# because a shell that opens with a broken prompt reads as a broken machine, and a minimal install has
# every right not to have starship on it.
if command -v starship >/dev/null 2>&1; then
  eval "$(starship init zsh)"
else
  autoload -Uz vcs_info
  precmd_vcs_info() { vcs_info }
  precmd_functions+=( precmd_vcs_info )
  zstyle ':vcs_info:git:*' formats ' %F{blue}%b%f'
  setopt PROMPT_SUBST
  PROMPT='%F{green}%n%f@%F{yellow}%m%f:[%~${vcs_info_msg_0_}]
%F{blue}❯%f '
fi

# ── Postgres ──
# Officer gave your account a Postgres role named the same as your login, and a ~/.pgpass holding its
# password — so psql never prompts you and you never have to know it.
#
#   createdb myapp        as many as you like; each one is yours
#   psql myapp            connect to one
#   dropdb myapp
#
# Nobody else can read your data, and you cannot reach Officer's own database.
#
# Nothing is set here. PGHOST, PGPORT, PGUSER and PGPASSWORD are in ~/.zshenv, which zsh reads before
# this file and for non-interactive shells too — so scripts and agents get them as well. That is also
# where to look if you want to read your own password; `cat ~/.zshenv`.
#
# PGHOST matters more than it looks: Postgres runs in a container published on loopback, so there is no
# unix socket on this machine, and without it psql fails with "No such file or directory" — which reads
# like Postgres is not installed rather than like it is one flag away.

# ── Docker ──
# Your own rootless daemon, if Officer provisioned one — Developer accounts get one. Containers you start
# run as your account in your own user namespace: root inside them is you outside them, and you cannot see
# anyone else's containers.
#
# Bind mounts belong under ~/.local/dockers. A container's inner uid is neither you nor Officer, so it
# needs traversal that only that directory grants; elsewhere in your home it will be denied.
#
# Set from $XDG_RUNTIME_DIR rather than a hard-coded uid so this line is the same in every account's file.
if [ -S "${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/docker.sock" ]; then
  export DOCKER_HOST="unix://${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/docker.sock"
fi

# ── Your own additions ──
# Sourced last so anything here wins. Officer never writes to it, so it is the safe place for your own
# configuration — and it is why this file can be replaced by a newer template without losing your work.
[ -f "$HOME/.zshrc.local" ] && source "$HOME/.zshrc.local"

# Tool-installed completions and env, if they exist. Each of these appends itself to a shell rc when you
# install the tool; sourcing them conditionally keeps that working without hard-coding anyone's home.
[ -s "$HOME/.bun/_bun" ] && source "$HOME/.bun/_bun"
[ -s "$HOME/.deno/env" ] && source "$HOME/.deno/env"
[ -f "$HOME/.cargo/env" ] && source "$HOME/.cargo/env"
