deicidus
2 years ago
29 changed files with 946 additions and 89 deletions
@ -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" |
@ -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,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 |
@ -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 |
||||||
|
} |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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…
Reference in new issue