You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The refactor is much easier to read! I didn't even notice it existed and have been scouring git for repository to splice together that are neither too complex, nor too simple for my needs seeing as multisekect is rare in a bash/posix menu system.
Guaranteed to be errors to fix, shellcheck pukes when I import the original isn't vscodium that I'll have to take care of, and way more to do, but a rough draft.
Updates as life allows and perhaps I'll fork/pr when I feel it's useable for my scripting needs.
Hopefully of nothing else refactoring for readability with a English speaking daddy world and simple comments is a help for now. Copy pasta your friend!
I came across this new repo I was the first star in that's very interesting a bash script "generator/constructor/boilerplate'r" named vesta or something, should be in my stars, that's very interesting yet multiselect is rare. Who wants dialog or whip?! His way of key press reads, as well as the selector repos implimentstion, is clean and modular for near ant key press.
Show this off to Chris Titus tech at some point in the future for some actual pull requests. wink
(Edits are done on mobile in bed and to my needs with residuals still in here. Didnt finish)
#!/usr/bin/env bash
#===============================================================================
# SOURCE: https://github.com/pedro-hs/checkbox.sh
#
# DESCRIPTION: Create customizable checkbox for the terminal.
# Check out how to use on README.md at <https://github.com/pedro-hs/checkbox.sh>
#===============================================================================
## Constants (readonly)
# ☆◇♡+÷#<>•°|《》▪︎¤○●■ as your TERM supports. linux-term compatible ligs÷icos in bashtop
declare -r SELECTED="✔" UNSELECTED="[ ]"
declare -r ANSI_ESC="\033" BLACK_FG="${ANSI_ESC}[30m"
GRAY_BG="${ANSI_ESC}[47m" WHITE="${ANSI_ESC}[37m" BLUE="${ANSI_ESC}[34m" RED="${ANSI_ESC}[36m" GREEN="${ANSI_ESC}[32m"
# is double too for active/header/footer plus tees
declare -r BOX_TOP_L="┌" BOX_TOP_R="┐" BOX_BOT_L="└" BOX_BOT_R="┘" BOX_HOR="─" BOX_VER="│"
## Variables
# ints (strings)
declare cursor=0 options_length=0 terminal_width=0 start_page=0 end_page=0
# bool
declare has_multiple_options=false has_index_result=false show_copy_message=false show_help=false
# arrays
declare -a options=("${DEFAULT_OPTIONS[@]}") selected_options=() checkbox_output=()
# strings
declare content="" message="" separator="" options_input=""
declare color=$WHITE
# Array Utilities
array_remove_value() {
local value="$1" && shift
local new_array=()
for item in "$@"; do
[[ "$item" != "$value" ]] && new_array+=("$item")
done
echo "${new_array[@]}" # TODO printf 》echo
}
array_contains() {
local element="$1" && shift
local elements=("$@")
for e in "${elements[@]}"; do
[[ "$e" == "$element" ]] && return 0
done
return 1
}
# Help Page
display_help() {
cat <<EOF
# Keybinds:
[UP/DOWN ARROWS], [HOME/END], [PAGE UP/DOWN] or k/j, g/G, u/d: Move cursor
o or [ENTER]: Close and return selected options
x or [SPACE]: Select current option
q or [ESC]: Exit
r: Refresh renderization
(press q to quit)
EOF
while true; do
local key=$(get_pressed_key)
case $key in
_esc|q) return ;;
esac
done
}
# Checkbox Rendering
render_options() {
declare content && content=""
local start=$start_page end=$end_page
for (( index = start; index <= end; index++ )); do
if [[ $index -ge 0 && $index < $options_length ]]; then # TODO RH quotes shellcheck
local option="${options[index]}"
if [[ $index -eq $cursor ]]; then
set_line_color
fi
render_option "$index" "$option" && color=$WHITE
fi
done
}
render_option() {
local index="$1" option="$2"
if array_contains "$index" "${selected_options[@]}"; then
content+="$color $SELECTED $option\n" # TODO content of what, selectable itsms? Descriptor
else
content+="$color $UNSELECTED $option\n"
fi
}
set_line_color() {
if [[ "$has_multiple_options" = true ]]; then
if [[ "$select_mode_on" = true ]]; then # TODO I personally won't need these, or yellow+grey?
color=$GREEN!!
elif [[ "$unselect_mode_on" = true ]]; then
color=$RED
else
color=$BLUE
fi
fi
}
# Option Handling
set_options() {
if [[ -n "$options_input" ]]; then
local escaped_options=$(escape_options_ascii_signs)
IFS="|" read -ra options <<< "$escaped_options"
fi
}
escape_options_ascii_signs() {
# TODO micro function required used once?
local options_str="${options_input#*=}"
options_str=$(echo "$options_str" | sed 's/\\[a-zA-Z]//g')
echo "$options_str"
}
# Terminal and Interface Management
validate_terminal_size() {
if [[ $terminal_width -lt 8 ]]; then
printf "Resize the terminal to at least 8 lines and press r to refresh. Current width: $terminal_width lines.\n"
fi
}
construct_footer() {
local footer="$(( $cursor + 1 ))/$options_length"
if [[ "$has_multiple_options" = true ]]; then
footer+=" | ${#selected_options[@]} selected"
fi
# TODO I won't need this copy pasta in tty isn't Chad
if [[ "$show_copy_message" = true ]]; then
footer+=" | current line copied"
show_copy_message=false
fi
# TODO arrays should have {}? (All over)
echo "$footer"
}
render_checkbox() {
# TODO use tput to rellace ansi in other places?
terminal_width=$(tput lines)
render_options
local output && output=""
if [[ -n "$message" ]]; then
local header=$(center_text " $message ")
output+="${BLACK_FG}${GRAY_BG}${BOX_TOP_L}$(printf '%0.s${BOX_HORI}' {1..$((${#header} - 2))})${BOX_TOP_R}${ANSI_ESC}[0m\n"
output+="${BLACK_FG}${GRAY_BACKGROUND}${BOX_VERT} $message ${BOX_VERT}${ANSI_ESC}[0m\n"
output+="${BLACK_FG}${GRAY_BG}${BOX_BOTTOM_L}$(printf '%0.s${BOX_HORI}' {1..$((${#header} - 2))})${BOX_BOTTOM_R}${ANSI_ESC}[0m\n"
fi
output+="$content"
local footer=$(construct_footer)
output+="${BLACK_FG}${GRAY_BG}${BOX_TOP_L}$(printf '%0.s${BOX_HORI}' {1..$((${#footer} - 2))})${BOX_TOP_R}${ANSI_ESC}[0m\n"
output+="${BLACK_FG}${GRAY_BG}${BOX_VERT} $footer ${BOX_VERT}${ANSI_ESC}[0m\n"
output+="${BLACK_FOREGROUND}${GRAY_BACKGROUND}${BOX_BOTTOM_LEFT}$(printf '%0.s${BOX_HORIZONTAL}' {1..$((${#footer} - 2))})${BOX_BOTTOM_RIGHT}${ANSI_ESCAPE}[0m\n"
printf "$output"
}
clear_checkbox() {
local header_footer_lines=3
local checkbox_lines=$(($options_length + $header_footer_lines))
local delete_lines_above="${ANSI_ESCAPE}[${checkbox_lines}A"
printf "$delete_lines_above"
}
render_result() {
for option in "${checkbox_output[@]}"; do
echo "$option"
done
}
# Key Press Handlers
toggle_select_mode() {
if [[ "$has_multiple_options" = true ]]; then
unselect_mode_on=false
if [[ "$select_mode_on" = true ]]; then
select_mode_on=false
else
select_mode_on=true
if ! array_contains "$cursor" "${selected_options[@]}"; then
selected_options+=("$cursor")
fi
fi
fi
}
toggle_unselect_mode() {
if [[ "$has_multiple_options" = true ]]; then
select_mode_on=false
if [[ "$unselect_mode_on" = true ]]; then
unselect_mode_on=false
else
unselect_mode_on=true
selected_options=($(array_remove_value "$cursor" "${selected_options[@]}"))
fi
fi
}
# Utility Functions
get_pressed_key() {
IFS= read -sn1 key 2>/dev/null >&2
read -sn1 -t 0.02
1 key
case $key in
'') key=_enter ;;
' ') key=_space ;;
$'\x1b') key=_esc ;;
$'\e[F') key=_end ;;
$'\e[H') key=_home ;;
$'\x7f') key=_backspace ;;
$'\x1b\x5b\x32\x7e') key=_insert ;;
$'\x1b\x5b\x41') key=_up ;;
$'\x1b\x5b\x42') key=_down ;;
$'\x1b\x5b\x35\x7e') key=_pgup ;;
$'\x1b\x5b\x36\x7e') key=_pgdown ;;
esac
echo "$key"
}
parse_arguments() {
while [[ $# -gt 0 ]]; do
opt=$1
shift
case $opt in
--index) has_index_result=true ;;
--multiple) has_multiple_options=true ;;
--message=*) message="${opt#*=}" ;;
--options=*) options_input="$opt" ;;
--help) show_help=true ;;
*) show_help=true ;;
esac
done
}
initialize() {
set_options
options_length=${#options[@]}
terminal_width=$(tput lines)
start_page=0
end_page=$(( $start_page + $terminal_width - 4 ))
[[ $end_page -ge $options_length ]] && end_page=$(( $options_length - 1 ))
if [[ ${#message} -gt 40 ]]; then
message_length=$(( ${#message} + 10 ))
else
message_length=50
fi
separator=$(perl -E "say '-' x $message_length")
}
# Center text function
center_text() {
local text="$1"
local width=$(tput cols)
local padding=$(( (width - ${#text}) / 2 ))
printf "%*s" $padding "" | tr ' ' "$BOX_HORIZONTAL"
printf "%s" "$text"
printf "%*s" $padding "" | tr ' ' "$BOX_HORIZONTAL"
}
# Main Function
main() {
parse_arguments "$@"
if [[ "$show_help" = true ]]; then
display_help
printf "\n"
exit
fi
initialize
render_checkbox
while true; do
validate_terminal_size
local key=$(get_pressed_key)
case $key in
_up|k) move_cursor_up ;;
_down|j) move_cursor_down ;;
_home|g) move_to_home ;;
_end|G) move_to_end ;;
_pgup|u) page_up ;;
_pgdown|d) page_down ;;
_esc|q) break ;;
_enter|o) confirm_selection && break ;;
_space|x) select_current_option ;;
_insert|v) toggle_select_mode ;;
_backspace|V) toggle_unselect_mode ;;
c|y) copy_current_option ;;
r) refresh_render ;;
a) select_all ;;
A) unselect_all ;;
esac
clear_checkbox
render_checkbox
done
render_result
}
main "$@"
shrug
The text was updated successfully, but these errors were encountered:
Nsomnia
changed the title
[IMPROVMENTS/WIP] Spitballing Readability & Visual Improvmenets
[IMPROVMENTS/WIP] Spitballing Readability & Visual Improvmenets + Refactor Ideas
Nov 26, 2024
The refactor is much easier to read! I didn't even notice it existed and have been scouring git for repository to splice together that are neither too complex, nor too simple for my needs seeing as multisekect is rare in a bash/posix menu system.
Guaranteed to be errors to fix, shellcheck pukes when I import the original isn't vscodium that I'll have to take care of, and way more to do, but a rough draft.
Updates as life allows and perhaps I'll fork/pr when I feel it's useable for my scripting needs.
Hopefully of nothing else refactoring for readability with a English speaking daddy world and simple comments is a help for now. Copy pasta your friend!
I came across this new repo I was the first star in that's very interesting a bash script "generator/constructor/boilerplate'r" named vesta or something, should be in my stars, that's very interesting yet multiselect is rare. Who wants dialog or whip?! His way of key press reads, as well as the selector repos implimentstion, is clean and modular for near ant key press.
Show this off to Chris Titus tech at some point in the future for some actual pull requests. wink
(Edits are done on mobile in bed and to my needs with residuals still in here. Didnt finish)
main "$@"
shrug
The text was updated successfully, but these errors were encountered: