From a0c376a23896b3e95daa8f8d8655681fa644ac94 Mon Sep 17 00:00:00 2001 From: SyntaxError Date: Thu, 11 Dec 2025 20:42:59 -0300 Subject: [PATCH] Added script --- README.md | 14 ++ teste.sh | 15 ++ toybox.sh | 519 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 548 insertions(+) create mode 100755 teste.sh create mode 100755 toybox.sh diff --git a/README.md b/README.md index 8e88232..7f8b6b9 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,16 @@ # toybox-bash Some cool tools to use your Bash scripts! + +To use, put toybox.sh on the same directory where you Bash script is, then type: + +```bash +source ./toybox.sh +``` + +or + +```bash +. ./toybox.sh +``` + +Then you can use the functions like menu, playaudio, colors, and more! diff --git a/teste.sh b/teste.sh new file mode 100755 index 0000000..9c08d1f --- /dev/null +++ b/teste.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +detect_distro() { + for f in /etc/*release; do + [ -f "$f" ] || continue + . "$f" + echo "$NAME" + return 0 + done + + echo "toybox.sh - detect_distro: ${RED}NotFound${NC}: Could not detect distribution name." + exit 127 +} + +detect_distro diff --git a/toybox.sh b/toybox.sh new file mode 100755 index 0000000..b6acf2c --- /dev/null +++ b/toybox.sh @@ -0,0 +1,519 @@ +RED='\033[0;31m' +ORANGE='\033[38;5;214m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +BLUE='\033[0;34m' +LBLUE='\033[94m' +NC='\033[0m' + +player_ok() { + "$@" >/dev/null 2>&1 & + local pid=$! + + # espera 0.2s para saber se o processo morreu (erro) ou continua (ok) + sleep 0.2 + + if ! kill -0 "$pid" 2>/dev/null; then + return 1 # morreu -> falhou + fi + + kill "$pid" 2>/dev/null + return 0 # funciona +} + +playaudio() { + local file="$1" + + [[ -f "$file" ]] || return 1 + + # aplay + if command -v aplay >/dev/null 2>&1; then + if player_ok aplay "$file"; then + nohup aplay "$file" >/dev/null 2>&1 & + return 0 + fi + fi + + # paplay + if command -v paplay >/dev/null 2>&1; then + if player_ok paplay "$file"; then + nohup paplay "$file" >/dev/null 2>&1 & + return 0 + fi + fi + + # play (SoX) + if command -v play >/dev/null 2>&1; then + if player_ok play "$file"; then + nohup play "$file" >/dev/null 2>&1 & + return 0 + fi + fi + + # ffplay + if command -v ffplay >/dev/null 2>&1; then + if player_ok ffplay -nodisp -autoexit -loglevel quiet "$file"; then + ffplay -nodisp -autoexit -loglevel quiet "$file" + return 0 + fi + fi + + return 2 # nenhum player funcional +} + + +anime() { + frames=("$@") + time=${frames[-1]} + + for frame in "${frames[@]:0:${#frames[@]}-1}"; do + if [[ $frame != $time ]]; then + printf "$frame" + sleep $time + clear + fi + done +} +s=0 + +menu() { + local titles=() + local footer="" + local options=() + + # parser de parâmetros + while (( $# > 0 )); do + case "$1" in + @title) + titles+=( "$2" ) + shift 2 + ;; + @footer) + footer="$2" + shift 2 + ;; + @circular) + circular=1 + shift + ;; + *) + options+=( "$1" ) + shift + ;; + esac + done + + while true; do + clear + + # comportamento circular + if [[ $circular ]]; then + (( s < 0 )) && s=$((${#options[@]} - 1)) + (( s >= ${#options[@]} )) && s=0 + else + (( s < 0 )) && s=0 + (( s >= ${#options[@]} )) && s=$((${#options[@]} - 1)) + fi + + # imprimir todos os títulos + for t in "${titles[@]}"; do + echo -e "$t" + done + [[ ${#titles[@]} -gt 0 ]] && echo + + # imprimir opções + for i in "${!options[@]}"; do + if [[ $s == $i ]]; then + echo -e "\e[30;47m> ${options[i]}\e[0m" + else + echo -e " ${options[i]}" + fi + done + + [[ -n "$footer" ]] && echo -e "\n$footer" + + # leitura de teclas + read -rsn1 key + if [[ -z $key ]]; then + key=$'\n' + elif [[ $key == $'\e' ]]; then + read -rsn2 -t 0.01 rest + key+="$rest" + fi + + case $key in + $'\e[A') s=$((s-1)) ;; + $'\e[B') s=$((s+1)) ;; + $'\e') clear; exit 0;; + $'\n'|$'\r') selected="$s"; break ;; + esac + done +} + +lecho() { + if [[ -z "$lang" ]]; then + echo -e "toybox.sh - lecho: ${RED}TypeError:${NC} Cannot read properties of null (reading 'lang')" + exit 1 + fi + + local prompt + [[ "$lang" == "0" ]] && prompt="$1" + [[ "$lang" == "1" ]] && prompt="$2" + + echo "$prompt" +} + +lechoe() { + if [[ -z "$lang" ]]; then + echo -e "toybox.sh - lechoe: ${RED}TypeError:${NC} Cannot read properties of null (reading 'lang')" + exit 1 + fi + + local prompt + [[ "$lang" == "0" ]] && prompt="$1" + [[ "$lang" == "1" ]] && prompt="$2" + + echo -e "$prompt" +} + +lprintf() { + if [[ -z "$lang" ]]; then + echo -e "toybox.sh - lprintf: ${RED}TypeError:${NC} Cannot read properties of null (reading 'lang')" + exit 1 + fi + + local prompt + [[ "$lang" == "0" ]] && prompt="$1" + [[ "$lang" == "1" ]] && prompt="$2" + + printf "$prompt" +} + +lreadp() { + if [[ -z "$lang" ]]; then + echo -e "toybox.sh - lreadp: ${RED}TypeError:${NC} Cannot read properties of null (reading 'lang')" + exit 1 + fi + + local prompt + [[ "$lang" == "0" ]] && prompt="$1" + [[ "$lang" == "1" ]] && prompt="$2" + + if [[ -n $3 ]]; then + declare -g "$3" + read -r -p "$prompt" "$3" + else + read -r -p "$prompt" + fi +} + +lmenu() { + if [[ -z "$lang" ]]; then + echo "toybox.sh - lreadp: ${RED}TypeError${NC}: missing 'lang'." + return 1 + fi + + local args=( "$@" ) + local titles=() + local options=() + local footer="" + + local i=0 + while (( i < ${#args[@]} )); do + local key="${args[i]}" + local pt="${args[i+1]:-}" + local en="${args[i+2]:-}" + + # --------------------------------------------------------------------- + # @title (multiplos) + # --------------------------------------------------------------------- + [[ "$key" == "@title" ]] && { + # normalização para ":" e campos ausentes + [[ "$pt" == ":" ]] && pt="$en" + [[ "$en" == ":" ]] && en="$pt" + [[ -z "$en" ]] && en="$pt" + [[ -z "$pt" ]] && pt="$en" + + [[ "$lang" == "1" ]] && titles+=( "$en" ) || titles+=( "$pt" ) + + ((i+=3)) + continue + } + + # --------------------------------------------------------------------- + # @footer (único) + # --------------------------------------------------------------------- + [[ "$key" == "@footer" ]] && { + [[ "$pt" == ":" ]] && pt="$en" + [[ "$en" == ":" ]] && en="$pt" + [[ -z "$en" ]] && en="$pt" + [[ -z "$pt" ]] && pt="$en" + + [[ "$lang" == "1" ]] && footer="$en" || footer="$pt" + + ((i+=3)) + continue + } + + # --------------------------------------------------------------------- + # Opções normais (PT EN) + # --------------------------------------------------------------------- + local o_pt="$key" + local o_en="$pt" + + [[ "$o_pt" == ":" ]] && o_pt="$o_en" + [[ "$o_en" == ":" ]] && o_en="$o_pt" + [[ -z "$o_pt" ]] && o_pt="$o_en" + [[ -z "$o_en" ]] && o_en="$o_pt" + + [[ "$lang" == "1" ]] && options+=( "$o_en" ) || options+=( "$o_pt" ) + + ((i+=2)) + done + + # Montar lista final para menu() + local final=() + + for t in "${titles[@]}"; do + final+=( "@title" "$t" ) + done + + final+=( "${options[@]}" ) + + [[ -n "$footer" ]] && final+=( "@footer" "$footer" ) + + menu "${final[@]}" +} + +loading() { + [[ ! $1 ]] && echo -e "toybox.sh - loading: ${RED}SyntaxError${NC}: missing 'type' argument." && exit 1 + [[ ! $2 ]] && echo -e "toybox.sh - loading: ${RED}SyntaxError${NC}: missing 'interval' argument." && exit 1 + [[ ! $3 ]] && echo -e "toybox.sh - loading: ${RED}SyntaxError${NC}: missing 'times' argument." && exit 1 + + local type="$1" + local interval="$2" + local times="$3" + local color="${4:-0}" # cor padrão 0 se não passada + local spinner=("|" "/" "-" "\\") # frames do spinner + + if [[ "$type" == "spin" ]]; then + for ((i=0; i> status + fi +} + +detect_base() { + # Detecta pela pkgbase (se nada mais funcionar) + if command -v apt &> /dev/null; then + PKG="debian" + elif command -v dnf &> /dev/null; then + PKG="fedora" + elif command -v pacman &> /dev/null; then + PKG="arch" + elif command -v zypper &> /dev/null; then + PKG="suse" + elif command -v apk &> /dev/null; then + PKG="alpine" + else + PKG="none" + fi + + # 1) Prioriza os-release + if [ -f /etc/os-release ]; then + . /etc/os-release + + if [ -n "$ID_LIKE" ]; then + read -r -a like_arr <<< "$ID_LIKE" + BASE="${like_arr[0]}" + return + fi + + if [ -n "$ID" ]; then + BASE="$ID" + return + fi + fi + + # 2) Fallback para outros arquivos + for file in /etc/*release /etc/*_version /etc/*-release; do + [ -f "$file" ] || continue + . "$file" + + if [ -n "$ID_LIKE" ]; then + read -r -a like_arr <<< "$ID_LIKE" + BASE="${like_arr[0]}" + return + elif [ -n "$ID" ]; then + BASE="$ID" + return + elif [ -n "$DISTRIB_ID" ]; then + BASE="$DISTRIB_ID" + return + else + BASE="$(head -n1 "$file")" + return + fi + done + + # 3) Ajustes baseados no PKG + if [[ "$ID" == "ubuntu" && "$PKG" == "debian" ]]; then + BASE="debian" + return + fi + + if [[ "$ID" != "$PKG" ]]; then + BASE="unknown" + return + fi + + if [[ "$ID" == "$PKG" ]]; then + BASE="$ID" + return + fi + + return 127 +} +# Result: +#detect_base +#echo $BASE +#> arch + +detect_distro() { + # 1) Prioriza os-release + if [ -f /etc/os-release ]; then + . /etc/os-release + DISTRO="${NAME:-$PRETTY_NAME}" + return + fi + + # 2) Fallback para arquivos específicos + shopt -s nullglob + for file in /etc/*release /etc/*_version /etc/*-release; do + [ -e "$file" ] || continue + + . "$file" + + if [ -n "${NAME:-}" ]; then + DISTRO="$NAME" + shopt -u nullglob + return + + elif [ -n "${DISTRIB_ID:-}" ]; then + DISTRO="$DISTRIB_ID" + shopt -u nullglob + return + + else + DISTRO="$(head -n1 "$file")" + shopt -u nullglob + return + fi + done + shopt -u nullglob + + return 127 + +} +# Result +# detect_distro +# echo "$NAME" +# > Arch Linux + +detect_windows() { + # 1) Git Bash / MSYS2 / MinGW + case "$(uname -s)" in + MINGW*|MSYS*) + windows_env="Git Bash / MSYS2" + return 0 + ;; + esac + + # 2) Windows environment variable (Git Bash, MSYS, Cygwin) + if [ "$is_windows" = false ] && [ "$OS" = "Windows_NT" ]; then + windows_env="Windows_NT (Git Bash/Cygwin/MSYS)" + return 0 + fi + + # 3) WSL + if [ "$is_windows" = false ] && grep -qi microsoft /proc/version 2>/dev/null; then + windows_env="Windows Subsystem for Linux" + return 0 + fi + + # 4) cmd.exe (fallback) + if [ "$is_windows" = false ] && command -v cmd.exe >/dev/null 2>&1; then + windows_env="Windows (via cmd.exe)" + return 0 + fi + + return 1 + + # Result + # if detect_windows; then + # echo "Windows detected ($windows_env)" + # else + # echo "Isn't windows." + # fi +} + +detect_android() { + # 1) build.prop + if grep -qi android /system/build.prop 2>/dev/null; then + android_env="build.prop" + return 0 + fi + + # 2) getprop + if command -v getprop >/dev/null 2>&1; then + if [ -n "$(getprop ro.build.version.release 2>/dev/null)" ]; then + android_env="getprop" + return 0 + fi + fi + + # 3) common directories + if [ -d /sdcard ] && [ -d /system ]; then + android_env="paths típicos" + return 0 + fi + + # 4) Termux + if [[ "$PREFIX" == /data/data/*com.termux* ]]; then + android_env="Termux" + return 0 + fi + + # 5) kernel + if uname -a | grep -qi android; then + android_env="kernel string" + return 0 + fi + + return 1 + + # Result + # if detect_android; then + # echo "Android detected ($android_env)" + # else + # echo "Isn't Android" + # fi +} \ No newline at end of file