Browse Source

menu works and users-menu uses it

main
deicidus 2 years ago
parent
commit
a5c19efda9
  1. 3
      README.md
  2. 10
      spells/cantrips/fathom-cursor
  3. 59
      spells/cantrips/menu
  4. 43
      spells/users-menu

3
README.md

@ -9,9 +9,10 @@ ao-mud is a project to make the terminal easier for novice users by narrativizin
* POSIX-compatible scripts - maximally compatible across platforms and weird nested environments
* immanence - the game is here, a meaningful virtual space in the terminal
* immediacy - the game is everywhere, not a separate mode
* pedagogy - collecting best practices and making them easy to use, learn, remember, and teach/share
* pedagogy - collecting best practices and making them easy to use, learn, remember, and teach/share in well-commented bash scripts
* sharpen the saw - gradually improving the architecture of the tech stack
* smarter conventions - we can evolve the terminal and make it easier to teach by migrating to higher-order semantics (new words)
* semantic evolution - we can evolve bash from a pidgin to a creole with rigorously one-function apps plus a recursive parser
# Architecture

10
spells/cantrips/fathom-cursor

@ -47,6 +47,16 @@ fathom_cursor() {
fi
}
test_fathom_cursor() {
assert_equal "$(./fathom-cursor -x)" "$(./fathom-cursor -y)" "fathom_cursor -x and -y outputs differ"
assert_equal "$(./fathom-cursor -x -v)" "X: $(./fathom-cursor -x)" "fathom_cursor -x and -x -v outputs differ"
assert_equal "$(./fathom-cursor -y -v)" "Y: $(./fathom-cursor -y)" "fathom_cursor -y and -y -v outputs differ"
assert_equal "$(./fathom-cursor -x -y -v)" "X: $(./fathom-cursor -x)\nY: $(./fathom-cursor -y)" "fathom_cursor -x -y and -x -y -v outputs differ"
assert_equal "$(./fathom-cursor -v -x -y)" "Position: $(./fathom-cursor -x -y)" "fathom_cursor -v -x -y and -x -y outputs differ"
assert_equal "$(./fathom-cursor -v)" "$(./fathom-cursor -x -y -v)" "fathom_cursor -v and -x -y -v outputs differ"
assert_equal "$(./fathom-cursor)" "$(./fathom-cursor -x -y)" "fathom_cursor and -x -y outputs differ"
}
# Check if the script is being called from another script
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
# If not, call the function

59
spells/cantrips/menu

@ -1,14 +1,30 @@
#!/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"
# Usage: menu "Please choose" "choice one,choice two with\, a comma,item three" "ls -al,cat \"This string\, has a comma\",command3"
# Use up/down arrow keys to select a menu item, then press Enter. Or cancel with ESC.
# Todo: the menu only works with one-word items and commands. maybe this is a problem with loading the arrays? it should work with multi-word items and commands.
. colors
description=$1
items=($2)
commands=($3)
#shift 1
#parse items array
IFS=',' read -r -a items <<< "$2"
items=("${items[@]//\\,/,}")
declare -a items
#parse commands array
IFS=',' read -r -a commands <<< "$3"
commands=("${commands[@]//\\,/,}")
declare -a commands
#items=("$@")
#commands=("${items[@]:3}")
#items=("$2")
#commands=("$3")
#read -r -a items <<< "$2"
#read -r -a commands <<< "$3"
selected=0
displayed=0
@ -20,8 +36,22 @@ menu_y=$(fathom-cursor -y)
num_rows=${#items[@]}
# Calculate the maximum length of the item names
max_name_length=$(max-length "${items[*]}")
max_name_length=$((max_name_length))
# Todo: abstract this out into a max-length function in another script. I gave up on trying to find an elegant way to pass a list of strings with spaces. Even separating them with newlines didn't work.
max_name_length=0
# Find the longest line
for line in "${items[@]}"; do
line_length=${#line}
if [ $line_length -gt $max_name_length ]; then
max_name_length=$line_length
fi
done
# Make sure the menu items don't wrap, multiline menu items are not supported
window_width=$(fathom-terminal -w)
if [ $max_name_length -gt $window_width ]; then
max_name_length=$window_width
fi
# Define the function to display the menu
display_menu() {
@ -45,11 +75,14 @@ display_menu() {
# Print the items and commands
for i in "${!items[@]}"; do
# Truncate the command to the width of the screen # Todo: come up with a better solution that allows the user to see the full command.
max_command_length=$(( $window_width - $max_name_length - 3 )) # -3 is for the > and the space between item and command
truncated_command=$(echo "${commands[$i]}" | cut -c -$max_command_length)
if [ $i -eq $selected ]; then
printf "${CYAN}> %-${max_name_length}s${RESET} ${GREY}%s${RESET}\n" "${items[$i]}" "${commands[$i]}"
printf "${CYAN}> %-${max_name_length}s${RESET} ${GREY}%s${RESET}\n" "${items[$i]}" "$truncated_command"
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]}"
printf " %-${max_name_length}s %*s\n" "${items[$i]}" "${#truncated_command}"
fi
done
}
@ -85,6 +118,18 @@ handle_key() {
esac
}
# Catch Ctrl-C and restore the cursor blink, so the user doesn't get stuck with an invisible cursor
handle_ctrl_c() {
trap 'cursor-blink on; exit' INT
}
handle_ctrl_c
test_menu() {
assert_equal "$(./menu "Please choose" "item1 item2 item3" "ls cat command3" -v)" "Please choose\n1) item1\n2) item2\n3) item3\n" "menu -v output differs"
assert_equal "$(./menu "Please choose" "item1 item2 item3" "ls cat command3")" "1) item1\n2) item2\n3) item3\n" "menu output differs"
}
cursor-blink off
# Display the menu's description

43
spells/users-menu

@ -0,0 +1,43 @@
# This script presents a menu of options for managing users on the system. The options available include:
# - Viewing the groups a user is in
# - Adding a user to a group
# - Changing a user's password
# - Creating a new user
# - Deleting an existing user
# - Exit the script
. colors
display_menu() {
options="Change my password,Change other user's password,View my group memberships,View other user's group membership,List all groups,Create new group,Delete group,Join group,Leave group,Add other user to group,Remove other user from group,Create new user,Delete user,Exit"
view_my_groups="groups"
view_other_groups="read -p \"Enter username: \" username; groups \$username"
change_my_password="passwd"
change_other_password="read -p \"Enter username: \" username; sudo passwd \$username"
list_groups="cut -d: -f1 /etc/group"
create_group="read -p \"Enter new group name: \" groupname; sudo groupadd \$groupname"
delete_group="read -p \"Enter group to delete: \" groupname; sudo groupdel \$groupname"
join_group="read -p \"Enter group name to join: \" groupname; sudo usermod -a -G \$groupname \$USER"
leave_group="read -p \"Enter group name to leave: \" group; sudo gpasswd -d \$USER \$group"
add_user_to_group="read -p \"Enter username: \" username; read -p \"Enter group name to add them to: \" group; sudo usermod -a -G \$group \$username"
remove_user_from_group="read -p \"Enter username: \" username; read -p \"Enter group to remove them from: \" group; sudo gpasswd -d \$username \$group"
create_user="read -p \"Enter new username: \" username; sudo useradd \$username; printf \"Please remember to set a password for the new user with the 'Change other user's password' option.\""
delete_user="read -p \"Enter username of user to delete: \" username; sudo userdel \$username"
my_pid=$$
exit="kill -2 $my_pid" # 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
commands="$change_my_password,$change_other_password,$view_my_groups,$view_other_groups,$list_groups,$create_group,$delete_group,$join_group,$leave_group,$add_user_to_group,$remove_user_from_group,$create_user,$delete_user,$exit"
menu "User management options:" "$options" "$commands"
}
# Catch Ctrl-C and exit
handle_ctrl_c() {
trap 'echo exiting; exit' INT
}
handle_ctrl_c
while true; do
display_menu
done
Loading…
Cancel
Save