diff --git a/config/agnoster.zsh-theme b/config/agnoster.zsh-theme deleted file mode 100644 index 7bbcebf..0000000 --- a/config/agnoster.zsh-theme +++ /dev/null @@ -1,183 +0,0 @@ -# vim:ft=zsh ts=2 sw=2 sts=2 -# -# agnoster's Theme - https://gist.github.com/3712874 -# A Powerline-inspired theme for ZSH - -### Segment drawing -CURRENT_BG='NONE' - -case ${SOLARIZED_THEME:-dark} in - light) - CURRENT_FG=${CURRENT_FG:-'white'} - CURRENT_DEFAULT_FG=${CURRENT_DEFAULT_FG:-'white'} - ;; - *) - CURRENT_FG=${CURRENT_FG:-'black'} - CURRENT_DEFAULT_FG=${CURRENT_DEFAULT_FG:-'default'} - ;; -esac - -### Theme Configuration Initialization -: ${AGNOSTER_DIR_FG:=${CURRENT_FG}} -: ${AGNOSTER_DIR_BG:=blue} - -: ${AGNOSTER_CONTEXT_FG:=${CURRENT_DEFAULT_FG}} -: ${AGNOSTER_CONTEXT_BG:=black} - -: ${AGNOSTER_GIT_CLEAN_FG:=${CURRENT_FG}} -: ${AGNOSTER_GIT_CLEAN_BG:=green} -: ${AGNOSTER_GIT_DIRTY_FG:=black} -: ${AGNOSTER_GIT_DIRTY_BG:=yellow} - -: ${AGNOSTER_BZR_CLEAN_FG:=${CURRENT_FG}} -: ${AGNOSTER_BZR_CLEAN_BG:=green} -: ${AGNOSTER_BZR_DIRTY_FG:=black} -: ${AGNOSTER_BZR_DIRTY_BG:=yellow} - -: ${AGNOSTER_HG_NEWFILE_FG:=white} -: ${AGNOSTER_HG_NEWFILE_BG:=red} -: ${AGNOSTER_HG_CHANGED_FG:=black} -: ${AGNOSTER_HG_CHANGED_BG:=yellow} -: ${AGNOSTER_HG_CLEAN_FG:=${CURRENT_FG}} -: ${AGNOSTER_HG_CLEAN_BG:=green} - -: ${AGNOSTER_VENV_FG:=black} -: ${AGNOSTER_VENV_BG:=blue} - -: ${AGNOSTER_AWS_PROD_FG:=yellow} -: ${AGNOSTER_AWS_PROD_BG:=red} -: ${AGNOSTER_AWS_FG:=black} -: ${AGNOSTER_AWS_BG:=green} - -: ${AGNOSTER_STATUS_RETVAL_FG:=red} -: ${AGNOSTER_STATUS_ROOT_FG:=yellow} -: ${AGNOSTER_STATUS_JOB_FG:=cyan} -: ${AGNOSTER_STATUS_FG:=${CURRENT_DEFAULT_FG}} -: ${AGNOSTER_STATUS_BG:=black} - -: ${AGNOSTER_STATUS_RETVAL_NUMERIC:=false} -: ${AGNOSTER_GIT_INLINE:=false} -: ${AGNOSTER_GIT_BRANCH_STATUS:=true} - -() { - local LC_ALL="" LC_CTYPE="en_US.UTF-8" - SEGMENT_SEPARATOR=$'\ue0b0' -} - -prompt_segment() { - local bg fg - [[ -n $1 ]] && bg="%K{$1}" || bg="%k" - [[ -n $2 ]] && fg="%F{$2}" || fg="%f" - if [[ $CURRENT_BG != 'NONE' && $1 != $CURRENT_BG ]]; then - echo -n " %{$bg%F{$CURRENT_BG}%}$SEGMENT_SEPARATOR%{$fg%} " - else - echo -n "%{$bg%}%{$fg%} " - fi - CURRENT_BG=$1 - [[ -n $3 ]] && echo -n $3 -} - -prompt_end() { - if [[ -n $CURRENT_BG ]]; then - echo -n " %{%k%F{$CURRENT_BG}%}$SEGMENT_SEPARATOR" - else - echo -n "%{%k%}" - fi - echo -n "%{%f%}" - CURRENT_BG='' -} - -git_toplevel() { - local repo_root=$(git rev-parse --show-toplevel) - if [[ $repo_root = '' ]]; then - repo_root=$(git rev-parse --git-dir) - [[ $repo_root = '.' ]] && repo_root=$PWD - fi - echo -n $repo_root -} - -### Prompt components - -prompt_context() { - if [[ -n "$SSH_CLIENT" ]]; then - prompt_segment "$AGNOSTER_CONTEXT_BG" "$AGNOSTER_CONTEXT_FG" "%(!.%{%F{$AGNOSTER_STATUS_ROOT_FG}%}.)%n@%m" - fi -} - -prompt_git_relative() { - local repo_root=$(git_toplevel) - local path_in_repo=$(pwd | sed "s/^$(echo "$repo_root" | sed 's:/:\\/:g;s/\$/\\$/g')//;s:^/::;s:/$::;") - [[ $path_in_repo != '' ]] && prompt_segment "$AGNOSTER_DIR_BG" "$AGNOSTER_DIR_FG" "$path_in_repo" -} - -prompt_git() { - (( $+commands[git] )) || return - [[ "$(command git config --get oh-my-zsh.hide-status 2>/dev/null)" = 1 ]] && return - - local PL_BRANCH_CHAR - () { local LC_ALL="" LC_CTYPE="en_US.UTF-8"; PL_BRANCH_CHAR=$'\ue0a0' } - - if [[ "$(command git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ]]; then - local dirty ref - dirty=$(parse_git_dirty) - ref=$(command git symbolic-ref HEAD 2>/dev/null) || \ - ref="➦ $(command git rev-parse --short HEAD 2>/dev/null)" - - if [[ -n $dirty ]]; then - prompt_segment "$AGNOSTER_GIT_DIRTY_BG" "$AGNOSTER_GIT_DIRTY_FG" - else - prompt_segment "$AGNOSTER_GIT_CLEAN_BG" "$AGNOSTER_GIT_CLEAN_FG" - fi - - echo -n "${${ref:gs/%/%%}/refs\/heads\//$PL_BRANCH_CHAR }" - fi -} - -prompt_dir() { - if [[ $AGNOSTER_GIT_INLINE == 'true' ]] && $(git rev-parse --is-inside-work-tree >/dev/null 2>&1); then - prompt_segment "$AGNOSTER_DIR_BG" "$AGNOSTER_DIR_FG" "$(git_toplevel | sed "s:^$HOME:~:")" - else - prompt_segment "$AGNOSTER_DIR_BG" "$AGNOSTER_DIR_FG" '%~' - fi -} - -prompt_virtualenv() { - return -} - -prompt_status() { - local -a symbols - [[ $AGNOSTER_STATUS_RETVAL_NUMERIC == 'true' && $RETVAL -ne 0 ]] && symbols+="%{%F{$AGNOSTER_STATUS_RETVAL_FG}%}$RETVAL" - [[ $AGNOSTER_STATUS_RETVAL_NUMERIC != 'true' && $RETVAL -ne 0 ]] && symbols+="%{%F{$AGNOSTER_STATUS_RETVAL_FG}%}✘" - [[ $UID -eq 0 ]] && symbols+="%{%F{$AGNOSTER_STATUS_ROOT_FG}%}⚡" - [[ $(jobs -l | wc -l) -gt 0 ]] && symbols+="%{%F{$AGNOSTER_STATUS_JOB_FG}%}⚙" - [[ -n "$symbols" ]] && prompt_segment "$AGNOSTER_STATUS_BG" "$AGNOSTER_STATUS_FG" "$symbols" -} - -prompt_aws() { - [[ -z "$AWS_PROFILE" || "$SHOW_AWS_PROMPT" = false ]] && return - case "$AWS_PROFILE" in - *-prod|*production*) prompt_segment "$AGNOSTER_AWS_PROD_BG" "$AGNOSTER_AWS_PROD_FG" "AWS: ${AWS_PROFILE:gs/%/%%}" ;; - *) prompt_segment "$AGNOSTER_AWS_BG" "$AGNOSTER_AWS_FG" "AWS: ${AWS_PROFILE:gs/%/%%}" ;; - esac -} - -prompt_terraform() { - local terraform_info=$(tf_prompt_info) - [[ -z "$terraform_info" ]] && return - prompt_segment magenta yellow "TF: $terraform_info" -} - -build_prompt() { - RETVAL=$? - prompt_status - prompt_virtualenv - prompt_aws - prompt_terraform - prompt_context - prompt_dir - prompt_git - prompt_end -} - -PROMPT='%{%f%b%k%}$(build_prompt) ' diff --git a/home/zsh.nix b/home/zsh.nix index dbc99c4..a7e7b39 100644 --- a/home/zsh.nix +++ b/home/zsh.nix @@ -9,13 +9,7 @@ let theme = import ../lib/theme.nix { inherit config; }; in { - home.file.".oh-my-zsh/custom/themes/agnoster.zsh-theme".source = ../config/agnoster.zsh-theme; - - home.activation.ensureOhMyZshCache = lib.hm.dag.entryAfter [ "writeBoundary" ] '' - mkdir -p "${config.xdg.cacheHome}/oh-my-zsh" - ''; - - home.packages = [ pkgs.oh-my-zsh ]; + home.packages = [ pkgs.pure-prompt ]; programs.zsh = { enable = true; @@ -74,18 +68,30 @@ in initContent = lib.mkMerge [ (lib.mkOrder 550 '' - # OpenSpec shell completions configuration - fpath=("$HOME/.oh-my-zsh/custom/completions" $fpath) + # Completions + autoload -U compinit && compinit -d "${config.xdg.stateHome}/zcompdump" -u + zmodload zsh/complist + zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-za-z}' '') (lib.mkOrder 800 '' - export ZSH="${pkgs.oh-my-zsh}/share/oh-my-zsh" - export ZSH_CUSTOM="$HOME/.oh-my-zsh/custom" - export ZSH_CACHE_DIR="${config.xdg.cacheHome}/oh-my-zsh" - ZSH_THEME="agnoster" - plugins=(git) - ZSH_DISABLE_COMPFIX=true - source "$ZSH/oh-my-zsh.sh" + # Pure prompt + fpath+=("${pkgs.pure-prompt}/share/zsh/site-functions") + autoload -Uz promptinit && promptinit + + export PURE_PROMPT_SYMBOL=">" + export PURE_PROMPT_VICMD_SYMBOL="<" + export PURE_GIT_UP_ARROW="^" + export PURE_GIT_DOWN_ARROW="v" + export PURE_GIT_STASH_SYMBOL="=" + export PURE_CMD_MAX_EXEC_TIME=5 + export PURE_GIT_PULL=0 + export PURE_GIT_UNTRACKED_DIRTY=1 + zstyle ':prompt:pure:git:stash' show yes + + ${theme.renderPurePrompt "dark"} + + prompt pure '') (lib.mkOrder 1000 '' @@ -130,6 +136,21 @@ in printf 'dark' } + _codex_apply_prompt_theme() { + local mode="$(_codex_read_theme_mode)" + if [[ "$mode" == "''${_CODEX_LAST_PROMPT_THEME:-}" ]]; then + return + fi + + if [[ "$mode" == light ]]; then + ${theme.renderPurePrompt "light"} + else + ${theme.renderPurePrompt "dark"} + fi + + typeset -g _CODEX_LAST_PROMPT_THEME="$mode" + } + _codex_apply_highlight_styles() { local mode="$(_codex_read_theme_mode)" if [[ "$mode" == "''${_CODEX_LAST_HIGHLIGHT_THEME:-}" ]]; then @@ -192,6 +213,7 @@ in zle -N zle-line-finish precmd() { + _codex_apply_prompt_theme _codex_apply_highlight_styles _codex_set_cursor beam } @@ -200,6 +222,7 @@ in _codex_set_cursor beam } + _codex_apply_prompt_theme _codex_apply_highlight_styles ${lib.optionalString hostConfig.isDarwin '' @@ -216,8 +239,8 @@ in '') (lib.mkAfter '' - bindkey '^k' forward-car - bindkey '^j' backward-car + bindkey '^k' forward-char + bindkey '^j' backward-char '') ]; }; diff --git a/lib/theme.nix b/lib/theme.nix index f118017..37eba75 100644 --- a/lib/theme.nix +++ b/lib/theme.nix @@ -140,6 +140,49 @@ let --color=fg+:${theme.text},bg+:${theme.surface},hl+:${theme.blue} --color=info:${theme.green},prompt:${theme.blue},pointer:${theme.text},marker:${theme.green},spinner:${theme.text} ''; + renderPurePrompt = + mode: + let + theme = themes.${mode}; + c = if mode == "light" then { + path = "#4261a5"; + branch = "#427b58"; + dirty = sharedPalette.yellow; + arrow = sharedPalette.purpleNeutral; + stash = sharedPalette.aquaNeutral; + success = "#427b58"; + error = "#c5524a"; + execTime = sharedPalette.gray; + host = sharedPalette.gray; + user = sharedPalette.gray; + } else { + path = sharedPalette.blue; + branch = sharedPalette.green; + dirty = sharedPalette.yellowBright; + arrow = sharedPalette.purple; + stash = sharedPalette.aqua; + success = sharedPalette.green; + error = sharedPalette.red; + execTime = sharedPalette.gray; + host = sharedPalette.gray; + user = sharedPalette.gray; + }; + in + '' + zstyle ':prompt:pure:path' color '${c.path}' + zstyle ':prompt:pure:git:branch' color '${c.branch}' + zstyle ':prompt:pure:git:dirty' color '${c.dirty}' + zstyle ':prompt:pure:git:arrow' color '${c.arrow}' + zstyle ':prompt:pure:git:stash' color '${c.stash}' + zstyle ':prompt:pure:git:action' color '${c.dirty}' + zstyle ':prompt:pure:prompt:success' color '${c.success}' + zstyle ':prompt:pure:prompt:error' color '${c.error}' + zstyle ':prompt:pure:execution_time' color '${c.execTime}' + zstyle ':prompt:pure:host' color '${c.host}' + zstyle ':prompt:pure:user' color '${c.user}' + zstyle ':prompt:pure:user:root' color '${c.error}' + ''; + batTheme = mode: if mode == "light" then "gruvbox-light" else "gruvbox-dark"; deltaTheme = mode: if mode == "light" then "gruvbox-light" else "gruvbox-dark"; @@ -210,6 +253,7 @@ in paths renderFzf renderGhostty + renderPurePrompt renderTmux renderZshHighlights themes diff --git a/nix-maxxing.txt b/nix-maxxing.txt index 4527b07..10f4d47 100644 --- a/nix-maxxing.txt +++ b/nix-maxxing.txt @@ -86,7 +86,9 @@ and Neovim (via RPC) live. Bat and delta are static at build time. 6. SHELL SETUP --------------- -oh-my-zsh with agnoster theme (powerline arrows + git branch coloring). +Pure prompt with gruvbox-colored git integration. Async git status +(no blocking on large repos). Colors defined in lib/theme.nix via +renderPurePrompt - adapts to light/dark mode at runtime. Vim mode via defaultKeymap = "viins" with cursor shape switching (beam for insert, block for normal).