Reputation: 1
I am writing a Bash function that only works the second time I call it. What it's supposed to do is write a string of characters using an easing function so that the first part of the string gets displayed quickly, then slows down to complete the final words of the string. The caveat is that it should show colors, using tput defined standard terminal colors.
It works great -- on the second run. When it's first run, it shows the escape sequences in the terminal, and not the colors I'm calling for.
Here's my code:
#!/usr/bin/env bash
# Easing function: ease_in_expo
ease_in_expo() {
local t=$1
echo "scale=4; if ($t == 0) 0 else 1 * e(10 * ($t - 1))" | bc -l
}
animate_text_with_ease_in_expo() {
text="$1"
delay="$2"
# Regular Colors
RESET=$(tput sgr0) # Text Reset
BLACK=$(tput setaf 0) # Black
RED=$(tput setaf 1) # Red
GREEN=$(tput setaf 2) # Green
YELLOW=$(tput setaf 3) # Yellow
BLUE=$(tput setaf 4) # Blue
PURPLE=$(tput setaf 5) # Purple
CYAN=$(tput setaf 6) # Cyan
WHITE=$(tput setaf 7) # White
for ((i = 0; i < ${#text}; i++)); do
progress=$(ease_in_expo "$((i + 1)) / ${#text}")
sleep "$(echo "$delay * $progress" | bc -l)"
# Write the string to output
echo -n "${text:$i:1}"
done
}
animate_text_with_ease_in_expo "Tutti ${RED}frutti${RESET}, oh ${CYAN}rooty${RESET}; A wop bop b-luma b-lop bam ${GREEN}boom." 0.30
Can ye Bash gurus point me on the right path to getting these color variables loaded on the first run of the function?
Tried defining color variables as ANSI escape sequences, as well as tput setaf's. Tried putting the color definitions in a separate function, calling that function first, and then callback to my animate_text_with_ease_in_expo function. Tried reloading the "text" variable by text=$text after the color definitions are declared.
Output on first run:
Tutti \033[0;31mfrutti, oh \033[0;36mrooty; A wop bop b-luma b-lop bam boom.
Output on second run:
Tutti frutti, oh rooty; A wop bop b-luma b-lop bam boom.
(The above, with appropriate colors added)
The above code is all written into a Bash script called "string-problem.sh". Once entering the directory the script is in, I am calling it via:
. string-problem.sh
Upvotes: 0
Views: 140
Reputation: 204477
As others have pointed out, you can't use a variable in the calling code that's set in the function being called:
$ foo() { local var=hungry; echo "$*"; }
$ foo "I am $var"
I am
$ foo "I am \$var"
I am $var
$ foo 'I am $var'
I am $var
If you're completely in control of the values being passed to that function, though, then you could escape the $
or otherwise stop the shell from expanding the variable when calling the function and then eval
the string passed in so the variable isn't expanded upon the function call, it's expanded when eval
ed inside the function:
$ foo() { local var=hungry; eval echo "$*"; }
$ foo "I am $var"
I am
$ foo "I am \$var"
I am hungry
$ foo 'I am $var'
I am hungry
You should really have your color variables declared outside of your function though so you don't have to call tput
9 times every time you call your function!
Upvotes: 1
Reputation: 141758
In short:
func() {
hello=world
}
func "${hello}"
hello
is getting set inside the function. At the time of "${hello}"
variable hello
is not set, so it expands to nothing.
Just set the variables, once.
# Regular Colors
RESET=$(tput sgr0) # Text Reset
BLACK=$(tput setaf 0) # Black
RED=$(tput setaf 1) # Red
GREEN=$(tput setaf 2) # Green
YELLOW=$(tput setaf 3) # Yellow
BLUE=$(tput setaf 4) # Blue
PURPLE=$(tput setaf 5) # Purple
CYAN=$(tput setaf 6) # Cyan
WHITE=$(tput setaf 7) # White
animate_text_with_ease_in_expo() {
text="$1"
delay="$2"
...
}
animate_text_with_ease_in_expo "Tutti ${RED}frutti${RESET}, oh ${CYAN}rooty${RESET}; A wop bop b-luma b-lop bam ${GREEN}boom." 0.30
Upvotes: 2