diff --git a/spells/disenchant b/spells/disenchant index 5267313..19792cb 100755 --- a/spells/disenchant +++ b/spells/disenchant @@ -38,7 +38,6 @@ fi keys=$(read-magic "$1") # Extract the attribute keys from the output of read-magic keys=$(echo "$keys" | awk -F: '{print $1}' | tr -d ' ') -echo $keys # Check if a key name was given as an argument if [ -z "$2" ]; then diff --git a/spells/hashchant b/spells/hashchant index 0dd7900..06ff534 100755 --- a/spells/hashchant +++ b/spells/hashchant @@ -1,9 +1,5 @@ #!/bin/sh -# This "enchant" spell imbues a file with the power of its own hash, binding it to its own unique identity. -# The spell requires a single argument: the path to the file to be enchanted. -# The resulting CRC-32 hash is saved as an extended attribute called "user.hash" in hexadecimal. - # Check if the required argument was provided if [ -z "$1" ]; then # If no argument was given, display an error message and exit @@ -22,7 +18,11 @@ if [ ! -e "$file" ]; then fi # Calculate the hash of the file -hash=$(echo -n "$file" | cksum | awk '{ print "0x"$1 }') +filename=$(basename "$file") +hash=$( (echo "$filename" && cat "$file") | cksum | awk '{ print $1 }') + +# Convert the hash to hexadecimal +hash=$(printf '0x%X' "$hash") # Save the hash as an extended attribute if command -v attr > /dev/null; then @@ -37,4 +37,4 @@ else exit 1 fi -echo "File enchanted with hash: $hash" +echo "File enchanted with hash: $hash" \ No newline at end of file diff --git a/spells/menu/bitcoin/bitcoin-menu b/spells/menu/bitcoin/bitcoin-menu index 46feae5..42d7f25 100755 --- a/spells/menu/bitcoin/bitcoin-menu +++ b/spells/menu/bitcoin/bitcoin-menu @@ -11,7 +11,7 @@ display_menu() { set_config="Configure Bitcoin%configure-bitcoin" change_directory="Change Bitcoin Directory%change-bitcoin-directory" clear_cache="Clear Bitcoin Cache%# coming soon" - repair_permissions="Repair Permissions%repair-bitcoin-permissions # Sometimes necessary" + repair_permissions="Repair Permissions%repair-bitcoin-permissions" exit_option="Exit%kill -2 $$" # Commands are run with 'eval' by the menu script, so we can't simply say 'exit'. The keyword $$ gets this scripts PID and the -2 code is SIGINT aka Ctrl-C if is-bitcoin-installed; then diff --git a/spells/menu/install-menu b/spells/menu/install-menu new file mode 100755 index 0000000..ad47462 --- /dev/null +++ b/spells/menu/install-menu @@ -0,0 +1,69 @@ +#!/bin/sh + +# This script displays a menu to install recommended free software. + +. colors + +# Catch Ctrl-C and exit +handle_ctrl_c() { + trap 'echo exiting; exit' INT +} + +handle_ctrl_c + +# Calculate the length of a string +strlen() { + echo -n "$1" | wc -c +} + +# Calculate maximum of two numbers +max() { + [ "$1" -gt "$2" ] && echo "$1" || echo "$2" +} + +script_dir="$(dirname "$0")" + +while true; do + max_name_length=0 + max_status_length=0 + formatted_items="" + + # First pass: calculate maximum lengths + for d in $(find "$script_dir" -maxdepth 1 -mindepth 1 -type d); do + name=$(basename "$d") + status=$(command -v "${name}-status" >/dev/null 2>&1 && eval "${name}-status" || echo "coming soon") + + # Update maximum lengths + max_name_length=$(max "$max_name_length" "$(strlen "$name")") + max_status_length=$(max "$max_status_length" "$(strlen "$status")") + done + + # Second pass: create menu items using the maximum lengths + for d in $(find "$script_dir" -maxdepth 1 -mindepth 1 -type d); do + name=$(basename "$d") + status=$(command -v "${name}-status" >/dev/null 2>&1 && eval "${name}-status" || echo "coming soon") + menu_command="${name}-menu" + + # Calculate padding for the name and status + name_padding=$(( max_name_length - $(strlen "$name") )) + status_length=$(strlen "$status") + total_padding=$(( max_status_length - status_length )) + left_padding=$(( total_padding / 2 )) + right_padding=$(( total_padding - left_padding )) + + # Build the formatted item string piece by piece + formatted_item="${name}$(printf "%${name_padding}s")" + formatted_item="${formatted_item}$(printf "%${left_padding}s")" + formatted_item="${formatted_item}${status}" + formatted_item="${formatted_item}$(printf "%${right_padding}s")" + + # Add formatted item to the list of menu items + formatted_items="${formatted_items} \"${formatted_item}%${menu_command}\"" + done + + # Add Exit command + formatted_items="${formatted_items} \"Exit%kill -2 $$\"" + + # Display the menu + eval "menu \"Install Menu:\" $formatted_items" +done \ No newline at end of file diff --git a/spells/menu/main-menu b/spells/menu/main-menu new file mode 100755 index 0000000..7f06fbc --- /dev/null +++ b/spells/menu/main-menu @@ -0,0 +1,26 @@ +#!/bin/sh + +# This spell displays the ao-mud main menu. + +. colors + +display_menu() { + mud="MUD menu%mud" + install="Install Free Software%install-menu" + update="Update all software%smart-update # Coming soon" + restart="Force restart%sudo shutdown -r now" + exit="Exit%kill -2 $$" # Commands are run with 'eval' by the menu script, so we can't simply say 'exit'. The keyword $$ gets this scripts PID and the -2 code is SIGINT aka Ctrl-C + + menu "Main Menu:" "$mud" "$install" "$update" "$restart" "$exit" +} + +# Catch Ctrl-C and exit +handle_ctrl_c() { + trap 'echo exiting; exit' INT +} + +handle_ctrl_c + +while true; do + display_menu +done diff --git a/spells/priorities b/spells/priorities new file mode 100755 index 0000000..c051de1 --- /dev/null +++ b/spells/priorities @@ -0,0 +1,86 @@ +#!/bin/sh + +# Initialize verbose flag to 0 +verbose=0 + +# Parse options +while getopts "v" opt; do + case $opt in + v) verbose=1 ;; # If -v is passed, set verbose to 1 + \?) echo "Invalid option: -$OPTARG" >&2 ;; # Invalid option + esac +done +shift $((OPTIND-1)) # Shift off the options and optional --. + +# Function to display priorities +display_priorities() { + # Get directory + DIR="${PWD}" + + # Get the current priorities of the directory + dir_priorities=$(read-magic "${DIR}" priorities) + + # If there are no priorities, print an error message and exit + if [ -z "${dir_priorities}" ] || [ "$dir_priorities" = "Error: The attribute does not exist." ]; then + echo "No priorities set in the current folder. Try 'prioritize '." + exit 1 + fi + + # Initialize variables + highest_priority="" + line_added=false + menu_command="menu Priorities:" + + # Loop through the priorities + dir_priorities=$(echo "${dir_priorities}" | tr ',' '\n') + + for priority_hash in $dir_priorities; do + # Get the priority file + priority_file=$(get-card "${priority_hash}") + + # Check if the file exists + if [ -n "${priority_file}" ]; then + # Get priority of the file + file_priority=$(read-magic "${priority_file}" priority 2>/dev/null) + + # If the file does not have a priority, set it to 0 + if [ -z "${file_priority}" ] || [ "$file_priority" = "Error: The attribute does not exist." ]; then + file_priority=0 + fi + + # If the priority of the file is a number + if [ "${file_priority}" -eq "${file_priority}" ] 2>/dev/null; then + # If the file's priority is not the highest priority, add a line + if [ -n "${highest_priority}" ] && [ "${file_priority}" -ne "${highest_priority}" ] && [ "${line_added}" = false ]; then + menu_command="${menu_command} \"─── %\"" + line_added=true + fi + + # Add the file to the menu command + menu_command="${menu_command} \"" + if [ $verbose -eq 1 ]; then + menu_command="${menu_command}${file_priority} " + fi + item_name=$(basename "$priority_file") + menu_command="${menu_command}$item_name%priority-menu \\\"${priority_file}\\\"\"" + + # Update the highest priority + highest_priority="${file_priority}" + fi + fi + done + + # Add exit command + menu_command="${menu_command} \"Exit%kill -2 $$\"" + + # Execute the constructed menu command + eval "${menu_command}" +} + +# This script displays a list of the prioritized cards in the current directory. +# Catch Ctrl-C +trap "exit" INT + +while true; do + display_priorities +done \ No newline at end of file diff --git a/spells/prioritize b/spells/prioritize new file mode 100755 index 0000000..1591e27 --- /dev/null +++ b/spells/prioritize @@ -0,0 +1,90 @@ +#!/bin/sh + +# Usage: prioritize [FILE] [OPTIONAL_DIRECTORY] +file_path=$1 +directory=$2 + +# Check if the target file exists +if [ ! -f "$file_path" ]; then + echo "Error: The file '$file_path' does not exist." + exit 1 +fi + +# Get the hash of the target file +hashchant "$file_path" > /dev/null +target_hash=$(read-magic "$file_path" hash 2>/dev/null) + +# Get the directory the file is in, if a target directory was not provided as the second optional argument +if [ -z "$directory" ]; then + directory=$(dirname "$file_path") +fi + +# Get the file's priority, or default to 0 +target_priority=$(read-magic "$file_path" priority 2>/dev/null || echo 0) + +# Retrieving the priority list from the directory's extended attributes +priorities=$(read-magic "$directory" priorities 2>/dev/null) + +# If there are no priorities, we add the target file as the only priority +if [ -z "$priorities" ] || [ "$priorities" = "Error: The attribute does not exist." ]; then + enchant "$directory" priorities "$target_hash" > /dev/null + enchant "$file_path" priority 1 > /dev/null + echo "Prioritized '$(basename "$file_path")' as the only priority." + exit 0 +fi + +# Get the priority of the first item in the current list of priorities +first_hash=$(echo "$priorities" | cut -d',' -f1) +first_file=$(get-card "$first_hash") +first_priority=$(read-magic "$first_file" priority 2>/dev/null || echo 0) + +# If the target file is already the first priority, we exit +if [ "$target_hash" = "$first_hash" ]; then + echo "'$(basename "$file_path")' is already the highest priority." + exit 0 +fi + +# Filter the target hash from the current priorities list, so it doesn't duplicate +priorities=$(echo "$priorities" | tr ',' '\n' | sed "/^$target_hash\$/d" | tr '\n' ',' | sed 's/,$//') + +# If the target file's priority is already equal the first item's priority, reprioritize it with a higher priority +if [ "$first_priority" -gt "0" ] && [ "$target_priority" = "$first_priority" ]; then + rebuilt_priorities="$target_hash,$priorities" + enchant "$file_path" priority $(($first_priority + 1)) > /dev/null + enchant "$directory" priorities "$rebuilt_priorities" > /dev/null + echo "Reprioritized '$(basename "$file_path")'." + exit 0 +fi + +# Loop through the comma-delimited string of hashes in a POSIX-compliant way +rebuilt_priorities="" +added=0 +for hash in $(echo "$priorities" | tr ',' ' '); do + file=$(get-card "$hash") + current_priority=$(read-magic "$file" priority 2>/dev/null || echo 0) + + # If the target file's priority is already higher than the current hash's priority + # or the current hash's priority is different from the first hash's priority + # we insert the target file's hash at this point + if [ ! $added ] && [ "$target_priority" -gt "$current_priority" ] || [ "$current_priority" != "$first_priority" ]; then + rebuilt_priorities="$rebuilt_priorities$target_hash," + added=1 + fi + rebuilt_priorities="$rebuilt_priorities$hash," +done + +# If we reached the end of the loop without adding the target hash, add it now +if [ "$added" -eq 0 ]; then + rebuilt_priorities="$rebuilt_priorities$target_hash" +fi + +# Trim trailing comma +rebuilt_priorities=$(echo "$rebuilt_priorities" | sed 's/,$//') + +# Setting the priority value of the target file to the value of the first item's priority +enchant "$file_path" priority "$first_priority" > /dev/null + +# Updating the directory's extended attributes with the new priorities list +enchant "$directory" priorities "$rebuilt_priorities" > /dev/null + +echo "Prioritized '$(basename "$file_path")'." \ No newline at end of file diff --git a/spells/priority-menu b/spells/priority-menu new file mode 100755 index 0000000..08572ca --- /dev/null +++ b/spells/priority-menu @@ -0,0 +1,33 @@ +#!/bin/sh + +# This spell displays a menu of commands for a prioritized file or folder. Use 'priorities' to easily select a priority with this menu. +# Usage: priority-menu [FILE] + +. colors + +FILE="${1}" + +display_menu() { + checked_state=$(read-magic "${FILE}" checked) + if [ "${checked_state}" = "Error: The attribute does not exist." ]; then + check_item="Check%echo 'Placeholder: Check command'" + else + check_item="Uncheck%echo 'Placeholder: Uncheck command'" + fi + + filename=$(basename "$FILE") + + menu "${GREEN}${BOLD}${filename}${RESET}" \ + "Prioritize (upboat)%prioritize \"$FILE\"; kill -2 $$" \ + "${check_item}" \ + "Discard from priorities (downboat)%echo 'Placeholder: Discard command'" \ + "Edit Card%echo 'Placeholder: Edit command'" \ + "Browse Within%echo 'Placeholder: Browse files within this file/folder'" \ + "Exit%kill -2 $$" +} + +trap 'exit' INT + +while true; do + display_menu +done \ No newline at end of file