Skip to content

Instantly share code, notes, and snippets.

@StrangeRanger
Last active April 6, 2023 18:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StrangeRanger/12e9b8292dc0d499a4fea42fdda93c03 to your computer and use it in GitHub Desktop.
Save StrangeRanger/12e9b8292dc0d499a4fea42fdda93c03 to your computer and use it in GitHub Desktop.
spinning-waiting-stick.sh
#!/usr/bin/env bash
#
# Provides two different methods that can be used to display a spinning stick that will
# continue to spin until a specific process is finished running.
#
# NOTE: 'method_two' is notiblely faster than 'method_one'. Despite this, it does not
# speak for the method's actual speed. That is dependent on how you use and
# implement the methods. For the case of the examples that I provided, 'method_one'
# is slower because I have it check if the incremented number is greater than or
# equal to the specified stopping number, for every iteration of the for loop.
# Though this might be obvious, checking during every iteration is not efficient
# and should not be implemented in an actual program, unelss you have a good
# reason. The only reason that I have 'method_one' do this, is because it allows
# me to provide a simple example of situations in which either method could be
# used.
#
########################################################################################
#### [ Variables ]
## Change the color of the output text.
green="$(printf '\033[0;32m')"
blue="$(printf '\033[0;34m')"
nc="$(printf '\033[0m')"
clrln="$(printf '\r\033[K')"
#### End of [ Variables ]
########################################################################################
#### [ Functions ]
#### Below are the two different methods (that I personally use) that can be used to
#### display a spinning stick.
########################################################################################
#### [[ method_one ]]
#### Using 'method_one' is ideal in all situations, with an exception of one. In a
#### situation where a variable is modified with the intent to be used later in the
#### code, 'method_two' is much more ideal. The reason for this is because when a
#### variable is modified orcreated inside of a subprocess/subshell, the changes to that
#### variable will be lost once the subprocess exits. For more information, refer to the
#### following link: https://github.com/koalaman/shellcheck/wiki/SC2031
method_one() {
# Variable to be incremented.
local var=0
# The integer to stop itterating at.
local stop_at=1000000
####
# Function Info: Until a specified process is finished running, a spinning stick
# will output to the terminal, in place.
#
# Parameters:
# $1 - required
# Process ID of some command/function.
####
waiting() {
local spin="-\|/"
local i=0
## If the process $1 exists, continuously output a new character inside of $spin
## to create the illusion of a spinning stick.
while ps -p "$1" &>/dev/null; do
i=$(( (i+1) %4 ))
# NOTE: Here is a labeled version, describing how the below variable
# expansion works: '${parameter:offset:length} -> ${spin:$i:1}'
# You can find more information at the following link:
# https://mywiki.wooledge.org/BashGuide/Parameters#Parameter_Expansion
printf "%sPerforming action: %s" "$clrln" "${spin:$i:1}"
sleep .1
done
}
## Recursively store the new value of $i, into $var.
## NOTE: This for statement is executed as a background process.
## NOTE 2: This for statement represents the actions to be performed and waited
## upon.
for ((i = 0; i < (stop_at + 1); i++)); do
var="$i"
## Once $i is greater than or equal to the value of $stop_at, output the value
## of $var.
if ((i >= stop_at)); then
# Output the new value of $var.
printf "%sOutput of 'var': %s\n" "$clrln" "${green}${var}${nc}"
fi
done &
# Execute the 'waiting' method, passing along the Process ID of the for statement.
waiting "$!"
echo -e "${green}==>${nc} Done with 'method_one'\n"
}
### End of [[ method_one ]]
########################################################################################
#### [[ method_two ]]
#### As mentioned in the description of 'method_one', 'method_two' is ideal in
#### situations were a variable is being modified with the intent of being used later in
#### the code.
method_two() {
# Variable to be incremented.
local var=0
####
# Function Info: Until a specified process is finished running, a spinning stick
# will output to the terminal, in place.
####
waiting() {
local spin="-\|/"
local i=0
## While true, continuously output a new character inside of $spin to create the
## illusion of a spinning stick.
while true; do
i=$(( (i+1) %4 ))
# NOTE: Here is a labeled version, describing how the below variable
# expansion works: '${parameter:offset:length} -> ${spin:$i:1}'
# You can find more information at the following link:
# https://mywiki.wooledge.org/BashGuide/Parameters#Parameter_Expansion
printf "%sPerforming action: %s" "$clrln" "${spin:$i:1}"
sleep .1
done
}
# Execute the 'waiting' method as a background process.
waiting &
# Save the Process ID of the executed function ('waiting').
local _PID=$!
## Recursively store the new value of $i, into $var.
## NOTE: This represents the actions to be performed and waited upon.
for i in {1..1000000}; do
var="$i"
done
# Once the for loop has finished, kill the process executing the 'waiting' method.
kill -9 $_PID &>/dev/null
# Output the new value of $var.
printf "%sOutput of 'var': %s\n" "$clrln" "${green}${var}"
echo -e "==>$nc Done with 'method_two'\n"
}
#### End of [[ method_two ]]
########################################################################################
#### [ Main ]
#### Below puts both methods/examples to use.
echo -e "$blue==>$nc Executing 'method_one'"
method_one
echo ""
echo -e "$blue==>$nc Executing 'method_two'"
method_two
#### End of [ Main ]
########################################################################################
@StrangeRanger
Copy link
Author

Project Tracker

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment