Since expanding a prompt string that contains a funsub will modify the
value of $_, would it make sense to restore the value of $_ after the
expansion is complete, as we do when executing PROMPT_COMMAND?

    $ PS0='${ : X; }' bash --norc
    bash-5.3$ : A
    bash-5.3$ echo $_
    X

P.S. Technically, it was also possible to modify the value of $_ during
prompt string expansion even before the addition of funsubs by doing a
direct assignment to `_' in an arithmetic expansion, something like:

    PS1='${X[_=1]}$ '

but I hope that there is not a legitimate use case for preserving a $_
value so modified past the prompt string expansion phase, as this patch
will also cause such an assignment to be reverted.
---
 parse.y | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/parse.y b/parse.y
index e1e64f5c..57b13aa1 100644
--- a/parse.y
+++ b/parse.y
@@ -6126,7 +6126,7 @@ char *
 decode_prompt_string (char *string)
 {
   WORD_LIST *list;
-  char *result, *t, *orig_string;
+  char *result, *t, *orig_string, *last_lastarg;
   struct dstack save_dstack;
   int last_exit_value, last_comsub_pid, last_comsub_status;
 #if defined (PROMPT_STRING_DECODE)
@@ -6535,10 +6535,15 @@ not_escape:
       last_exit_value = last_command_exit_value;
       last_comsub_pid = last_command_subst_pid;
       last_comsub_status = last_command_subst_status;
+      last_lastarg = get_string_value ("_");
+      if (last_lastarg)
+        last_lastarg = savestring (last_lastarg);
       list = expand_prompt_string (result, Q_DOUBLE_QUOTES, 0);
       free (result);
       result = string_list (list);
       dispose_words (list);
+      bind_lastarg (last_lastarg);
+      FREE (last_lastarg);
       last_command_exit_value = last_exit_value;
       last_command_subst_pid = last_comsub_pid;
       last_command_subst_status = last_comsub_status;
-- 
2.43.0

Reply via email to