diff --git a/.mise.toml b/.mise.toml index 97be4b0..decd338 100644 --- a/.mise.toml +++ b/.mise.toml @@ -2,4 +2,3 @@ node = "24.12.0" pnpm = "11.15.1" neovim = "0.12.4" -starship = "1.26.0" diff --git a/README.md b/README.md index e14f04f..642bf9c 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ brew install mise git clone https://github.com/viqueen/devbox.git cd devbox -# install tools (node, pnpm, neovim, starship) +# install tools (node, pnpm, neovim) mise install # install dependencies @@ -23,7 +23,7 @@ pnpm install # configure shell (exports, PATH, aliases, mise config symlink) ./setup.sh config_box -# optional: workspace-aware prompt (starship) +# optional: workspace-aware prompt ./setup.sh config_prompt # optional: neovim with lazy.nvim @@ -36,17 +36,16 @@ pnpm install Defined in `.mise.toml` and symlinked to `~/.mise.toml` by `config_box`: -| Tool | Purpose | -| -------- | --------------- | -| node | Node.js runtime | -| pnpm | Package manager | -| neovim | Editor | -| starship | Shell prompt | +| Tool | Purpose | +| ------ | --------------- | +| node | Node.js runtime | +| pnpm | Package manager | +| neovim | Editor | ### Prompt -A workspace-aware [starship](https://starship.rs/) prompt that color-codes the hostname segment -based on which workspace you're in: +A dependency-free, workspace-aware prompt (`cli/.promptline.sh`) that color-codes the hostname +segment based on which workspace you're in: | Workspace | Color | | ------------------------------ | ------ | diff --git a/cli/.promptline.sh b/cli/.promptline.sh index 2d5e866..926b804 100644 --- a/cli/.promptline.sh +++ b/cli/.promptline.sh @@ -1,6 +1,13 @@ #!/usr/bin/env bash # -# workspace-aware prompt using starship +# workspace-aware prompt (no external dependencies) +# +# colors match the original promptline / starship workspace palette: +# viqueen workspace -> orange (fg:220 bg:166) +# primary org -> purple (fg:135 bg:55) +# secondary org -> blue (fg:110 bg:20) +# home -> green (fg:231 bg:35) +# elsewhere (default) -> red (fg:231 bg:124) # __devbox_detect_workspace() { @@ -26,14 +33,121 @@ __devbox_detect_workspace() { # cache workspaces root export DEVBOX_WORKSPACES_ROOT="${DEVBOX_WORKSPACES_ROOT:-$(git config labset.workspaces.root 2>/dev/null)}" -# starship config -export STARSHIP_CONFIG="${VIQUEEN_DEVBOX_HOME}/cli/starship.toml" +__devbox_prompt_dir() { + local dir_limit=3 + local truncation="⋯" + local part_count=0 + local formatted="" + local tilde="~" + local cwd="${PWD/#$HOME/$tilde}" + local first_char + + if [[ -n ${ZSH_VERSION-} ]]; then + first_char=${cwd[1,1]} + else + first_char=${cwd::1} + fi + cwd="${cwd#\~}" + + while [[ "$cwd" == */* && "$cwd" != "/" ]]; do + local part="${cwd##*/}" + cwd="${cwd%/*}" + formatted="/$part$formatted" + part_count=$((part_count + 1)) + if [[ $part_count -eq $dir_limit ]]; then + first_char="$truncation" + break + fi + done + + printf "%s" "$first_char$formatted" +} + +__devbox_prompt_git_branch() { + hash git 2>/dev/null || return 1 + local branch + branch=$(git symbolic-ref --quiet --short HEAD 2>/dev/null) || branch=$(git rev-parse --short HEAD 2>/dev/null) || return 1 + printf "%s" "$branch" +} + +__devbox_prompt_render() { + local exit_code=$? + __devbox_detect_workspace + + local wrap end_wrap esc + esc=$'\033[' + if [[ -n ${ZSH_VERSION-} ]]; then + wrap='%{' end_wrap='%}' + else + wrap='\[' end_wrap='\]' + fi + + # sgr fg [bg] -> non-printing-safe escape that resets, then sets fg (and bg if given) + __devbox_sgr() { + local fg="$1" bg="$2" code="0;38;5;${1}" + [[ -n "$bg" ]] && code="${code};48;5;${bg}" + printf '%s%s%sm%s' "$wrap" "$esc" "$code" "$end_wrap" + } + + local reset + reset="${wrap}${esc}0m${end_wrap}" + + local host_fg host_bg + case "$DEVBOX_WORKSPACE" in + viqueen) host_fg=220 host_bg=166 ;; + primary) host_fg=135 host_bg=55 ;; + secondary) host_fg=110 host_bg=20 ;; + home) host_fg=231 host_bg=35 ;; + *) host_fg=231 host_bg=124 ;; + esac + + local host="${VIQUEEN_DEVBOX_MACHINE:-$(hostname -s)}" + local prompt="" + + # workspace host segment -> username segment + prompt+="$(__devbox_sgr "$host_fg" "$host_bg") ${host} " + prompt+="$(__devbox_sgr "$host_bg" 31)" + + # username segment -> directory segment + prompt+="$(__devbox_sgr 231 31) ${USER} " + prompt+="$(__devbox_sgr 31 240)" + + # directory segment -> git branch segment + prompt+="$(__devbox_sgr 250 240) $(__devbox_prompt_dir) " + prompt+="$(__devbox_sgr 240 236)" + + local branch git_symbol=$'' + if branch=$(__devbox_prompt_git_branch); then + # git branch segment -> end of line + prompt+="$(__devbox_sgr 114 236) ${git_symbol} ${branch} " + prompt+="$(__devbox_sgr 236)" + else + prompt+="$(__devbox_sgr 240)" + fi + + if [[ $exit_code -ne 0 ]]; then + prompt+="${reset}$(__devbox_sgr 196) ${exit_code}" + fi + + prompt+="${reset}"$'\n' + + if [[ $exit_code -eq 0 ]]; then + prompt+="$(__devbox_sgr 34)❯ ${reset}" + else + prompt+="$(__devbox_sgr 196)❯ ${reset}" + fi + + printf "%s" "$prompt" +} -# init starship with workspace detection hook if [[ -n ${ZSH_VERSION-} ]]; then - precmd_functions+=(__devbox_detect_workspace) - eval "$(starship init zsh)" + __devbox_prompt_precmd() { PROMPT="$(__devbox_prompt_render)"; } + if [[ ! ${precmd_functions[(r)__devbox_prompt_precmd]} == __devbox_prompt_precmd ]]; then + precmd_functions+=(__devbox_prompt_precmd) + fi else - starship_precmd_user_func="__devbox_detect_workspace" - eval "$(starship init bash)" + __devbox_prompt_precmd() { PS1="$(__devbox_prompt_render)"; } + if [[ ! "$PROMPT_COMMAND" == *__devbox_prompt_precmd* ]]; then + PROMPT_COMMAND='__devbox_prompt_precmd;'$'\n'"$PROMPT_COMMAND" + fi fi diff --git a/cli/starship.toml b/cli/starship.toml deleted file mode 100644 index b6abda6..0000000 --- a/cli/starship.toml +++ /dev/null @@ -1,68 +0,0 @@ -"$schema" = "https://starship.rs/config-schema.json" - -format = """ -${custom.ws_viqueen}\ -${custom.ws_primary}\ -${custom.ws_secondary}\ -${custom.ws_home}\ -${custom.ws_default}\ -$username\ -$directory\ -$git_branch\ -$status\ -$line_break\ -$character""" - -# workspace host segments — mutually exclusive via DEVBOX_WORKSPACE env var -# colors match the original promptline workspace palette - -[custom.ws_viqueen] -command = 'echo "${VIQUEEN_DEVBOX_MACHINE:-$(hostname -s)}"' -when = '[ "$DEVBOX_WORKSPACE" = "viqueen" ]' -format = "[ $output ](fg:220 bg:166)[](fg:166 bg:31)" - -[custom.ws_primary] -command = 'echo "${VIQUEEN_DEVBOX_MACHINE:-$(hostname -s)}"' -when = '[ "$DEVBOX_WORKSPACE" = "primary" ]' -format = "[ $output ](fg:135 bg:55)[](fg:55 bg:31)" - -[custom.ws_secondary] -command = 'echo "${VIQUEEN_DEVBOX_MACHINE:-$(hostname -s)}"' -when = '[ "$DEVBOX_WORKSPACE" = "secondary" ]' -format = "[ $output ](fg:110 bg:20)[](fg:20 bg:31)" - -[custom.ws_home] -command = 'echo "${VIQUEEN_DEVBOX_MACHINE:-$(hostname -s)}"' -when = '[ "$DEVBOX_WORKSPACE" = "home" ]' -format = "[ $output ](fg:231 bg:35)[](fg:35 bg:31)" - -[custom.ws_default] -command = 'echo "${VIQUEEN_DEVBOX_MACHINE:-$(hostname -s)}"' -when = '[ "$DEVBOX_WORKSPACE" = "default" ] || [ -z "$DEVBOX_WORKSPACE" ]' -format = "[ $output ](fg:231 bg:124)[](fg:124 bg:31)" - -[username] -show_always = true -style_user = "fg:231 bg:31" -style_root = "fg:231 bg:31" -format = "[ $user ]($style)[](fg:31 bg:240)" - -[directory] -style = "fg:250 bg:240" -format = "[ $path ]($style)[](fg:240 bg:236)" -truncation_length = 3 -truncation_symbol = "⋯/" - -[git_branch] -style = "fg:250 bg:236" -symbol = " " -format = "[ $symbol]($style)[$branch ](fg:114 bg:236)[](fg:236)" - -[status] -disabled = false -style = "bold red" -format = " [$status]($style)" - -[character] -success_symbol = "[❯](green)" -error_symbol = "[❯](red)" diff --git a/setup.sh b/setup.sh index 0b1d06e..9d5cd77 100755 --- a/setup.sh +++ b/setup.sh @@ -18,8 +18,6 @@ function config_box() { echo "export PATH=${PATH}:${VIQUEEN_DEVBOX_HOME}/modules/cli/bin:${VIQUEEN_DEVBOX_HOME}/cli/bin:~/bin" >> "${rc_file}" ln -sfnv "${VIQUEEN_DEVBOX_HOME}"/cli/.devboxrc "${HOME}/.devboxrc" echo "source ${HOME}/.devboxrc" >> "${rc_file}" - # symlink mise config so tools are available globally - ln -sfnv "${VIQUEEN_DEVBOX_HOME}"/.mise.toml "${HOME}/.mise.toml" } function config_vim() {