You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
242 lines
7.5 KiB
242 lines
7.5 KiB
#!/bin/sh |
|
# Bare Metal Alchemist, 2022 |
|
|
|
############################################# |
|
# Lead - ♄ # |
|
############################################# |
|
|
|
# The most basic ingredient in an Alchemy recipe, lead is used in all |
|
# recipes in this repository to standardize some simple things that I |
|
# rely on to make scripts concise and pleasant to use |
|
|
|
# --------------- Escape Codes --------------- |
|
# These constants are used to add color and text formatting to the |
|
# terminal's output -- Further reading: ANSI Escape Codes |
|
RED="\e[0;31m" |
|
GREEN="\e[0;32m" |
|
BLUE="\e[0;34m" |
|
BOLD="\e[1m" |
|
ITALIC="\e[3m" |
|
ULINE="\e[4m" |
|
RESET="\e[0m" |
|
|
|
# TODO -- there are actually a lot of ANSI codes that can be used |
|
# 0 - Reset (normal attributes) |
|
# 1 - Bold or increased intensity |
|
# 2 - Faint (opposite of bold) |
|
# 3 - Italic |
|
# 4 - Underline |
|
# 5 - Blink slowly |
|
# 6 - Blink quickly |
|
# 7 - Swap foreground and background |
|
# 8 - Conceal |
|
# 9 - Cross-out |
|
# 10 - Default font |
|
# 11-19 - Alternate fonts |
|
# 20 - Fraktur font |
|
# 21 - Bold off or double underline |
|
# 22 - Bold and faint off |
|
# 23 - Italic and fraktur off |
|
# 24 - Underline off |
|
# 25 - Blink off |
|
# 27 - Undo foreground and background swapping |
|
# 28 - Conceal off |
|
# 29 - Cross-out off |
|
# 39 - Default text color |
|
# 49 - Default background color |
|
# 51 - Framed |
|
# 52 - Encircled |
|
# 53 - Overlined |
|
# 54 - Frame and encircle off |
|
# 55 - Overline off |
|
|
|
# TODO -- these should be implemented as part of the syntax for "say" |
|
|
|
# --------------- Traps --------------- |
|
|
|
# Traps, in the case of shell scripting, listen for certain signals |
|
# that are broadcast by the system and execute a command in response |
|
|
|
# We only want these to activate if we're running a recipe, so we |
|
# check to see if we're running a "shell inside of a shell" |
|
if [[ $SHLVL -gt 1 ]]; then |
|
# Make sure that ctrl+C consistently exits the script |
|
trap "exit" INT |
|
# Give informative error messages when we receive ERR |
|
trap 'say "${RED}Oops...${RESET} Something went wrong on line $LINENO of this script. Exit code was $?" >&2' ERR |
|
fi |
|
|
|
# --------------- Functions --------------- |
|
|
|
# Coding Moment: generally, whenever you see something with brackets |
|
# at the end of it, like this() or like(this), it's a function! |
|
# It takes inputs and gives (or does) something as an output |
|
|
|
# --------------- Input/Output --------------- |
|
|
|
# 'say' is a simple function that imitates "echo" |
|
# This needs to be built out way more! Replace echo for POSIX compatibility |
|
say() { |
|
printf "%b\n" "${1}" |
|
} |
|
|
|
ask_for() { |
|
if [ ${#} -eq 0 ]; then |
|
say "To use this command, you need to pass the variable you want," |
|
say "and then add as string of text to ask for it if you want. Example:\n" |
|
say "ask_for RESPONSE \"Could you give me a RESPONSE please?\"" |
|
say "" |
|
say "Afterwards, you'll be able to use \$RESPONSE as a variable," |
|
say "and ${ITALIC}say \$RESPONSE${RESET} will respond with your entry" |
|
return 0 |
|
fi |
|
|
|
if [ -n "${2}" ]; then |
|
printf "%b" "${2}" |
|
fi |
|
|
|
read ${1} |
|
} |
|
|
|
# --------------- Environment Setup --------------- |
|
|
|
# If there's an env file, export it's contents to the environment |
|
source_env() { |
|
if [ -f .env ]; then |
|
export $(grep -v '^#' .env | xargs) |
|
else |
|
if [ -z $ALCHEMY ]; then |
|
say "No .env file, this might cause some issues..." |
|
fi |
|
fi |
|
} |
|
|
|
# This is how we call a function that we have already defined. |
|
# This one takes no arguments (words after the function name |
|
source_env |
|
|
|
# --------------- Program Installation --------------- |
|
|
|
# Checks to see if we can use a command or not |
|
check_for() { |
|
command -v "$1" >/dev/null |
|
} |
|
if [ "$EUID" -eq 0 ]; then |
|
echo -e "${RED}Woah there!${RESET} Seems you're running this script as a superuser." |
|
echo "" |
|
echo "That might cause some issues with permissions and whatnot. Run this script as your default user (without sudo) and I'll ask you when I need superuser permissions" |
|
echo "" |
|
exit 1 |
|
fi |
|
|
|
|
|
# This one installs utilities to your OS (If you need them!) |
|
install_if_needed() { |
|
for package in "$@" # $@ means "all the arguments you passed |
|
do |
|
case $DISTRO in |
|
"debian") |
|
# TODO Better installation detection than check_for |
|
if [ -z $(check_for $package) ]; then |
|
say "installing $package" |
|
sudo apt install -y $package |
|
else |
|
say "$package already installed!" |
|
fi |
|
;; |
|
"arch") |
|
if pacman -Qi $package &>/dev/null; then |
|
say "$package already installed!" |
|
else |
|
say "installing $package" |
|
sudo pacman -S $package --noconfirm --needed |
|
fi |
|
;; |
|
"fedora") |
|
# TODO Better installation detection than "check_for" |
|
if [ -z $(check_for $package) ]; then |
|
say "installing $package" |
|
sudo dnf install -y $package |
|
else |
|
say "$package already installed!" |
|
fi |
|
;; |
|
"mac") |
|
# TODO Better installation detection than "check_for" |
|
if [ -z $(check_for $package) ]; then |
|
say "installing $package" |
|
brew install $package |
|
else |
|
say "$package already installed!" |
|
fi |
|
;; |
|
esac |
|
done |
|
} |
|
|
|
|
|
# --------------- Memory --------------- |
|
# These two functions might look like gibberish because we're using regex, |
|
# short for REGular EXpression. It's a form of matching text to a pattern. |
|
|
|
|
|
# It takes values and stores them away in the env for later reference |
|
forget() { |
|
DOTENV_ENTRY=$(cat .env | grep ^${1}\=) |
|
if [ -n "$DOTENV_ENTRY" ]; then |
|
unset ${1} |
|
sed -i "/^${1}.*$/d" .env |
|
else |
|
say "I already don't remember ${BLUE}${1}${RESET}..." |
|
fi |
|
|
|
# Once we've made changes, we need to make sure we're up to date |
|
source_env |
|
} |
|
|
|
remember() { |
|
KEY=$(say ${1} | cut -d'=' -f 1) |
|
VALUE=$(say ${1} | cut -d'=' -f 2) |
|
|
|
if [[ ! $KEY =~ ^[A-Z_]+$ ]]; then |
|
say "Keys must consist only of capital letters and underscores" |
|
fi |
|
|
|
if [[ ! $VALUE =~ ^[A-Za-z0-9/_.:-]+$ ]]; then |
|
say "Valid characters for env values: letters, numbers, \".\",\"/\",\"_\"",\":\", \"-\" |
|
fi |
|
|
|
# If we're setting a valid key/value pair |
|
if [[ ${1} =~ ^[A-Z_]+\=[A-Za-z0-9/._:-]*$ ]]; then |
|
|
|
DOTENV_ENTRY=$(cat .env | grep ${KEY}) |
|
# If something already exists and we're trying to set it to something new |
|
if [ -n "$DOTENV_ENTRY" ] && [ "$DOTENV_ENTRY" != "$1" ]; then |
|
say "I'm trying to remember ${BLUE}${1}${RESET}, but..." |
|
say "" |
|
say "${BLUE}${DOTENV_ENTRY}${RESET}" |
|
say "This has already been defined in the .env file!" |
|
say "" |
|
ask_for overwrite "would you like to overwrite it? ${BLUE}(y/n)${RESET} " |
|
case $overwrite in |
|
"y" | "Y") |
|
unset ${KEY} |
|
sed -i "/^${KEY}.*$/d" .env |
|
echo "${1}" >> .env |
|
export ${1} |
|
;; |
|
esac |
|
elif [ -z "$DOTENV_ENTRY" ]; then |
|
unset ${KEY} |
|
echo "${1}" >> .env |
|
export ${1} |
|
fi |
|
fi |
|
|
|
# Once we've made changes, we need to make sure we're up to date |
|
source_env |
|
} |
|
|
|
LEAD=1 |
|
|
|
# Confirm? Something to automate the y/n dialog
|
|
|