From 77cae177b9820df737d8f0c793d437a5cf56aa82 Mon Sep 17 00:00:00 2001 From: "Thomas G. Lopes" Date: Thu, 5 Mar 2026 15:05:58 +0000 Subject: [PATCH] replace starship with custom fish prompt --- fish/files/config.fish | 3 +- fish/files/functions/_prompt_config.fish | 57 ++++++ fish/files/functions/_prompt_directory.fish | 22 +++ fish/files/functions/_prompt_segment.fish | 15 ++ fish/files/functions/fish_mode_prompt.fish | 3 + fish/files/functions/fish_prompt.fish | 173 ++++++++++++++++++ fish/files/functions/fish_right_prompt.fish | 3 + fish/files/functions/prompt-config.fish | 80 ++++++++ matugen/files/config.toml | 14 +- .../files/templates/fish-prompt-colors.fish | 11 ++ matugen/files/templates/starship-colors.toml | 166 ----------------- 11 files changed, 373 insertions(+), 174 deletions(-) create mode 100644 fish/files/functions/_prompt_config.fish create mode 100644 fish/files/functions/_prompt_directory.fish create mode 100644 fish/files/functions/_prompt_segment.fish create mode 100644 fish/files/functions/fish_mode_prompt.fish create mode 100644 fish/files/functions/fish_prompt.fish create mode 100644 fish/files/functions/fish_right_prompt.fish create mode 100644 fish/files/functions/prompt-config.fish create mode 100644 matugen/files/templates/fish-prompt-colors.fish delete mode 100644 matugen/files/templates/starship-colors.toml diff --git a/fish/files/config.fish b/fish/files/config.fish index ba6e5b0..3579918 100644 --- a/fish/files/config.fish +++ b/fish/files/config.fish @@ -65,7 +65,6 @@ status is-interactive; and begin nerdfetch if test "$TERM" != dumb - eval (starship init fish) fzf --fish | source end @@ -170,5 +169,7 @@ if test (uname) = Darwin # opencode fish_add_path /Users/thomasglopes/.opencode/bin + end + diff --git a/fish/files/functions/_prompt_config.fish b/fish/files/functions/_prompt_config.fish new file mode 100644 index 0000000..91f237d --- /dev/null +++ b/fish/files/functions/_prompt_config.fish @@ -0,0 +1,57 @@ +# Prompt configuration + +function _prompt_config + # Colors + if not set -q prompt_color_surface; and not set -Uq prompt_color_surface + set -U prompt_color_surface 1b2122 + end + if not set -q prompt_color_primary; and not set -Uq prompt_color_primary + set -U prompt_color_primary 81d3df + end + if not set -q prompt_color_secondary; and not set -Uq prompt_color_secondary + set -U prompt_color_secondary b1cbcf + end + if not set -q prompt_color_tertiary; and not set -Uq prompt_color_tertiary + set -U prompt_color_tertiary b9c6ea + end + if not set -q prompt_color_error; and not set -Uq prompt_color_error + set -U prompt_color_error ffb4ab + end + if not set -q prompt_color_primary_fixed; and not set -Uq prompt_color_primary_fixed + set -U prompt_color_primary_fixed 9df0fb + end + if not set -q prompt_color_tertiary_fixed; and not set -Uq prompt_color_tertiary_fixed + set -U prompt_color_tertiary_fixed d9e2ff + end + + # Behavior + if not set -q prompt_show_username; and not set -Uq prompt_show_username + set -U prompt_show_username true + end + if not set -q prompt_show_time; and not set -Uq prompt_show_time + set -U prompt_show_time true + end + if not set -q prompt_time_format; and not set -Uq prompt_time_format + set -U prompt_time_format "%I:%M%P" + end + if not set -q prompt_dir_truncation; and not set -Uq prompt_dir_truncation + set -U prompt_dir_truncation 3 + end + + # Symbols + if not set -q prompt_symbol; and not set -Uq prompt_symbol + set -U prompt_symbol "󱞪" + end + if not set -q prompt_user_symbol; and not set -Uq prompt_user_symbol + set -U prompt_user_symbol "󰧱" + end + + # Directory substitutions + if not set -q prompt_dir_substitutions; and not set -Uq prompt_dir_substitutions + set -U prompt_dir_substitutions \ + "Documents:󰈙" \ + "Downloads: " \ + "Music: " \ + "Pictures: " + end +end diff --git a/fish/files/functions/_prompt_directory.fish b/fish/files/functions/_prompt_directory.fish new file mode 100644 index 0000000..4a316ad --- /dev/null +++ b/fish/files/functions/_prompt_directory.fish @@ -0,0 +1,22 @@ +# Format current directory with substitutions and truncation +function _prompt_directory + set -l dir (pwd | string replace $HOME "~") + + for sub in $prompt_dir_substitutions + set -l parts (string split ":" $sub) + set -l name $parts[1] + set -l icon $parts[2] + set dir (string replace -a "/$name" "/$icon" $dir) + set dir (string replace "^$name" "$icon" $dir) + end + + if test $prompt_dir_truncation -gt 0 + set -l parts (string split "/" $dir) + if test (count $parts) -gt $prompt_dir_truncation + set parts "…" $parts[(math 2 - $prompt_dir_truncation)..-1] + end + set dir (string join "/" $parts) + end + + echo $dir +end diff --git a/fish/files/functions/_prompt_segment.fish b/fish/files/functions/_prompt_segment.fish new file mode 100644 index 0000000..802df99 --- /dev/null +++ b/fish/files/functions/_prompt_segment.fish @@ -0,0 +1,15 @@ +# Build a prompt segment with rounded corners +function _prompt_segment + set content $argv[1] + set bg $argv[2] + set fg $argv[3] + + test -z "$content"; and return + + set bg (string replace -a "#" "" $bg) + set bg (string replace -a '"' '' $bg) + set fg (string replace -a "#" "" $fg) + set fg (string replace -a '"' '' $fg) + + echo (set_color $bg)(set_color -b $bg $fg)" $content "(set_color normal)(set_color $bg)(set_color normal) +end diff --git a/fish/files/functions/fish_mode_prompt.fish b/fish/files/functions/fish_mode_prompt.fish new file mode 100644 index 0000000..880c98c --- /dev/null +++ b/fish/files/functions/fish_mode_prompt.fish @@ -0,0 +1,3 @@ +# Disable fish's built-in vi mode indicator (we render our own mode pill in fish_prompt) +function fish_mode_prompt +end diff --git a/fish/files/functions/fish_prompt.fish b/fish/files/functions/fish_prompt.fish new file mode 100644 index 0000000..a4d8bb8 --- /dev/null +++ b/fish/files/functions/fish_prompt.fish @@ -0,0 +1,173 @@ +# Custom Fish prompt - simple version +# Configure via: prompt-config + +function _prompt_git_branch + git branch --show-current 2>/dev/null +end + +function _prompt_git_icon + set -l remotes (git remote -v 2>/dev/null | awk '{print $2}') + test -z "$remotes"; and return + + for remote in $remotes + if not string match -q "*github.com*" $remote + printf '\ue702' + return + end + end + printf '\uf113' +end + +function _prompt_git_status + git rev-parse --git-dir >/dev/null 2>&1; or return + + set -l staged (git diff --cached --numstat 2>/dev/null | wc -l) + set -l modified (git diff --numstat 2>/dev/null | wc -l) + set -l untracked (git ls-files --others --exclude-standard 2>/dev/null | wc -l) + set -l stashed (git stash list 2>/dev/null | wc -l) + + set -l ahead_behind (git rev-list --left-right --count @{upstream}...HEAD 2>/dev/null) + set -l ahead (echo $ahead_behind | awk '{print $2}') + set -l behind (echo $ahead_behind | awk '{print $1}') + + set -l status_parts + + if test "$staged" -gt 0 + set status_parts $status_parts "++($staged)" + end + + if test "$modified" -gt 0 + set status_parts $status_parts "!($modified)" + end + + if test "$untracked" -gt 0 + set status_parts $status_parts "?($untracked)" + end + + if test "$stashed" -gt 0 + set status_parts $status_parts "\$" + end + + if test -n "$ahead" -a "$ahead" -gt 0 + if test -n "$behind" -a "$behind" -gt 0 + set status_parts $status_parts "⇕[⇡($ahead)⇣($behind)]" + else + set status_parts $status_parts "⇡($ahead)" + end + else if test -n "$behind" -a "$behind" -gt 0 + set status_parts $status_parts "⇣($behind)" + end + + if test -z "$status_parts" + echo "✓" + else + string join "" $status_parts + end +end + +function _prompt_mode_text + switch $fish_bind_mode + case default + echo "N" + case insert + echo "I" + case visual + echo "V" + case replace-one + echo "R" + case '*' + echo "$fish_bind_mode" + end +end + +function _prompt_mode_color + switch $fish_bind_mode + case default + echo $prompt_color_error + case insert + echo $prompt_color_tertiary_fixed + case visual + echo $prompt_color_primary_fixed + case replace-one + echo $prompt_color_error + case '*' + echo $prompt_color_tertiary_fixed + end +end + + +function fish_prompt + # keep vertical spacing consistent (including empty Enter) + echo + + _prompt_config + + set -l bg $prompt_color_surface + set -l left_parts + + # vi mode indicator pill on left + set -l mode_text (_prompt_mode_text) + set -l mode_color (_prompt_mode_color) + set left_parts $left_parts (_prompt_segment "$mode_text" $bg $mode_color) + + # Username + if test "$prompt_show_username" = true + set left_parts $left_parts (_prompt_segment "$prompt_user_symbol $USER" $bg $prompt_color_tertiary_fixed) + end + + # Directory + set -l dir (_prompt_directory) + set left_parts $left_parts (_prompt_segment "$dir" $bg $prompt_color_primary) + + # Git branch with dynamic icon + set -l branch (_prompt_git_branch) + if test -n "$branch" + set -l git_icon (_prompt_git_icon) + set left_parts $left_parts (_prompt_segment "$git_icon $branch" $bg $prompt_color_primary_fixed) + end + + # Git status + set -l git_status (_prompt_git_status) + if test -n "$git_status" + set -l fg_color $prompt_color_error + if test "$git_status" = "✓" + set fg_color $prompt_color_tertiary_fixed + end + set left_parts $left_parts (_prompt_segment "$git_status" $bg $fg_color) + end + + set -l left_line (string join " " $left_parts) + + # Right-aligned time pill + set -l right_line "" + if test "$prompt_show_time" = true + set -l time_str (date "+$prompt_time_format") + set right_line (_prompt_segment "󰴈 $time_str" $bg $prompt_color_secondary) + end + + if test -n "$right_line" + set -l cols $COLUMNS + test -z "$cols"; and set cols (tput cols 2>/dev/null) + test -z "$cols"; and set cols 80 + + set -l left_width (string length -V -- $left_line) + set -l right_width (string length -V -- $right_line) + set -l gap (math $cols - $left_width - $right_width) + + if test $gap -lt 1 + set gap 1 + end + + set -l spaces (string repeat -n $gap " ") + echo "$left_line$spaces$right_line" + else + echo $left_line + end + + # Second line: input prompt + set -l tertiary_clean (string replace -a "#" "" $prompt_color_tertiary) + set tertiary_clean (string replace -a '"' '' $tertiary_clean) + set_color $tertiary_clean + echo -n "$prompt_symbol " + set_color normal +end diff --git a/fish/files/functions/fish_right_prompt.fish b/fish/files/functions/fish_right_prompt.fish new file mode 100644 index 0000000..84dfab8 --- /dev/null +++ b/fish/files/functions/fish_right_prompt.fish @@ -0,0 +1,3 @@ +# Right prompt disabled (time is shown inline in fish_prompt) +function fish_right_prompt +end diff --git a/fish/files/functions/prompt-config.fish b/fish/files/functions/prompt-config.fish new file mode 100644 index 0000000..f80bdd9 --- /dev/null +++ b/fish/files/functions/prompt-config.fish @@ -0,0 +1,80 @@ +# Customize prompt settings +# Usage: prompt-config [setting] [value] +# Examples: +# prompt-config # Show current settings +# prompt-config show_username false +# prompt-config color_primary ff6b6b +# prompt-config reset + +function prompt-config + if test (count $argv) -eq 0 + echo "Current prompt settings:" + echo "" + echo "Colors:" + echo " surface: $prompt_color_surface" + echo " primary: $prompt_color_primary" + echo " secondary: $prompt_color_secondary" + echo " tertiary: $prompt_color_tertiary" + echo " error: $prompt_color_error" + echo " primary_fixed: $prompt_color_primary_fixed" + echo " tertiary_fixed: $prompt_color_tertiary_fixed" + echo "" + echo "Behavior:" + echo " show_username: $prompt_show_username" + echo " show_time: $prompt_show_time" + echo " time_format: $prompt_time_format" + echo " dir_truncation: $prompt_dir_truncation" + echo "" + echo "Symbols:" + echo " prompt_symbol: $prompt_symbol" + echo " user_symbol: $prompt_user_symbol" + echo "" + echo "Usage: prompt-config " + echo " prompt-config reset" + return + end + + if test "$argv[1]" = "reset" + set -e prompt_color_surface + set -e prompt_color_primary + set -e prompt_color_secondary + set -e prompt_color_tertiary + set -e prompt_color_error + set -e prompt_color_primary_fixed + set -e prompt_color_tertiary_fixed + set -e prompt_show_username + set -e prompt_show_time + set -e prompt_time_format + set -e prompt_dir_truncation + set -e prompt_symbol + set -e prompt_user_symbol + echo "Prompt settings reset." + return + end + + if test (count $argv) -lt 2 + echo "Usage: prompt-config " + return 1 + end + + set -l setting $argv[1] + set -l value $argv[2..-1] + set -l varname prompt_$setting + + set -U $varname $value + echo "Set $setting = $value" +end + +complete -c prompt-config -f +complete -c prompt-config -n __fish_use_subcommand -a "reset" -d "Reset to defaults" +complete -c prompt-config -n __fish_use_subcommand -a "show_username" -d "Show username (true/false)" +complete -c prompt-config -n __fish_use_subcommand -a "show_time" -d "Show time (true/false)" +complete -c prompt-config -n __fish_use_subcommand -a "time_format" -d "Time format (e.g. %H:%M)" +complete -c prompt-config -n __fish_use_subcommand -a "dir_truncation" -d "Directory truncation depth" +complete -c prompt-config -n __fish_use_subcommand -a "symbol" -d "Prompt symbol" +complete -c prompt-config -n __fish_use_subcommand -a "user_symbol" -d "Username icon" +complete -c prompt-config -n __fish_use_subcommand -a "color_surface" -d "Surface color" +complete -c prompt-config -n __fish_use_subcommand -a "color_primary" -d "Primary color" +complete -c prompt-config -n __fish_use_subcommand -a "color_secondary" -d "Secondary color" +complete -c prompt-config -n __fish_use_subcommand -a "color_tertiary" -d "Tertiary color" +complete -c prompt-config -n __fish_use_subcommand -a "color_error" -d "Error color" diff --git a/matugen/files/config.toml b/matugen/files/config.toml index 88d81d5..c325d29 100644 --- a/matugen/files/config.toml +++ b/matugen/files/config.toml @@ -21,9 +21,9 @@ output_path = '~/.config/gtk-3.0/colors.css' input_path = '~/.config/matugen/templates/gtk-colors.css' output_path = '~/.config/gtk-4.0/colors.css' -[templates.starship] -input_path = '~/.config/matugen/templates/starship-colors.toml' -output_path = '~/.config/starship.toml' +[templates.fish-prompt] +input_path = '~/.config/matugen/templates/fish-prompt-colors.fish' +output_path = '~/.config/fish/conf.d/prompt-colors.fish' [templates.yazi] input_path = '~/.config/matugen/templates/yazi-theme.toml' @@ -50,10 +50,10 @@ post_hook = 'touch ~/.config/zellij/config.kdl && nohup ~/.config/matugen/script input_path = '~/.config/matugen/templates/jjui-theme.toml' output_path = '~/.config/jjui/themes/matugen.toml' -[templates.nvim] -input_path = '~/.config/matugen/templates/neovim.lua' -output_path = '~/.config/nvim/lua/plugins/dankcolors.lua' -post_hook = 'nohup ~/.config/matugen/scripts/sync-nvim-mac.sh >/dev/null 2>&1 &' +# [templates.nvim] +# input_path = '~/.config/matugen/templates/neovim.lua' +# output_path = '~/.config/nvim/lua/plugins/dankcolors.lua' +# post_hook = 'nohup ~/.config/matugen/scripts/sync-nvim-mac.sh >/dev/null 2>&1 &' [templates.pi] input_path = '~/.config/matugen/templates/pi-theme.json' diff --git a/matugen/files/templates/fish-prompt-colors.fish b/matugen/files/templates/fish-prompt-colors.fish new file mode 100644 index 0000000..227c838 --- /dev/null +++ b/matugen/files/templates/fish-prompt-colors.fish @@ -0,0 +1,11 @@ +# Prompt colors (generated by matugen) +# Do not edit manually - run `matugen` to regenerate + +set -U prompt_color_surface "{{colors.surface_container.default.hex}}" +set -U prompt_color_primary "{{colors.primary.default.hex}}" +set -U prompt_color_secondary "{{colors.secondary.default.hex}}" +set -U prompt_color_tertiary "{{colors.tertiary.default.hex}}" +set -U prompt_color_error "{{colors.error.default.hex}}" +set -U prompt_color_primary_fixed "{{colors.primary_fixed.default.hex}}" +set -U prompt_color_tertiary_fixed "{{colors.tertiary_fixed.default.hex}}" +set -U prompt_color_text "{{colors.on_surface.default.hex}}" diff --git a/matugen/files/templates/starship-colors.toml b/matugen/files/templates/starship-colors.toml deleted file mode 100644 index 5acefc5..0000000 --- a/matugen/files/templates/starship-colors.toml +++ /dev/null @@ -1,166 +0,0 @@ -"$schema" = 'https://starship.rs/config-schema.json' - -format = """ -$username\ -$directory\ -$git_branch\ -$git_status\ -$fill\ -$c\ -$elixir\ -$elm\ -$golang\ -$haskell\ -$java\ -$julia\ -$nodejs\ -$nim\ -$rust\ -$scala\ -$conda\ -$python\ -$time\n \ -[󱞪](fg:tertiary) \ -""" - -palette = "colors" - -[palettes.colors] -surface_container = '{{colors.surface_container.default.hex}}' -error = '{{colors.error.default.hex}}' -tertiary = '{{colors.tertiary.default.hex}}' -secondary = '{{colors.secondary.default.hex}}' -primary = '{{colors.primary.default.hex}}' -primary_fixed = '{{colors.primary_fixed.default.hex}}' -tertiary_fixed = '{{colors.tertiary_fixed.default.hex}}' -on_surface = '{{colors.on_surface.default.hex}}' - -[directory] -format = "[](fg:surface_container)[ $path ]($style)[](fg:surface_container) " -style = "bg:surface_container fg:primary" -truncation_length = 3 -truncation_symbol = "…/" - -[directory.substitutions] -Documents = "󰈙" -Downloads = " " -Music = " " -Pictures = " " - -[fill] -style = "fg:surface_container" -symbol = " " - -[git_branch] -format = "[](fg:surface_container)[ $symbol $branch ]($style)[](fg:surface_container) " -style = "bg:surface_container fg:primary_fixed" -symbol = "" - -[git_status] -disabled = false -style = "bg:surface_container fg:error" -format = '[](fg:surface_container)([$all_status$ahead_behind]($style))[](fg:surface_container) ' -up_to_date = '[ ✓ ](bg:surface_container fg:tertiary_fixed)' -untracked = '[?\($count\)](bg:surface_container fg:tertiary)' -stashed = '[\$](bg:surface_container fg:tertiary_fixed)' -modified = '[!\($count\)](bg:surface_container fg:tertiary)' -renamed = '[»\($count\)](bg:surface_container fg:tertiary_fixed)' -deleted = '[✘\($count\)](style)' -staged = '[++\($count\)](bg:surface_container fg:tertiary)' -ahead = '[⇡\(${count}\)](bg:surface_container fg:primary_fixed)' -diverged = '⇕[\[](bg:surface_container fg:tertiary_fixed)[⇡\(${ahead_count}\)](bg:surface_container fg:primary_fixed)[⇣\(${behind_count}\)](bg:surface_container fg:secondary)[\]](bg:surface_container fg:tertiary_fixed)' -behind = '[⇣\(${count}\)](bg:surface_container fg:secondary)' - -[time] -disabled = false -format = " [](fg:surface_container)[ $time 󰴈 ]($style)[](fg:surface_container)" -style = "bg:surface_container fg:secondary" -time_format = "%I:%M%P" -use_12hr = true - -[username] -disabled = false -format = "[](fg:surface_container)[ 󰧱 $user ]($style)[](fg:surface_container) " -show_always = true -style_root = "bg:surface_container fg:tertiary_fixed" -style_user = "bg:surface_container fg:tertiary_fixed" - -# Languages - -[c] -style = "bg:surface_container fg:primary" -format = " [](fg:surface_container)[ $symbol$version ]($style)[](fg:surface_container)" -disabled = false -symbol = " " - -[elixir] -style = "bg:surface_container fg:primary" -format = " [](fg:surface_container)[ $symbol$version ]($style)[](fg:surface_container)" -disabled = false -symbol = " " - -[elm] -style = "bg:surface_container fg:primary" -format = " [](fg:surface_container)[ $symbol$version ]($style)[](fg:surface_container)" -disabled = false -symbol = " " - -[golang] -style = "bg:surface_container fg:primary" -format = " [](fg:surface_container)[ $symbol$version ]($style)[](fg:surface_container)" -disabled = false -symbol = " " - -[haskell] -style = "bg:surface_container fg:primary" -format = " [](fg:surface_container)[ $symbol$version ]($style)[](fg:surface_container)" -disabled = false -symbol = " " - -[java] -style = "bg:surface_container fg:primary" -format = " [](fg:surface_container)[ $symbol$version ]($style)[](fg:surface_container)" -disabled = false -symbol = " " - -[julia] -style = "bg:surface_container fg:primary" -format = " [](fg:surface_container)[ $symbol$version ]($style)[](fg:surface_container)" -disabled = false -symbol = " " - -[nodejs] -style = "bg:surface_container fg:primary" -format = " [](fg:surface_container)[ $symbol$version ]($style)[](fg:surface_container)" -disabled = false -symbol = "󰎙 " - -[nim] -style = "bg:surface_container fg:primary" -format = " [](fg:surface_container)[ $symbol$version ]($style)[](fg:surface_container)" -disabled = false -symbol = "󰆥 " - -[rust] -style = "bg:surface_container fg:primary" -format = " [](fg:surface_container)[ $symbol$version ]($style)[](fg:surface_container)" -disabled = false -symbol = " " - -[scala] -style = "bg:surface_container fg:primary" -format = " [](fg:surface_container)[ $symbol$version ]($style)[](fg:surface_container)" -disabled = false -symbol = " " - -[python] -style = "bg:surface_container fg:primary" -format = " [](fg:surface_container)[ $symbol$version ]($style)[](fg:surface_container)" -disabled = false -symbol = ' ' - -[conda] -style = "bg:surface_container fg:primary" -format = " [](fg:surface_container)[ $symbol$environment ]($style)[](fg:surface_container)" -disabled = false -symbol = '🅒 '