re: your solution of a loop every second: you could write to a file in /tmp, instead of in your home directory. And PS1=$(customW)$(< ~/.ps1)\$ '
would save a fork/exec of cat
.
re: the original question: how to get an async update to PS1
:
To start an async write to PS1
:
- set
PROMPT_COMMAND
to a function that checks if the data is available.
- If it is, update
PS1
and unset PROMPT_COMMAND
- If not, leave
PS1
with the old or placeholder value.
Use a file in /tmp
for the async IO to write to, and PROMPT_COMMAND
to read from.
I think this should work.
Your question is a bit rambling. I'll answer what seems to be the central part, on the difference between ksh and bash that you observe.
You have encountered what is probably the #1 incompatibility between ksh and bash when it comes to scripts. ATT ksh (both ksh88 and ksh93) and zsh execute the last (rightmost) command in a pipeline in the parent shell, whereas other shells (Bourne, ash, bash, pdksh, mksh) execute all the commands including the last one in a subshell.
Here is a simple test program:
msg="a subshell"
true | msg="the parent shell"
echo "This shell runs the last command of a pipeline in $msg"
In ATT ksh and zsh, the second assignment to msg
is executed in the parent shell so the effect is visible after the pipeline. In other shells, this assignment is executed in a subshell so the first assignment remains in place in the parent.
A workaround is to execute the rest of the script in the pipeline. This is a common idiom for reading data and doing some processing afterward:
output_some_stuff | {
var=
while IFS= read -r line; do
var=$(process "$line")
done
use "$var"
}
You appear to have run into a ksh bug. I recommend upgrading to a non-buggy version. If that isn't possible, try Stephane Chazelas's workaround. While you can try running your scripts in bash, it is not (and does not pretend to be) a drop-in replacement for ksh; there are plenty of ksh features that bash doesn't have (and vice versa). Bash and ksh are only compatible in their POSIX core and some other central features (in particular arrays, [[ … ]]
, and local variables in functions declared by typeset
).
You could also try zsh, which when invoked as ksh
behaves in a way that's a bit closer to ksh than bash is. You may nonetheless run into incompatibilities.
Best Answer
One potential approach would be to put a
while...read
construct inside your functions which would process any data that came into the function through STDIN, operate on it, and then emit the resulting data back out via STDOUT.Care will need to be spent with how you configure your
while ..read..
components since they'll be highly dependent on the types of data they'll be able to reliably consume. There may be an optimal configuration that you can come up with.Example
Here's each function by itself.
Here they are when we use them together.
They can take various styles of input.