diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9165c5d6e..98cd6ebe9 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -9,6 +9,8 @@ Interactive improvements ------------------------ - On the first run after upgrading from an older version, fish will try harder to check if the current theme matches a historical default, in which case fish won't create ``~/.config/fish/conf.d/fish_frozen_theme.fish``. This means that on systems where fish version 3.x was installed originally, the update will avoid creating that file (:issue:`12725`). +- ``fish_hg_prompt``, ``fish_git_prompt`` and ``fish_fossil_prompt`` now strip control characters from VCS state read off disk, matching ``prompt_pwd``. +- The sample informative and minimalist prompts now use ``prompt_pwd`` instead of printing ``$PWD`` directly. For distributors and developers ------------------------------- diff --git a/share/functions/fish_fossil_prompt.fish b/share/functions/fish_fossil_prompt.fish index 122d57656..21636dffb 100644 --- a/share/functions/fish_fossil_prompt.fish +++ b/share/functions/fish_fossil_prompt.fish @@ -48,6 +48,9 @@ function fish_fossil_prompt --description 'Write out the fossil prompt' echo -n ' (' set_color magenta + # Strip control characters to avoid injecting terminal escape sequences into the prompt. + # Raw C1 bytes are stored in fish's private-use encoding at U+F680-U+F69F. + set branch (string replace -ra '[\x00-\x1f\x7f-\x9f\x{f680}-\x{f69f}]' '' -- $branch) echo -n "$branch" set_color --reset echo -n '|' diff --git a/share/functions/fish_git_prompt.fish b/share/functions/fish_git_prompt.fish index ec8ff7423..73dcdd1ec 100644 --- a/share/functions/fish_git_prompt.fish +++ b/share/functions/fish_git_prompt.fish @@ -495,6 +495,8 @@ function __fish_git_prompt_operation_branch_bare --description "fish_git_prompt set -l step set -l total + # Strip control characters from these dot-files before showing them in the prompt. + # (git itself does not validate the contents of rebase-merge/rebase-apply state files). if test -d $git_dir/rebase-merge set branch (cat $git_dir/rebase-merge/head-name 2>/dev/null) set step (cat $git_dir/rebase-merge/msgnum 2>/dev/null) @@ -527,10 +529,6 @@ function __fish_git_prompt_operation_branch_bare --description "fish_git_prompt end end - if test -n "$step" -a -n "$total" - set operation "$operation $step/$total" - end - if test -z "$branch" if not set branch (command git symbolic-ref HEAD 2>/dev/null) set detached yes @@ -567,6 +565,16 @@ function __fish_git_prompt_operation_branch_bare --description "fish_git_prompt end end + for var_name in branch step total + if set -q $var_name[1] + set $var_name (string replace -ra '[\x00-\x1f\x7f-\x9f\x{f680}-\x{f69f}]' '' -- $$var_name) + end + end + + if test -n "$step" -a -n "$total" + set operation "$operation $step/$total" + end + echo $operation echo $branch echo $detached diff --git a/share/functions/fish_hg_prompt.fish b/share/functions/fish_hg_prompt.fish index f7a1c09d1..df6efe9cd 100644 --- a/share/functions/fish_hg_prompt.fish +++ b/share/functions/fish_hg_prompt.fish @@ -30,9 +30,14 @@ function fish_hg_prompt --description 'Write out the hg prompt' set -l root (fish_print_hg_root) or return 1 - # Read branch and bookmark + # Read branch and bookmark. + # Strip control characters before showing branch/bookmark names in the prompt. + # Raw C1 bytes are stored in fish's private-use encoding at U+F680-U+F69F. + # (they live under .hg/ and are not validated by hg itself in this code path). set -l branch (cat $root/branch 2>/dev/null; or echo default) + set branch (string replace -ra '[\x00-\x1f\x7f-\x9f\x{f680}-\x{f69f}]' '' -- $branch) if set -l bookmark (cat $root/bookmarks.current 2>/dev/null) + set bookmark (string replace -ra '[\x00-\x1f\x7f-\x9f\x{f680}-\x{f69f}]' '' -- $bookmark) set branch "$branch|$bookmark" end diff --git a/share/prompts/informative.fish b/share/prompts/informative.fish index 67a05fac6..b8fbacb6d 100644 --- a/share/prompts/informative.fish +++ b/share/prompts/informative.fish @@ -17,7 +17,7 @@ function fish_prompt --description 'Informative prompt' set -l pipestatus_string (__fish_print_pipestatus "[" "]" "|" "$status_color" "$statusb_color" $last_pipestatus) printf '[%s] %s%s@%s %s%s %s%s%s \n> ' (date "+%H:%M:%S") (set_color brblue) \ - $USER (prompt_hostname) (set_color $fish_color_cwd) $PWD $pipestatus_string \ + $USER (prompt_hostname) (set_color $fish_color_cwd) (prompt_pwd) $pipestatus_string \ (set_color --reset) end end diff --git a/share/prompts/minimalist.fish b/share/prompts/minimalist.fish index 5e0dba7d7..e223ff37a 100644 --- a/share/prompts/minimalist.fish +++ b/share/prompts/minimalist.fish @@ -3,7 +3,7 @@ function fish_prompt set_color $fish_color_cwd - echo -n (path basename $PWD) + echo -n (prompt_pwd | path basename) set_color --reset echo -n ' ) ' end diff --git a/tests/checks/vcs-prompts.fish b/tests/checks/vcs-prompts.fish new file mode 100644 index 000000000..c4b4d61dc --- /dev/null +++ b/tests/checks/vcs-prompts.fish @@ -0,0 +1,36 @@ +#RUN: %fish %s +#REQUIRES: command -v git + +# Verify VCS prompts strip control characters from +# state files before showing them (same class as prompt_pwd / #12629). + +set -l tmp (mktemp -d) + +# --- fish_hg_prompt --- +# Stub `hg` to satisfy `command -sq hg` without requiring real Mercurial. +mkdir $tmp/bin +echo '#!/bin/sh' >$tmp/bin/hg +chmod +x $tmp/bin/hg +set -gx PATH $tmp/bin $PATH + +mkdir -p $tmp/hgrepo/.hg +touch $tmp/hgrepo/.hg/dirstate +printf 'main\e]0;OHNO\a\x7f\u0080\x80' >$tmp/hgrepo/.hg/branch + +cd $tmp/hgrepo +fish_hg_prompt +echo +# CHECK: {{.*}} (main]0;OHNO) + +# --- fish_git_prompt: rebase-merge state with escape sequence in head-name --- +mkdir $tmp/gitrepo +cd $tmp/gitrepo +git init -q +mkdir .git/rebase-merge +printf 'refs/heads/main\e]0;OHNO\a\x7f\u0080\x80' >.git/rebase-merge/head-name +: >.git/rebase-merge/msgnum +: >.git/rebase-merge/end + +fish_git_prompt +echo +# CHECK: (main]0;OHNO|REBASE-m)