How to use PROMPT_COMMAND(S) without breaking other scripts

10 views
Skip to first unread message

Koichi Murase

unread,
Aug 22, 2020, 10:35:53 PM8/22/20
to bug-...@gnu.org
Hi, I have a question on the behavior of the new array PROMPT_COMMANDS
and the best practice to use it.

In coming Bash 5.1, the new array variable `PROMPT_COMMANDS' is
available in the replacement of `PROMPT_COMMAND'. When the array
`PROMPT_COMMANDS' has one or more elements, the scalar version
`PROMPT_COMMAND' is disabled.

Is there a background that the scalar version is disabled in the
presence of the array version? Because of this behavior, I am
wondering how to write a source script in the way not interfering with
other source scripts which might use either of `PROMPT_COMMANDS' or
`PROMPT_COMMAND'.

* If I use the newer form `PROMPT_COMMANDS+=(my-function)', other
scripts that use `PROMPT_COMMAND' will be broken. Maybe I can write
in the following way to convert `PROMPT_COMMAND' to
`PROMPT_COMMANDS', but it still does not resolve the problem of the
scripts sourced after my script.

if [[ $PROMPT_COMMAND ]]; then
PROMPT_COMMANDS+=("$PROMPT_COMMAND")
unset PROMPT_COMMAND
fi
PROMPT_COMMANDS+=(my-function)

* If I use the older form with `PROMPT_COMMAND', it will be broken
when another script sets the variable `PROMPT_COMMANDS'. Maybe I
can switch to `PROMPT_COMMANDS' only when the array already exists,
but it again does not work when the other script sourced after mine
newly sets `PROMPT_COMMANDS'.

if ((${#PROMPT_COMMANDS})); then
PROMPT_COMMANDS+=(my-function)
else
PROMPT_COMMAND="my-function${PROMPT_COMMAND:+;}$PROMPT_COMMAND"
fi

Here, my question is what is the best practice to use the new array
variable `PROMPT_COMMANDS' in the way that it does not break the
conventional scripts that use `PROMPT_COMMAND'.

# The related commit is 5f49ef47d (commit bash-20200323 snapshot).
# Here are the related threads:
# https://lists.gnu.org/archive/html/bug-bash/2018-01/threads.html#00067
# https://lists.gnu.org/archive/html/bug-bash/2018-02/threads.html#00019

--
Koichi

Chet Ramey

unread,
Aug 24, 2020, 10:58:07 AM8/24/20
to Koichi Murase, bug-...@gnu.org, chet....@case.edu
On 8/22/20 10:35 PM, Koichi Murase wrote:
> Hi, I have a question on the behavior of the new array PROMPT_COMMANDS
> and the best practice to use it.
>
> In coming Bash 5.1, the new array variable `PROMPT_COMMANDS' is
> available in the replacement of `PROMPT_COMMAND'. When the array
> `PROMPT_COMMANDS' has one or more elements, the scalar version
> `PROMPT_COMMAND' is disabled.
>
> Is there a background that the scalar version is disabled in the
> presence of the array version?

There's no real good solution. I wanted a clean break between the scalar
and array versions, figuring that the distributions that populated
PROMPT_COMMAND could easily make that PROMPT_COMMANDS[0].

It would be easy enough to favor PROMPT_COMMANDS over PROMPT_COMMAND,
but execute both if both are set. The problem there is that it
interferes with the ability to use both, as some distros might want as a
transition, and result in commands being executed twice. Since you have
to check the bash version to make sure that PROMPT_COMMANDS is going to
work, I don't think it's going to be that hard to use one or the other
consistently.

I sometimes think I should have stuck with converting PROMPT_COMMAND to
an array. Either way, there's going to be a transition, and maybe that
would have been the easiest.


--
``The lyf so short, the craft so long to lerne.'' - Chaucer
``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU ch...@case.edu http://tiswww.cwru.edu/~chet/

Koichi Murase

unread,
Aug 24, 2020, 11:38:41 AM8/24/20
to Chester Ramey, bug-...@gnu.org
2020-08-24 23:57 Chet Ramey <chet....@case.edu>:
> There's no real good solution. I wanted a clean break between the scalar
> and array versions, figuring that the distributions that populated
> PROMPT_COMMAND could easily make that PROMPT_COMMANDS[0].

Thank you for your reply. OK, if there would be no better solution, I
would go with the first option (to convert PROMPT_COMMAND to
PROMPT_COMMANDS and append mine to PROMPT_COMMANDS) and see if
something happens.

> The problem there is that it interferes with the ability to use
> both, as some distros might want as a transition, and result in
> commands being executed twice.

Now I see the points. I didn't come to the idea to set the values to
both as I somehow unconsciously assumed that everyone checks the Bash
version when one uses PROMPT_COMMANDS. Thank you for pointing this
out. This means that I need to be careful if I would convert
PROMPT_COMMAND set by others into PROMPT_COMMANDS.

--
Koichi

Martijn Dekker

unread,
Aug 24, 2020, 12:58:47 PM8/24/20
to bug-...@gnu.org
Op 24-08-20 om 15:57 schreef Chet Ramey:
> I sometimes think I should have stuck with converting PROMPT_COMMAND to
> an array. Either way, there's going to be a transition, and maybe that
> would have been the easiest.

Is it too late? I think that would actually be cleaner than adding a
separate array, per Koichi's report.

One problem is that if a script does the obvious

PROMPT_COMMAND+=("some command here")

if PROMPT_COMMAND is not yet set, then it starts adding at array index
0, so a subsequent traditional usage from some other script

PROMPT_COMMAND="some command here"

would overwrite it. So array usage should not use the 0 index. To avoid
using the 0 index, one possibility is:

PROMPT_COMMAND[$(( ${#PROMPT_COMMAND[@]} + 1 ))]="some command here"

which, if PROMPT_COMMAND is unset, starts adding at index 1, not 0, and
otherwise acts identically. However, 'set -u'/'set -o nounset' kills
that. That option makes the ${#PROMPT_COMMAND[@]} expansion error out if
there are no array elements (even though ${#@} works with no positional
parameters). It's also an unwieldy command. So maybe that idea is not
the best.

Another way to avoid using the 0 index, which is 'set -u' compatible,
would be

PROMPT_COMMAND=${PROMPT_COMMAND-}
PROMPT_COMMAND+=("some command here")

The first command sets PROMPT_COMMAND[0] to the empty value if it
doesn't exist yet, and otherwise leaves it unchanged. It's a bit of an
ugly hack though.

But then, maybe it's best if bash itself just sets PROMPT_COMMAND[0] to
the empty value on initialisation. IMO that would be a reasonably clean
and reliable way to ensure a smooth transition.

Just my 2¢,

- M.

--
|| modernish -- harness the shell
|| https://github.com/modernish/modernish
||
|| KornShell lives!
|| https://github.com/ksh93/ksh

Chet Ramey

unread,
Aug 24, 2020, 3:37:28 PM8/24/20
to Martijn Dekker, bug-...@gnu.org, chet....@case.edu
On 8/24/20 12:58 PM, Martijn Dekker wrote:
> Op 24-08-20 om 15:57 schreef Chet Ramey:
>> I sometimes think I should have stuck with converting PROMPT_COMMAND to
>> an array. Either way, there's going to be a transition, and maybe that
>> would have been the easiest.
>
> Is it too late? I think that would actually be cleaner than adding a
> separate array, per Koichi's report.

We're not "adding" anything. Bash just looks for this variable and reacts
if it finds it. It's not a special variable, and bash doesn't create it if
it doesn't exist.

What I mean is looking for PROMPT_COMMAND as happens now, and reacting a
different way if it's an array variable. That would resolve the existing
assignment issues, but open up the separate issues you describe.

Chet

Koichi Murase

unread,
Aug 24, 2020, 3:37:29 PM8/24/20
to bug-...@gnu.org
2020-08-25 1:59 Martijn Dekker <mar...@inlv.org>:
> Is it too late? I think that would actually be cleaner than adding a
> separate array, per Koichi's report.

If it's not too late to change, converting PROMPT_COMMAND to an array
looks better to me too. As for the problem of scripts doing
`PROMPT_COMMAND=command', as suggested in the last paragraph from
Martijn, I think it is enough to initialize PROMPT_COMMAND[0] by an
empty string.

--
Koichi

Martijn Dekker

unread,
Aug 24, 2020, 3:53:54 PM8/24/20
to bug-...@gnu.org
Op 24-08-20 om 20:37 schreef Chet Ramey:
> On 8/24/20 12:58 PM, Martijn Dekker wrote:
>> Op 24-08-20 om 15:57 schreef Chet Ramey:
>>> I sometimes think I should have stuck with converting PROMPT_COMMAND to
>>> an array. Either way, there's going to be a transition, and maybe that
>>> would have been the easiest.
>>
>> Is it too late? I think that would actually be cleaner than adding a
>> separate array, per Koichi's report.
>
> We're not "adding" anything. Bash just looks for this variable and reacts
> if it finds it. It's not a special variable, and bash doesn't create it if
> it doesn't exist.


So now you're adding code that looks for an array. Which is something
other than nothing.

Granted, my language wasn't very precise, but I'm fairly confident that
my intent was understandable.

> What I mean is looking for PROMPT_COMMAND as happens now, and reacting a
> different way if it's an array variable. That would resolve the existing
> assignment issues, but open up the separate issues you describe.


But I also suggested a way of avoiding those issues: initialise
$PROMPT_COMMAND a.k.a. ${PROMPT_COMMAND[0]} as empty.

Chet Ramey

unread,
Aug 24, 2020, 3:58:46 PM8/24/20
to Martijn Dekker, bug-...@gnu.org, chet....@case.edu
On 8/24/20 3:53 PM, Martijn Dekker wrote:

>> What I mean is looking for PROMPT_COMMAND as happens now, and reacting a
>> different way if it's an array variable. That would resolve the existing
>> assignment issues, but open up the separate issues you describe.
>
>
> But I also suggested a way of avoiding those issues: initialise
> $PROMPT_COMMAND a.k.a. ${PROMPT_COMMAND[0]} as empty.

Sure. The burden to do that is on the user. As long as startup scripts do
that -- which they don't do now -- there's no problem.
Reply all
Reply to author
Forward
0 new messages