What I want to do is to call a function in PS1 to update a variable inside the function. Then I like to use that variable to add another line to PS1. Like bellow:
my_func(){
var="_RED_"
echo "hello in red"
}
PS1="\[\033]0;\w\007\]"
PS1+='$(my_func)'
if [ $var = "_RED_" ]; then # here I want to use that var
PS1+="\[$(tput setaf 124)\] red"
fi
The reason for doing this is to bring non-printable characters \[ and \] out of the function to prevent from overlapping long lines that is caused by \[ \]
You can absolutely update global variables inside a shell function -- all assignments inside functions modify global variables unless local or declare variables were used to create a new scope.
The problem here, however, is that you aren't running your function in the same shell process as the code that later tries to read var (though whether it is in fact "later" or not is a separate issue)! When you use command substitution -- the $() in $(my_func) -- you're creating a new forked-off subprocess to run that function. When that subprocess exits, all changes to variable values it's made are lost with it.
However, you can work around that by not using command substitution at all. Consider the below, which uses the PROMPT_COMMAND hook to assign PS1:
# code to run before each time a prompt is printed
PROMPT_COMMAND='build_ps1_func'
# rewrite your function to write to a named variable, not stdout
my_func(){
local outvar=$1; shift # named variable to write stdout to
var="_RED_" # hardcoded global to update, per question
printf -v "$outvar" '%s' "hello in red"
}
build_ps1_func() {
local your_str # define your_str as a local variable
my_func your_str # call my_func, telling it to write output to your_str
PS1="\[\033]0;\w\007\]"
PS1+="$your_str"
if [ $var = "_RED_" ]; then # using that variable here
PS1+="\[$(tput setaf 124)\] red"
fi
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With