Browse Source

Refactored menu spell works!

main
deicidus 2 years ago
parent
commit
796a2dfe9b
  1. 18
      README.md
  2. 19
      spells/bind-summary
  3. 44
      spells/bind-tome
  4. 0
      spells/cantrips/ask
  5. 30
      spells/cantrips/ask_Yn
  6. 49
      spells/cantrips/assertions
  7. 6
      spells/cantrips/await-keypress
  8. 41
      spells/cantrips/bg_log
  9. 15
      spells/cantrips/check-wizard
  10. 52
      spells/cantrips/clear-area
  11. 45
      spells/cantrips/clear-input-lines
  12. 24
      spells/cantrips/colors
  13. 51
      spells/cantrips/current-input-lines
  14. 2
      spells/cantrips/cursor
  15. 0
      spells/cantrips/cursor-blink
  16. 54
      spells/cantrips/fathom-cursor
  17. 70
      spells/cantrips/fathom-terminal
  18. 42
      spells/cantrips/max-length
  19. 97
      spells/cantrips/menu
  20. 29
      spells/cantrips/move-cursor
  21. 8
      spells/cantrips/say
  22. 15
      spells/cantrips/wizard-eyes
  23. 4
      spells/detect-distro
  24. 0
      spells/hashchant
  25. 57
      spells/hourly-bell
  26. 18
      spells/menu/fathom-cursor
  27. 22
      spells/menu/fathom-terminal
  28. 27
      spells/menu/max-length
  29. 196
      spells/rosetta-stone

18
README.md

@ -47,6 +47,22 @@ On your AO adventure, there are three different tutorials which gradually unlock
ao-mud contains unlockable menus and terminal shortcuts that make using the terminal easier and more fun. To skip ahead and turn some of these features on without unlocking them in tutorial mode, you can use a Save Code that you received from an earlier playthrough. To use a Save Code, open the AO main menu, select "Load Saved Game", enter your Save Code, and press Enter. ao-mud contains unlockable menus and terminal shortcuts that make using the terminal easier and more fun. To skip ahead and turn some of these features on without unlocking them in tutorial mode, you can use a Save Code that you received from an earlier playthrough. To use a Save Code, open the AO main menu, select "Load Saved Game", enter your Save Code, and press Enter.
# Folder Structure
The structure of this project right now is simple. There is a `spells` folder containing spells you can cast. This folder has a subfolder called `cantrips`, which contains tiny spells that are used to compose larger spells that aren't meant to be used on their own.
# Conventions
1. As a naming convention, spells that use hypens (-) in their name instead of spaces are set up to be run as scripts in the terminal (even if they are cantrips that will merely inform you not to do so). Spells that include a function that is not accessible by executing the script in the terminal are named with underscores (_) in their names. Open these (or any) spells in a text editor to see what they contain.
2. Terminal commands that simply output a single value should output the bare value by default. A --verbose or -v flag should be included on all such functions to include a description field such as "Cursor X:".
3. Cantrips should be so atomic so as to include a single value, if possible. This reduces parsing that must be done by those using the cantrip.
# How to Cast a Spell
To cast a spell, `cd` into the spells directory. Then, the first time you cast the spell, `chmod +x spellname`. Then `./spellname` to cast.
# How to Begin # How to Begin
To start your AO adventure, type ./ao in this directory. A tutorial is coming soon. For now, explore the `./spells` directory. Try reading or running the `rosetta-stone` script or the `jump` script.

19
spells/bind-summary

@ -0,0 +1,19 @@
#!/bin/bash
# Check that a folder path was provided as an argument
if [ "$#" -ne 1 ]; then
echo "Error: Please provide a folder path as an argument."
exit 1
fi
# Create a text file with the same name as the folder
folder_name=$(basename "$1")
text_file="$folder_name.txt"
# Read all the filenames in the folder and put them in the text file
# Todo: Remove the folder/ name from before the filename
for filename in "$1"/*; do
echo "$filename" >> "$text_file"
done
echo "Text file created: $text_file"

44
spells/bind-tome

@ -0,0 +1,44 @@
#!/bin/bash
# The Tome Fusion Spell
#
# This powerful spell allows you to magically bind together the scattered pages of a tome, creating a single
# cohesive text file. Simply provide the path to the folder containing the sliced pages as an argument, and the
# spell will do the rest. If you want to destroy the original pages after fusing them together, use the -d flag.
#
# Usage: ./fuse_text_file_lines.sh path/to/folder [-d]
# todo: see if we can shorten or replace this script with `cat folder/* > file.txt` which simply cats a folder of scripts together (no separators tho)
# Check that a folder path was provided as an argument
if [ "$#" -ne 1 ]; then
echo "Error: Please provide a folder path as an argument."
exit 1
fi
# Create a new text file with the same name as the folder
folder_name=$(basename "$1")
text_file="$folder_name.txt"
touch "$text_file"
# Read all the files in the folder and append their content to the text file, with a special line marking the beginning and end of each file
for file in "$1"/*; do
filename=$(basename "$file")
echo "----- $filename -----" >> "$text_file"
cat "$file" >> "$text_file"
echo "----- End of $filename -----" >> "$text_file"
done
echo "Text file created: $text_file"
# Check if the delete flag (-d) was provided as an argument
while getopts "d" opt; do
case $opt in
d)
# If the delete flag was provided, delete all the original files
for file in "$1"/*; do
rm "$file"
done
echo "Original files deleted."
;;
esac
done

0
spells/ask → spells/cantrips/ask

30
spells/cantrips/ask_Yn

@ -0,0 +1,30 @@
#!/usr/bin/env sh
# Define ask_Yn, which asks a yes or no question and saves the result in the given variable name (defaults to yes)
# Takes one arg, which is the variable name where the result will be saved
# No is 0 and Yes is 1
source say
ask_Yn() {
if [ -n "$2" ]; then
say_inline "$2 (Y/n): "
fi
STTY_CONFIG=$(stty -g) # Save current stty config
stty raw -echo # Disable echo
ANSWER=$(head -c 1) # Scrape terminal input
stty $STTY_CONFIG # Restore stty config
if [ "$ANSWER" != "${ANSWER#[Nn]}" ]; then
say "N"
export "${1}=0"
else
say "Y"
export "${1}=1"
fi
}
# Check if the script is being called from another script
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
# If not, call the function
ask_Yn "$@"
fi

49
spells/cantrips/assertions

@ -0,0 +1,49 @@
#!/usr/bin/env bash
# Functions unit tests, to test assertions. The point of an assertion is to crash if it isn't true.
# Usage:
# assert_equal $value1 $value2
# assert_output "./scriptname" "expected output"
# assert_success $(command)
# assert_failure "./scriptname"
# Helper function to compare two values
assert_equal() {
if [ "$1" != "$2" ]; then
echo "Assertion failed: $1 != $2"
exit 1
fi
}
# Helper function to compare the output of a given command to an expected value
assert_output() {
local command=$1
local expected_output=$2
echo com $command
echo exp $expected_output
echo out $($command)
if [ "$($command)" != "$expected_output" ]; then
echo "Test failed: $command"
exit 1
fi
}
# Helper function to run a command and check for a non-zero exit status
assert_success() {
local command=$1
if ! $command; then
echo "Test failed: $command"
exit 1
fi
}
# Helper function to run a command and check for a zero exit status
assert_failure() {
local command=$1
if $command; then
echo "Test failed: $command"
exit 1
fi
}

6
spells/menu/await_keypress → spells/cantrips/await-keypress

@ -5,12 +5,10 @@
# todo: Tab key not distinguished from Enter (\t case does not work) # todo: Tab key not distinguished from Enter (\t case does not work)
# Define the function to handle key presses # Define the function to handle key presses
handle_key() { await_keypress() {
# Read a single character from the terminal # Read a single character from the terminal
read -s -n1 key read -s -n1 key
#echo $key > ./invisible_character # debug
# Check the value of the key # Check the value of the key
case "$key" in case "$key" in
# Enter key # Enter key
@ -70,5 +68,5 @@ handle_key() {
# Check if the script is being executed or sourced, if executed then call the function # Check if the script is being executed or sourced, if executed then call the function
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
handle_key await_keypress
fi fi

41
spells/cantrips/bg_log

@ -0,0 +1,41 @@
#!/bin/sh
# bg_log: a script to output a message from a background process, while taking
# into account the user's current input and preserving it.
#
# Cast this spell to send a message from a background process to the terminal,
# without interrupting or overwriting the user's input.
# todo: refactor this to use the cursor file
bg_log() {
# Save the current cursor position
printf '\033[s'
# Calculate the number of lines used by the user's input
lines=$(current_input_lines)
# Move the cursor up the number of lines used by the user's input
printf '\033[%dA' "$lines"
# Clear the current line
printf '\033[2K'
# Output the message
printf '%s\n' "$@"
# Clear the current line
printf '\033[2K'
# Move the cursor down the number of lines used by the user's input
printf '\033[%dB' "$lines"
# Restore the cursor position
printf '\033[u'
}
# Check if the script is being executed or sourced
if [ "$0" = "$BASH_SOURCE" ]; then
# Script is being executed, call the bg_log function to output a message
bg_log $1
fi

15
spells/cantrips/check-wizard

@ -0,0 +1,15 @@
#!/usr/bin/env sh
# Asks the user if they are a wizard and exports an environment variable with the result
# Todo next: Add remember/recall functions so that wizard status is remembered after first ask
check_wizard() {
ask_Yn WIZARD "First, let me ask, are you a wizard?"
export "WIZARD=$WIZARD"
}
# Check if the script is being called from another script
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
# If not, call the function
check_wizard "$@"
fi

52
spells/cantrips/clear-area

@ -0,0 +1,52 @@
#!/usr/bin/env sh
# todo: this script doesn't work at alll for some reason. clear_area is being called but the cursor isn't moving around correctly
# This magical spell clears a specific area of the terminal window, leaving behind a clean and clear space.
# Usage: cast_clear_area x y width height
# The area to be cleared is specified by its top left corner (x, y) and its width and height.
# Define the function to clear the specified area
clear_area() {
x=$1
y=$2
width=$3
height=$4
# Move the cursor to the top left corner of the area to be cleared
move-cursor $x $y
#echo -en "\033[$y;$xH"
# Clear the area by outputting a space and then moving the cursor back
i=0
while [ $i -lt $height ]; do
j=0
while [ $j -lt $width ]; do
echo -n " "
j=$((j + 1))
done
# Move the cursor back to the start of the line
#echo -en "\033[$((y + i));$xH"
move-cursor $x $((y + i))
i=$((i + 1))
done
}
# Unit test--this doesn't work yet, but I tseted clear_area manually and it works
test_clear_area() {
. assertions
initial_x=$(fathom-cursor -x)
initial_y=$(fathom-cursor -y)
move_cursor 5 5
clear-area 3 3
move_cursor 5 5
assert_equal "$(tput cup 5 5; tput sc; tput cup $initial_y $initial_x)" ""
move_cursor $initial_x $initial_y
echo "All tests passed"
}
# Check if the script is being called from another script
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
# If not, call the function and pass it the command line arguments
clear_area "$@"
fi

45
spells/cantrips/clear-input-lines

@ -0,0 +1,45 @@
#!/bin/sh
# A cantrip to clear the user's current input lines in the terminal, including
# the terminal prompt.
#
# Cast this spell to erase the user's current input lines, leaving the terminal
# ready for a new command.
# todo: modify this to use our cursor file
clear_input_lines() {
# Save the current cursor position
printf '\033[s'
# Move the cursor to the beginning of the line
printf '\033[1G'
# Clear the current line
printf '\033[2K'
# Calculate the number of lines used by the user's input
lines="$(current_input_lines)"
# Clear the remaining lines
i=1
while [ "$i" -lt "$lines" ]; do
# Move the cursor down one line
printf '\033[1B'
# Clear the current line
printf '\033[2K'
# Increment the counter
i=$(( i + 1 ))
done
# Restore the cursor position
printf '\033[u'
}
# Check if the script is being executed or sourced
if [ "$0" = "$BASH_SOURCE" ]; then
# Script is being executed, call the clear_input_lines function
clear_input_lines
fi

24
spells/colors → spells/cantrips/colors

@ -2,7 +2,10 @@
# This magical knowledge serves as a colorful palette of hues and shades, # This magical knowledge serves as a colorful palette of hues and shades,
# granting control over the appearance of the terminal. # granting control over the appearance of the terminal.
# Use these variables to add a splash of color to your scripts. # Use these variables to add color to your writing.
# Example: echo -en "${RED}Error:${RESET} An error message."
# This script contains all color codes in the POSIX standard.
# You must source this script with 'source ./cursor' or '. ./cursor' to use it.
# Reset all attributes to their default values # Reset all attributes to their default values
RESET="\033[0m" RESET="\033[0m"
@ -13,9 +16,18 @@ RED="\033[31m"
GREEN="\033[32m" GREEN="\033[32m"
YELLOW="\033[33m" YELLOW="\033[33m"
BLUE="\033[34m" BLUE="\033[34m"
MAGENTA="\033[35m" PURPLE="\033[35m"
CYAN="\033[36m" CYAN="\033[36m"
WHITE="\033[37m" WHITE="\033[37m" # Or is this default/white?
GREY="\033[2m"
# Formatting
BOLD="\033[1m"
ITALICS="\033[3m" #or 3?
UNDERLINED="\033[4m"
BLINK="\033[5m"
INVERT="\033[7m"
STRIKE="\033[9m" # Strikethrough
# Bright colors # Bright colors
BRIGHT_BLACK="\033[30;1m" BRIGHT_BLACK="\033[30;1m"
@ -23,7 +35,7 @@ BRIGHT_RED="\033[31;1m"
BRIGHT_GREEN="\033[32;1m" BRIGHT_GREEN="\033[32;1m"
BRIGHT_YELLOW="\033[33;1m" BRIGHT_YELLOW="\033[33;1m"
BRIGHT_BLUE="\033[34;1m" BRIGHT_BLUE="\033[34;1m"
BRIGHT_MAGENTA="\033[35;1m" BRIGHT_PURPLE="\033[35;1m"
BRIGHT_CYAN="\033[36;1m" BRIGHT_CYAN="\033[36;1m"
BRIGHT_WHITE="\033[37;1m" BRIGHT_WHITE="\033[37;1m"
@ -33,7 +45,7 @@ BG_RED="\033[41m"
BG_GREEN="\033[42m" BG_GREEN="\033[42m"
BG_YELLOW="\033[43m" BG_YELLOW="\033[43m"
BG_BLUE="\033[44m" BG_BLUE="\033[44m"
BG_MAGENTA="\033[45m" BG_PURPLE="\033[45m"
BG_CYAN="\033[46m" BG_CYAN="\033[46m"
BG_WHITE="\033[47m" BG_WHITE="\033[47m"
@ -43,6 +55,6 @@ BG_BRIGHT_RED="\033[41;1m"
BG_BRIGHT_GREEN="\033[42;1m" BG_BRIGHT_GREEN="\033[42;1m"
BG_BRIGHT_YELLOW="\033[103m" BG_BRIGHT_YELLOW="\033[103m"
BG_BRIGHT_BLUE="\033[104m" BG_BRIGHT_BLUE="\033[104m"
BG_BRIGHT_MAGENTA="\033[105m" BG_BRIGHT_PURPLE="\033[105m"
BG_BRIGHT_CYAN="\033[106m" BG_BRIGHT_CYAN="\033[106m"
BG_BRIGHT_WHITE="\033[107m" BG_BRIGHT_WHITE="\033[107m"

51
spells/cantrips/current-input-lines

@ -0,0 +1,51 @@
#!/bin/sh
# current_input_lines: a cantrip to count the number of lines used by the user's
# current input in the terminal, taking into account wrapped lines and the length
# of the terminal prompt.
#
# Cast this spell to measure the number of lines taken up vertically by the user's
# current input in the terminal, even if the input is wrapped to multiple lines or
# the terminal prompt is longer than usual.
#
# Usage:
# current_input_lines
#
# Returns:
# The number of lines used by the user's current input.
#!/bin/sh
current_input_lines() {
# Save the current cursor position
printf '\033[s'
# Measure the width of the terminal
terminal_width=$(fathom-terminal -w)
# Measure the length of the terminal prompt
prompt_length=$(echo -n "$PS1" | wc -c)
# Calculate the number of columns available for the user's input
available_columns=$(( terminal_width - prompt_length ))
# Calculate the number of lines used by the user's input
lines=$(( terminal_width / available_columns ))
# If the input does not fit evenly into the available columns, add an extra line
if [ "$(( terminal_width % available_columns ))" -ne 0 ]; then
lines=$(( lines + 1 ))
fi
# Restore the cursor position
printf '\033[u'
echo "$lines"
}
# Check if the script is being executed or sourced
if [ "$0" = "$BASH_SOURCE" ]; then
# Script is being executed
# Call the current_input_lines function
current_input_lines
fi

2
spells/cursor → spells/cantrips/cursor

@ -4,6 +4,8 @@
# allowing you to control the position and appearance of the terminal cursor. # allowing you to control the position and appearance of the terminal cursor.
# Use these variables to move the cursor around the screen, # Use these variables to move the cursor around the screen,
# hide and show it, and save and restore its position. # hide and show it, and save and restore its position.
# This script contains all cursor control codes in the POSIX standard.
# You must source this script with 'source ./cursor' or '. ./cursor' to use it.
# #
# Example usage: # Example usage:
# printf "$SAVE_CURSOR" # printf "$SAVE_CURSOR"

0
spells/menu/cursor-blink → spells/cantrips/cursor-blink

54
spells/cantrips/fathom-cursor

@ -0,0 +1,54 @@
#!/usr/bin/env sh
# This spell reveals the x and y coordinates of the cursor in the terminal window.
# Define the function to calculate the position of the cursor
fathom_cursor() {
local position
local x=false
local y=false
local verbose=false
while getopts 'vxy' flag; do
case "${flag}" in
--verbose|v) verbose=true ;;
x) x=true ;;
y) y=true ;;
esac
done
# Get the position of the cursor
position=$(IFS=';' read -sdR -p $'\E[6n' ROW COL; printf "%s;%s" "${ROW#*[}" "$COL")
if [ $x = true ] && [ $y = true ]; then
if [ $verbose = true ]; then
printf "X: %s\n" "${position##*;}"
printf "Y: %s\n" "${position%%;*}"
else
printf "%s\n" "${position##*;}"
printf "%s\n" "${position%%;*}"
fi
else
if [ $x = true ]; then
if [ $verbose = true ]; then
printf "X: "
fi
printf "%s\n" "${position##*;}"
elif [ $y = true ]; then
if [ $verbose = true ]; then
printf "Y: "
fi
printf "%s\n" "${position%%;*}"
else
if [ $verbose = true ]; then
printf "Position: "
fi
printf "%s\n" "$position"
fi
fi
}
# Check if the script is being called from another script
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
# If not, call the function
fathom_cursor "$@"
fi

70
spells/cantrips/fathom-terminal

@ -0,0 +1,70 @@
#!/usr/bin/env sh
# This spell reveals the width and height of the terminal window.
# Define the function to calculate the size of the terminal window
fathom_terminal() {
width=false
height=false
verbose=false
while getopts "vwht" flag; do
case "${flag}" in
--verbose|v) verbose=true;;
--width|w) width=true;;
--height|h) height=true;;
--test|t) test_fathom_terminal; exit 0;;
esac
done
# Get the size of the terminal window
window_width=$(tput cols)
window_height=$(tput lines)
size="${window_width};${window_height}"
if [ $width = true ] && [ $height = true ]; then
if [ $verbose = true ]; then
printf "Width: %s\n" "${window_width}"
printf "Height: %s\n" "${window_height}"
else
printf "%s\n" "${window_width}"
printf "%s\n" "${window_height}"
fi
else
if [ $width = true ]; then
if [ $verbose = true ]; then
printf "Width: "
fi
printf "%s\n" "${window_width}"
elif [ $height = true ]; then
if [ $verbose = true ]; then
printf "Height: "
fi
printf "%s\n" "${window_height}"
else
if [ $verbose = true ]; then
printf "Size: "
fi
printf "%s\n" "$size"
fi
fi
}
# Unit test
test_fathom_terminal() {
. "./assertions"
assert_output "fathom_terminal -w" "$(tput cols)"
assert_output "fathom_terminal --width" "$(tput cols)"
assert_output "fathom_terminal -h" "$(tput lines)"
assert_output "fathom_terminal --height" "$(tput lines)"
assert_output "fathom_terminal -w -v" "Width: $(tput cols)"
assert_output "fathom_terminal --width --verbose" "Width: $(tput cols)"
assert_output "fathom_terminal -h -v" "Height: $(tput lines)"
assert_output "fathom_terminal --height --verbose" "Height: $(tput lines)"
assert_output "fathom_terminal -h -v -w" "Height: $(tput lines)\nWidth: $(tput cols)"
assert_output "fathom_terminal --height --verbose --width" "Height: $(tput lines)\nWidth: $(tput cols)"
}
# Check if the script is being called from another script
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
# If not, call the function
fathom_terminal "$@"
fi

42
spells/cantrips/max-length

@ -0,0 +1,42 @@
#!/usr/bin/env sh
# This magical spell reveals the maximum length of a list of strings.
# Accepts either a list ("word1 word2 word3" or an array of strings
# Usage: cast_max_length string1 string2 ...
# Define the function to calculate the maximum length of the given strings
max_length() {
if [ -z "$1" ]; then
echo "No arguments passed to max_length"
return 1
fi
if [[ "$1" == *" "* ]]; then
# Argument is a string containing multiple words
longest=0
for arg in $1; do
arg_length=${#arg}
if [ $arg_length -gt $longest ]; then
longest=$arg_length
fi
done
else
# Argument is an array
longest=0
for arg in "${!1}"; do
arg_length=${#arg}
if [ $arg_length -gt $longest ]; then
longest=$arg_length
fi
done
fi
if [ "$2" == "-v" ]; then
echo "Maximum length: $longest"
fi
echo $longest
}
# Check if the script is being called from another script
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
# If not, call the function and pass it the command line arguments
max_length "$@"
fi

97
spells/cantrips/menu

@ -0,0 +1,97 @@
#!/usr/bin/env sh
# This script generates a menu from the given list of items. Choosing an item runs the command for that item.
# Usage: menu "Please choose" "item1 item2 item3" "ls cat command3"
# Use up/down arrow keys to select a menu item, then press Enter. Or cancel with ESC.
. colors
description=$1
items=($2)
commands=($3)
selected=0
displayed=0
# Calculate the position of the menu
menu_x=$((0))
menu_y=$(fathom-cursor -y)
# Calculate the number of rows that the menu will occupy
num_rows=${#items[@]}
# Calculate the maximum length of the item names
max_name_length=$(max-length "${items[*]}")
max_name_length=$((max_name_length))
# Define the function to display the menu
display_menu() {
# Get the dimensions of the terminal window (again each time in case window is resized)
window_width=$(fathom-terminal -w)
window_height=$(fathom-terminal -h)
# Recalculate the position of the menu
menu_y=$(fathom-cursor -y)
# Move the cursor to the correct position
if [ $displayed -eq 0 ]; then
# Don't move the cursor or clear the screen the first time
displayed=1
else
if [ $((menu_y + num_rows)) -ge $window_height ]; then
menu_y=$((window_height))
fi
move-cursor $menu_x $((menu_y - num_rows))
fi
# Print the items and commands
for i in "${!items[@]}"; do
if [ $i -eq $selected ]; then
printf "${CYAN}> %-${max_name_length}s${RESET} ${GREY}%s${RESET}\n" "${items[$i]}" "${commands[$i]}"
else
# Print the menu item plus extra spaces to cover up its command, since it's not selected
printf " %-${max_name_length}s %*s\n" "${items[$i]}" "${#commands[$i]}"
fi
done
}
# Define the function to handle key presses
handle_key() {
key=$(await-keypress)
case "$key" in
up)
selected=$((selected - 1))
if [ $selected -lt 0 ]; then
selected=$((num_rows - 1))
fi
;;
down)
selected=$((selected + 1))
if [ $selected -ge $num_rows ]; then
selected=0
fi
;;
enter)
cursor-blink on
command="${commands[$selected]}"
printf "\n"
eval $command
exit 0
;;
escape)
cursor-blink on
echo ESC
exit
;;
esac
}
cursor-blink off
# Display the menu's description
echo $description
# Menu loop
while true; do
display_menu
handle_key $key
done

29
spells/cantrips/move-cursor

@ -0,0 +1,29 @@
#!/usr/bin/env sh
# This magical spell moves the cursor to the specified x and y coordinates in the terminal window, as if guided by an unseen hand.
# Define the function to move the cursor
move_cursor() {
x=$1
y=$2
# Move the cursor to the specified position
printf "\033[${y};${x}H"
}
# Unit test
test_move_cursor() {
. assertions
initial_x=$(fathom-cursor -x)
initial_y=$(fathom-cursor -y)
move_cursor 3 4
final_position=$(fathom-cursor)
assert_equal $final_position "3;4"
move_cursor $initial_x $initial_y
echo "All tests passed"
}
# Check if the script is being sourced, and run it if not
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
move_cursor "$@"
fi

8
spells/say → spells/cantrips/say

@ -8,4 +8,10 @@ say() {
say_inline() { say_inline() {
printf "%b" "${1}" printf "%b" "${1}"
} }
# Check if the script is being called from another script
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
# If not, call the function
say "$@"
fi

15
spells/wizard_eyes → spells/cantrips/wizard-eyes

@ -3,16 +3,15 @@
# A special version of say that prints the text in grey text, indented. # A special version of say that prints the text in grey text, indented.
# Use this to show commands before they are executed, to teach those on the path of wizardry. # Use this to show commands before they are executed, to teach those on the path of wizardry.
source ./say . colors
source ./ask_Yn
wizard_eyes() { wizard_eyes() {
if [ -z $WIZARD ]; then check_wizard; fi if [ -z $WIZARD ]; then check-wizard; fi
if [ -n "$WIZARD" ] && [ "$WIZARD" -eq 1 ]; then say " ${GREY}${1}${RESET}"; fi if [ -n "$WIZARD" ] && [ "$WIZARD" -eq 1 ]; then say " ${GREY}${1}${RESET}"; fi
} }
# Todo next: Add remember/recall functions so that wizard status is remembered after first ask # Check if the script is being called from another script
check_wizard() { if [ "${BASH_SOURCE[0]}" = "$0" ]; then
ask_Yn WIZARD "First, let me ask, are you a wizard?" # If not, call the function
export "WIZARD=$WIZARD" wizard_eyes "$@"
} fi

4
spells/detect-distro

@ -4,8 +4,8 @@
# Also saves the result in the $DISTRO environment variable. # Also saves the result in the $DISTRO environment variable.
# -v for more verbose output # -v for more verbose output
source ./colors source colors
source ./say source say
# Read arguments # Read arguments
while getopts v flag while getopts v flag

0
spells/rehashchant → spells/hashchant

57
spells/hourly-bell

@ -0,0 +1,57 @@
#!/bin/sh
start_hourly_bell(){
# Set up an array of message templates
messages=(
"In the silent depths of the night, a bell tolls and tells you it is %s o'clock."
"A lone bell tolls, a reminder of the hour %s."
"On the top of the hill, the ancient bell tolls to mark the hour, %s."
"Deep in the forest, the bell echoes announcing it's %s o'clock."
"You hear the chimes of a far-off bell. It's the hour of %s."
"From the cathedral tower, the bell tolls out the hour of %s."
"The bell of the clock tower tolls %s o'clock."
"A bell tolls in the distance, signaling that it is %s."
"On a still night, the bell tolls, %s o'clock."
"As you sit in your quiet study, a bell tolls, announcing the hour %s."
"A bell tolls, and the hour is %s"
"The bell tolls, and you realize it's %s o'clock."
"A bell echoes in the valley, announcing the hour %s."
"With a final toll, the bell signals the hour %s."
"A bell tolls softly, reminding you that it is %s o'clock."
)
while true; do
current_time=$(date +%T) # gets the current hour and minutes
current_hour=$(date +%H) # gets the current hour in 24 hour format
current_minutes=$(date +%M) # gets the current minute
# calculate how many seconds are left until the next hour
sleep_time=$((3600 - (current_minutes * 60) - $(date +%S)))
sleep $sleep_time
# Choose a random message template
message=${messages[$RANDOM % ${#messages[@]}]}
# Use the bg_log function to output the message
bg_log "$(printf "$message" "$current_hour")"
done
}
install_hourly_bell(){
if grep -q "source ${BASH_SOURCE[0]}" ~/.bashrc; then
echo "You have already memorized this spell"
else
echo "Do you wish to memorize this spell? (yes/no)"
read -r answer
if [ "$answer" == "yes" ]; then
echo "source ${BASH_SOURCE[0]}" >> ~/.bashrc
echo "Spell memorized in .bashrc, so the bell will always be active in the terminal."
else
echo "The bell will only ring in this shell window."
fi
fi
}
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
install_hourly_bell
trap '' 2 # Traps the INT signal and does nothing with it
start_hourly_bell & # runs the function in background
echo "Hourly bell has started" # message when script is run
fi

18
spells/menu/fathom-cursor

@ -1,18 +0,0 @@
#!/usr/bin/env sh
# This spell reveals the x and y coordinates of the cursor in the terminal window.
# Define the function to calculate the position of the cursor
fathom_cursor() {
# Get the position of the cursor
position=$(IFS=';' read -sdR -p $'\E[6n' ROW COL; printf "%s;%s" "${ROW#*[}" "$COL")
# Output the position of the cursor
echo "Cursor position: $position"
}
# Check if the script is being called from another script
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
# If not, call the function
fathom_cursor
fi

22
spells/menu/fathom-terminal

@ -1,22 +0,0 @@
#!/usr/bin/env sh
# This magical spell reveals the dimensions of the terminal window, displaying the width and height as if by magic.
# Define the function to calculate the dimensions of the terminal window
fathom_dimensions() {
# Get the width of the terminal window
width=$(tput cols)
# Get the height of the terminal window
height=$(tput lines)
# Output the dimensions of the terminal window
echo "Width: $width"
echo "Height: $height"
}
# Check if the script is being called from another script
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
# If not, call the function
fathom_dimensions
fi

27
spells/menu/max-length

@ -1,27 +0,0 @@
#!/usr/bin/env sh
# This magical spell reveals the maximum length of a list of strings.
# Usage: cast_max_length string1 string2 ...
# Define the function to calculate the maximum length of the given strings
max_length() {
# Initialize the maximum length to 0
max_length=0
# Loop through the arguments and calculate the maximum length
for string in "$@"; do
length=${#string}
if [ $length -gt $max_length ]; then
max_length=$length
fi
done
# Output the maximum length
echo "Maximum length: $max_length"
}
# Check if the script is being called from another script
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
# If not, call the function and pass it the command line arguments
max_length "$@"
fi

196
spells/rosetta-stone

@ -0,0 +1,196 @@
#!/bin/sh
# The Rosetta Stone Spell
#
# This spell is an immutable, self-describing teacher-script, designed to teach
# basic Unix commands to wizards studying magic.
# todo: this should allow colors
quest_text() {
foo=$1
for (( i=0; i<${#foo}; i++ )); do
echo -en "${foo:$i:1}"
sleep 0.01
if [ "${foo:$i:1}" = " " ]; then
# Add an extra pause between words
sleep "0.0$(echo $((RANDOM)))"
fi
done
echo -en "\n"
sleep 0.22
}
indent() { sed 's/^/ /'; }
this_spell="${GREEN}this spell${RESET}"
This_spell="${GREEN}This spell${RESET}"
# The rune for checking if a script file exists is -e
if [ -e "$0" ]; then
quest_text "This spell exists."
else
quest_text "The spell $0 does not exist."
fi
# The rune for checking if a script file is a regular file is -f
if [ -f "$0" ]; then
quest_text "The spell is a regular file."
else
quest_text "The spell is not a regular file."
fi
# The rune for checking if a script file is empty is -s
if [ -s "$0" ]; then
quest_text "The spell is not empty."
else
quest_text "The spell is empty."
fi
# The rune for revealing the name of this script is $0
quest_text "${This_spell} is named $0."
# The rune for determining the number of arguments passed to this script
quest_text "${This_spell} was passed $# arguments."
if [ $# -ge 1 ]; then
# The rune for revealing the first argument passed to this script
quest_text "The first argument passed to ${this_spell} is '$1'."
# The rune for revealing all of the arguments passed to this script
quest_text "All arguments passed to ${this_spell} are '$@'."
fi
# The rune for revealing the process ID of the current script
quest_text "The process ID of ${this_spell} is $$."
# The rune for revealing the exit status of the last executed command
quest_text "The exit status of the command ran previously to ${this_spell} was $?."
# todo: make sure -e is the right flag for checking that the string exists / is 1 or greater length
if [ -e "$!" ]; then
# The rune for revealing the process ID of the last backgrounded command
quest_text "The process ID of the last background command in this shell is $!."
fi
# The rune for revealing the current line number in the script
quest_text "The current line number in ${this_spell} is $LINENO."
# The spell for displaying the script's file type
quest_text "This spell is of type: "
quest_text "$(file $0 | indent)"
# The spell for displaying the script's permissions
quest_text "This spell has permissions $(ls -l $0 | awk '{print $1}')."
# The spell for displaying the script's owner and group
quest_text "This spell is owned by $(ls -l $0 | awk '{print $3}')."
quest_text "This spell belongs to group $(ls -l $0 | awk '{print $4}')."
# The spell for displaying the last time the script was modified
quest_text "This spell was last modified on $(ls -l --time-style=+"%D %T" $0 | awk '{print $6, $7}')."
# The spell for displaying the script's size
quest_text "This spell has a size of $(du -h $0 | awk '{print $1}')."
# The spell for displaying the number of lines in this script
quest_text "This spell has $(wc -l $0 | awk '{print $1}') lines."
# The spell for displaying the number of characters in this script
quest_text "This spell has $(wc -m $0 | awk '{print $1}') characters."
# The spell for displaying the number of words in this script
quest_text "This spell has $(wc -w $0 | awk '{print $1}') words."
# The spell for displaying the average line length of this script
quest_text "This script has an average line length of $(awk '{x += length; ++n} END {print x/n;}' $0)."
# The spell for displaying the top 10 most common words used in this script
quest_text "The top 10 most common words used in this spell are: "
quest_text "$(tr -cs "[:alpha:]" "\n" < $0 | tr '[:upper:]' '[:lower:]' | sort | uniq -c | sort -n | tail -10 | indent)"
# The rune for revealing the current working directory
quest_text "The current working directory you are running ${this_spell} in is $(pwd)."
# The rune for revealing the current date and time
quest_text "The current date and time ${this_spell} is running is $(date)."
# The rune for revealing the current user's home directory
quest_text "The home directory of the user running ${this_spell} is $HOME."
# The rune for revealing the current shell
quest_text "The current shell is $SHELL."
# The rune for revealing the hostname of the system
quest_text "The hostname of the system ${this_spell} is on is $(hostname)."
# The rune for revealing the current user
quest_text "The current user is $(whoami)."
# The rune for revealing the current working directory's permissions
# quest_text
#!/bin/sh
# The rune for revealing the current PATH environment variable
quest_text "The current PATH env variable for the environment ${this_spell} is being run in is $PATH."
# The rune for revealing all the environment variables
quest_text "All environment variables are $ENV."
# The rune for revealing the number of seconds since the script was started
quest_text "Time since ${this_spell} started is $SECONDS."
# The spell for generating a hash of the script for integrity verification
quest_text "The SHA-256 hash of this spell is $(sha256sum $0)"
# The rune for revealing the system uptime
quest_text "Uptime since the system ${this_spell} is running on started is:"
quest_text "$(uptime | indent)"
printf "\n"
# The rune for revealing memory usage is free
quest_text "RAM memory usage is:"
quest_text "$(free -h | indent)."
printf "\n"
# The rune for revealing the total storage usage is df
quest_text "Hard disk storage usage is:"
quest_text "$(df -h | indent)"
printf "\n"
# The spell for revealing the total number of running processes is pgrep
#quest_text "Total number of running processes: $(pgrep -c | indent)"
#printf "\n"
# The spell for revealing all the running processes is ps
quest_text "All running processes on the shell ${this_spell} is running on are:"
quest_text "$(ps | indent)"
printf "\n"
# The spell for searching this script for a specific pattern or keyword
quest_text "Searching this spell for the word 'wizard':"
quest_text "$(grep -n "wizard" $0 | indent)"
printf "\n"
# The spell for performing text replacement within this script
#echo "Replacing all instances of 'spell' with 'incantation' in this script"
#sed -i "s/spell/incantation/g" $0
# The spell for extracting specific fields or information from this script
#echo "Extracting line numbers and line contents of all lines that contain the word 'spell':"
#awk '$0 ~ /spell/ {print NR,$0}' $0
# The spell for reading the content of the script file
quest_text "Complete contents of this spell are:"
cat $0 | indent
# The spell for copying the script file to a new location
quest_text "Copying this spell to rosetta-stone-backup.sh"
cp $0 rosetta-stone-backup.sh
# The spell for removing the script file
#quest_text "Deleting this script."
#rm $0
# The spell for making this script into an executable, self-destructing spell
echo "This script will now self-destruct."
chmod +x $0; rm $0
Loading…
Cancel
Save