Bonjour à vous,
Histoire :
je vous propose une commande que j'ai créé suite à un besoin personnel. En effet la commande select est pas mal mais ne permettait pas de choisir les infos à récupérer ni li les sélections multiples.
Mes attentes :
Tous vos retours sont bons à prendre, alors n’hésitez pas à me proposer de nouvelles possibilités, des corrections (orthographe, code...), j'attends que ça 🙂
Description :
HizoSelect permet d'afficher une "question" et une liste de proposition avec :
- de la couleur ou non...
- la possibilité de choix multiple (par plage ou toutes les valeurs)
- la possibilité de choix aléatoire
- la possibilité de limiter le nombre de choix
- la possibilité d'ajouter une description/commentaire aux propositions
- la possibilité de choisir le format de retour avec le numéro, le texte, le commentaire ou bien une valeur cachée
- la possibilité de choisir le format d'affichage des propositions
- disponible en français et anglais (sûrement plein de fautes :p )
- et pas mal d'autres choses...
Exemples :
Pour avoir des exemples :
hizoselect --examples
Une petite vidéo pour montrer à quoi ça ressemble :
https://asciinema.org/a/BuWsTAVxL5hbsQEGtRwOV2rLz
Aide :
La commande à un argument help :
hizoselect --help
La commande est livrée avec des manpages (fr et en), donc il faut exécuter :
man hizoselect
Si vous avez télécharger le fichier tar.gz, il faut exécuter :
man ./hizoselect1.fr.1
Téléchargement :
Via un fichier tar.gz :
Le fichier est disponible ici :
http://hizo.fr/linux/hizoselect/hizoselect.tar.gz
Via un fichier deb :
Le deb est dispo sur le ppa :
https://launchpad.net/~hizo/+archive/ubuntu/bash/+packages
Via un PPA :
sudo add-apt-repository ppa:hizo/bash
sudo apt update
sudo apt install hizoselect
Dernière version (2.0.2) :
Mini maj
Ajout de la licence
Ajout de la possibilité d'utiliser des % en les echappant dans les formats
Modification complete de la gestion des couleurs remplacé par --effects, voir la manpage dessus
Ajout de nouvelles vérifications
Création d'une barre d'aide permettant des modifications en direct, voir la manpage dessus
Remplacement de --limit par --max et création de --min
Refonte du système de traduction qui utilise maitnenant gettext
Suppression de --range --random --all et --exit
Suppression de --lang, il faut utiliser la variable LANGUAGE
Remplacement de --multi par --several
Dernière version du code :
#!/bin/bash
### Bloque l’expansion de ? et de *
set -f
### version et licence
Version="2.0.0 - 24/09/2017"
Licence="GNU GPL v3"
### Variables par défaut
Min=0
Max=0
MaxImplied=0
Bar=true
Choix[0]="" # Nécessaire de créer le 0 pour que les réponses commencent à 1
Uniq=true
Debug=true
All=true
Random=true
Range=true
OutputText="%t"
InputText="%n) <%t : %c|%t|%c>"
##################################
## Fonction de sortie en erreur ##
##################################
### Fonction arrêtant la commande en mode erreur avec le texte d'erreur
function ExitErreur
{
# Saut de ligne esthétique
echo >&2
# Renvoie le texte Exit
echo "Exit"
### Débloque l’expansion de ? et de *
set +f
# Arrêt "problématique"
exit 1
}
##########################
## Fonction de couleurs ##
##########################
function EffectsSetUp
{
# Destructions des couleurs
unset Effects
# Déclaration du tableau
declare -Ag Effects
# Déclaration de la valeur de réinitialisation
Effects["Unset"]=$(tput sgr0)
case ${1} in
# Redefinition des couleurs
on)
if [[ ${DefineEffects["Exists"]} ]]
then
Effects["Commentaries"]="${DefineEffects["Commentaries"]}"
Effects["Errors"]="${DefineEffects["Errors"]}"
Effects["Numbers"]="${DefineEffects["Numbers"]}"
Effects["Secrets"]="${DefineEffects["Secrets"]}"
Effects["Texts"]="${DefineEffects["Texts"]}"
Effects["Title"]="${DefineEffects["Title"]}"
Effects["Prompt"]="${DefineEffects["Prompt"]}"
Effects["Exists"]=true
else
EffectsSetUp auto
fi
;;
# Mise en place des couleurs automatiques
auto)
Effects["Commentaries"]=$(tput setaf 2)
Effects["Errors"]=$(tput setaf 1)
Effects["Numbers"]=$(tput setaf 5)
Effects["Secrets"]=$(tput setaf 3)
Effects["Texts"]=$(tput setaf 4)
Effects["Title"]=$(tput setaf 6)
Effects["Prompt"]=$(tput setaf 6)
Effects["Exists"]=true
;;
# Dans le cas de la demande de couleur automatiques en argument, ainsi on peut remodifier uniquement certaines couleurs
# --effects "auto" --effects "%n=1"
auto-arg)
# Variable conservant en mémoire les couleurs
declare -Ag DefineEffects
DefineEffects["Commentaries"]=$(tput setaf 2)
DefineEffects["Errors"]=$(tput setaf 1)
DefineEffects["Numbers"]=$(tput setaf 5)
DefineEffects["Secrets"]=$(tput setaf 3)
DefineEffects["Texts"]=$(tput setaf 4)
DefineEffects["Title"]=$(tput setaf 6)
DefineEffects["Prompt"]=$(tput setaf 6)
DefineEffects["Exists"]=true
EffectsSetUp auto
;;
esac
}
#######################################
## Fonction de vérification de plage ##
#######################################
function RangeCheck
{
# Code 0 : La plage est valide
# Code 1 : La plage est invalide
# ${1} : valeur à tester
local MinValue=${1%-*} MaxValue=${1#*-}
# Si Max n'existe pas
if [[ -z ${MaxValue} ]]
then
[[ ${Debug} ]] && echo -en "\r${Clear}${Effects["Errors"]}$(LangText "error_range_max")${Effects["Unset"]} ${LastText}" >&2
return 1
# Max n'est supérieur à Min
elif [[ ${MinValue} -ge ${MaxValue} ]]
then
[[ ${Debug} ]] && echo -en "\r${Clear}${Effects["Errors"]}$(LangText "error_numbers")${Effects["Unset"]} ${LastText}" >&2
return 1
# Min n'existe pas dans la liste
elif [[ -z $(printf "%s\n" "${!Choix[@]}" | grep "^${MinValue}$") ]]
then
[[ ${Debug} ]] && printf "\r${Clear}${Effects["Errors"]}$(LangText "error_default_check")${Effects["Unset"]} ${LastText}" "${MinValue}" >&2
return 1
# Max n'existe pas dans la liste
elif [[ -z $(printf "%s\n" "${!Choix[@]}" | grep "^${MaxValue}$") ]]
then
[[ ${Debug} ]] && printf "\r${Clear}${Effects["Errors"]}$(LangText "error_default_check")${Effects["Unset"]} ${LastText}" "${MaxValue}" >&2
return 1
else
return 0
fi
}
##################################################################
## Fonction de calcul du nombre de réponse et verifie la limite ##
##################################################################
function AnswerLimit
{
# Code 0 : La limite n'est pas atteinte
# Code 1 : La limite est atteinte
# ${1} : Liste des réponses
# ${2} : liste des propositions
# ${3} : mode gt et non ge (pour tester defaut et savoir s'il reste encore une place)
# Variables locales
local Answers=(${1}) Items=(${2}) NumberItem=0
# Teste les réponses une à une
for Answer in "${Answers[@]}"
do
# Si ce n'est qu'un nombre ou nombre aléatoire
if [[ "${Answer}" =~ ^[0-9?]+$ ]]
then
# Incrément simple
((NumberItem++))
# Si c'est une plage
elif [[ ${Answer} == *-* ]]
then
local MinValue=${Answer%-*}
local MaxValue=${Answer#*-}
local SeqValues=($(seq ${MinValue} ${MaxValue}))
# Incrément du nombre de proposition de la plage
NumberItem=$[NumberItem + ${#SeqValues[@]}]
fi
done
### Regarde si la limit est atteinte
# 1: Mode gt, Limit est à utiliser, le nombre de proposition est > à la limite
# 2: Mode ge, Limit est à utiliser, le nombre de proposition est >= à la limite
# 3: Mode gt, MaxImplied est à utiliser, le nombre de proposition est > à la MaxImplied
# 4: Mode ge, MaxImplied est à utiliser, le nombre de proposition est >= à la MaxImplied
if [[ ${3} && ${Max} -gt 0 && ${NumberItem} -gt ${Max} ]] || [[ -z ${3} && ${Max} -gt 0 && ${NumberItem} -ge ${Max} ]] || [[ ${3} && ${MaxImplied} -gt 0 && ${NumberItem} -gt ${MaxImplied} ]] || [[ -z ${3} && ${MaxImplied} -gt 0 && ${NumberItem} -ge ${MaxImplied} ]]
then
[[ ${Debug} ]] && echo -en "\r${Clear}${Effects["Errors"]}$(LangText "error_limit_max")${Effects["Unset"]} ${LastText}" >&2
return 1
# Tous les autres cas
else
return 0
fi
}
#########################################
## Fonction de remplissage de la liste ##
#########################################
function AnswerGet
{
# ${1} : Liste des réponses
# ${2} : liste des propositions
# ${3} : Ne pas remplacer les ? par des valeurs
local Answers=(${1})
local Items=(${2})
local AnswerList=()
local Question=()
### Teste les réponses une à une
for Answer in "${Answers[@]}"
do
# Si ce n'est qu'un nombre
if [[ ${Answer} =~ ^[0-9]+$ ]]
then
# Ajout de la valeur
AnswerList+=(${Answer})
# Si c'est un nombre aléatoire
elif [[ ${Answer} == "?" ]]
then
Question+=("?")
# Si c'est toutes les propositions
elif [[ ${Answer} == "*" ]]
then
# Ajout de toutes les valeurs
AnswerList+=(${Items[@]})
# Si c'est une plage
elif [[ ${Answer} == *-* ]]
then
local MinValue=${Answer%-*}
local MaxValue=${Answer#*-}
local SeqValues=($(seq ${MinValue} ${MaxValue}))
# Ajout de la plage
AnswerList+=(${SeqValues[@]})
fi
done
if [[ ${3} ]]
then
AnswerList+=(${Question[@]})
# les ? doivent être fait après coup car sinon ils risques de poser problème au niveau doublon
# genre ? devient 1 puis 1 a été rentré après...
elif [[ ${Question[@]} ]]
then
# Remplace les ? un par un
for Number in ${Question[@]}
do
# Si le mode unique est actif
if [[ ${Uniq} ]]
then
# Liste temporaire supprimant les valeurs déjà utilisées ainsi que les 0
ListeTemp=($(comm -23 <(printf "%s\n" "${Items[@]}" | sort) <(printf "%s\n" 0 "${AnswerList[@]}" | sort)))
# Change le ? en une autre valeur non utilisée
AnswerList+=($(printf "%s\n" "${ListeTemp[@]}" | shuf -n 1))
# Si pas de mode unique
else
# Change le ? en une autre valeur
AnswerList+=($(shuf -i1-${#Items[@]} -n1))
fi
done
fi
# Renvoie la liste
echo ${AnswerList[@]}
}
###############################################
## Fonction recherchant les suites possibles ##
###############################################
function NumberDigit
{
# Code 0 : Il peut grandir et est disponible
# Code 1 : Il peut grandir mais est déjà utilisé
# Code 2 : Il ne peut pas grandir mais est disponible
# Code 3 : Ne peut pas grandir et est déjà utilisé
# Code 4 : Le nombre n'existe pas
# Code 5 : Le nombre commence par un 0
# ${1} : Nombre à tester
# ${2} : Liste des propositions possibles
# ${3} : Propositions déjà présentes
# Variables
local Number=${1}
local Items=(${2})
local Answers=(${3})
local ActualList=()
# Arrêt de la fonction si le chiffre commence par 0
if [[ "${Number:0:1}" == 0 ]]
then
[[ ${Debug} ]] && echo -en "\r${Clear}${Effects["Errors"]}$(LangText "error_zero")${Effects["Unset"]} ${LastText}" >&2
return 5
fi
# Arrêt de la fonction si le nombre n'existe pas
if [[ -z $(grep -w "${Number}" <<< "${Items[@]}") ]]
then
[[ ${Debug} ]] && printf "\r${Clear}${Effects["Errors"]}$(LangText "error_choice")${Effects["Unset"]} ${LastText}" "${Number}" >&2
return 4
fi
# Récupérer la liste des réponses actuelles
[[ "${Answers[@]}" ]] && ActualList+=($(AnswerGet "${Answers[*]}" "${Items[*]}" "NoChange?"))
# Regarde si la valeur est déjà utilisée
local DejaUtilise=$(printf "%s\n" "${ActualList[@]}" | grep -w "${Number}")
# Recherche des nombres possibles
local Possible=($(printf "%s\n" "${Items[@]}" | egrep "^${Number}[0-9]+$"))
# Si on peut aller plus loin
if [[ ${Possible[@]} ]]
then
# Il faut prendre en compte unique
if [[ ${Uniq} ]]
then
# Recherche des nombres déjà utilisés
local Deja=($(printf "%s\n" ${Answers[@]} | egrep "^${Number}[0-9]+$"))
# S'il reste des valeurs disponibles
if [[ $(comm -23 <(printf "%s\n" "${Possible[@]}" | sort) <(printf "%s\n" 0 "${Deja[@]}" | sort)) ]]
then
[[ ${DejaUtilise} ]] && return 1 || return 0
else
if [[ ${DejaUtilise} ]]
then
[[ ${Debug} ]] && printf "\r${Clear}${Effects["Errors"]}$(LangText "error_max")${Effects["Unset"]} ${LastText}" "${Number}" >&2
return 3
else
return 2
fi
fi
# Si Uniq ne rentre pas en ligne de compte
else
return 0
fi
# On ne peut pas aller plus loin, la valeur est déjà prise et le mode unique est actif
elif [[ ${Uniq} && ${DejaUtilise} ]]
then
[[ ${Debug} ]] && printf "\r${Clear}${Effects["Errors"]}$(LangText "error_used")${Effects["Unset"]} ${LastText}" "${Number}" >&2
return 3
# On ne peut pas aller plus loin mais la valeur est disponible ou le mode unique n'est pas actif
else
return 2
fi
}
#############################################################
## Fonction essayant d'ajouter la variable temp à la liste ##
#############################################################
function AnswerAdd
{
# Code 0 : OK on peut ajouter la valeur
# Code 1 : On ne peut pas l'ajouter
# ${1} : Nombre à ajouter à la liste des réponses
# ${2} : Liste des réponses
# ${3} : liste des propositions
local Number=${1}
local Answers=(${2})
local Items=(${3})
local ActualList=()
# Récupérer la liste des réponses actuelles
[[ "${Answers[@]}" ]] && ActualList+=($(AnswerGet "${Answers[*]}" "${Items[*]}" "NoChange?"))
# Si le mode unique n'est pas actif et qu'il n'y a pas de limite, il n'y a rien d'autre à tester
[[ ${Max} -eq 0 && -z ${Uniq} ]] && return 0
# Si ce n'est qu'un nombre
if [[ ${Number} =~ ^[0-9]+$ ]]
then
# Le nombre n'est pas présent
if [[ -z "${Items[@]}" ]]
then
# Teste la nouvelle liste
ActualList+=(${Number})
AnswerLimit "${ActualList[*]}" "${Items[*]}" "ModeGT" && return 0 || return 1
# Arrêt de la fonction si le nombre n'existe pas ou Le nombre est déjà présent avec le mode unique est actif
elif [[ -z $(grep -w "${Number}" <<< "${Items[@]}") ]] || [[ ${Uniq} && $(grep -w "${Number}" <<< "${ActualList[@]}") ]]
then
return 1
else
# Teste la nouvelle liste
ActualList+=(${Number})
AnswerLimit "${ActualList[*]}" "${Items[*]}" "ModeGT" && return 0 || return 1
fi
# Si ce n'est qu'un nombre aléatoire
elif [[ ${Number} == "?" ]]
then
# Teste la nouvelle liste
ActualList+=(${Number})
AnswerLimit "${ActualList[*]}" "${Items[*]}" "ModeGT" && return 0 || return 1
# Si c'est une plage
elif [[ ${Number} == *-* ]]
then
# vérifie que la plage est bonne
RangeCheck ${Number} || return 1
local MinValue=${Number%-*}
local MaxValue=${Number#*-}
local SeqValues=($(seq ${MinValue} ${MaxValue}))
for x in ${SeqValues[@]}
do
# Si le nombre n'existe pas ou Si le nombre est déjà présent avec le mode uniq
if [[ -z $(grep -w "${x}" <<< "${Items[@]}") ]] || [[ ${Uniq} && $(grep -w "${x}" <<< "${ActualList[@]}") ]]
then
return 1
# Dans les autres cas
else
# Teste la nouvelle liste
ActualList+=(${x})
AnswerLimit "${ActualList[*]}" "${Items[*]}" "ModeGT" || return 1
fi
done
# Si rien ne l'a fait quitté en erreur
return 0
fi
}
######################################
## Fonction lisant les propositions ##
######################################
function FormatReader
{
# ${1} : Texte
# ${2} : Variable à utiliser
# ${3} : Sert à modifier les textes avec ces nouvelles valeurs
# Destruction de la variable
unset Item
# Déclaration du tableau global
declare -Ag Item
# Protection du %, tout de suite car le nettoyage se fait en fonction des %
local Temp1="${1//\\%/¦¦¦¦¦Hizo¦¦¦¦¦}"
# Remplissage du tableau
[[ "${Temp1}" =~ "%c=" ]] && Item["Com"]="${Temp1#*%c=}" Item["Com"]="${Item["Com"]%%%*}" Item["Com"]="${Item["Com"]/%[[:space:]]}"
[[ "${Temp1}" =~ "%s=" ]] && Item["Secret"]="${Temp1#*%s=}" Item["Secret"]="${Item["Secret"]%%%*}" Item["Secret"]="${Item["Secret"]/%[[:space:]]}"
[[ "${Temp1}" =~ "%t=" ]] && Item["Text"]="${Temp1#*%t=}" Item["Text"]="${Item["Text"]%%%*}" Item["Text"]="${Item["Text"]/%[[:space:]]}"
[[ -z ${Item["Text"]} ]] && Item["Text"]="${Temp1%%%*}" Item["Text"]="${Item["Text"]/%[[:space:]]}"
# Si une valeur est donnée, on l'utilise pour créer le texte à afficher
if [[ ${2} ]]
then
if [[ ${2} == InputText ]]
then
local VarTemp="${InputText}"
else
local VarTemp="${OutputText}"
unset Effects
fi
# Protection des < > et |
VarTemp="${VarTemp//\\</@@@@@Hizo@@@@@}"
VarTemp="${VarTemp//\\>/#####Hizo#####}"
VarTemp="${VarTemp//\\|/&&&&&Hizo&&&&&}"
# Remplacement des variables par leur valeur, l'IFS permet de ne pas supprimer les espaces
while IFS='' read Line
do
# Si la ligne est vide on saute le tour
[[ -z ${Line} ]] && continue
# Ajout des valeurs à la liste
[[ "${Line}" =~ "%n" && ${3} ]] && Line="${Line//%n/${Effects["Numbers"]}${3}${Effects["Unset"]}}"
[[ "${Line}" =~ "%t" && ${Item["Text"]} ]] && Line="${Line//%t/${Effects["Texts"]}${Item["Text"]}${Effects["Unset"]}}"
[[ "${Line}" =~ "%c" && ${Item["Com"]} ]] && Line="${Line//%c/${Effects["Commentaries"]}${Item["Com"]}${Effects["Unset"]}}"
[[ "${Line}" =~ "%s" && ${Item["Secret"]} ]] && Line="${Line//%s/${Effects["Secrets"]}${Item["Secret"]}${Effects["Unset"]}}"
# Variables locales
local VarTest="" Part
# Découpe en fonction des |
old_IFS="${IFS}"
IFS="|" Part=(${Line})
IFS="${old_IFS}"
# Traite chaque partie (séparée par |) tant qu'on trouve des variables
for Value in "${Part[@]}"
do
# S'il n'y a plus de variable
[[ ! "${Value}" =~ %[ncst] ]] && { Line="${Value}"; VarTest=true; break; }
done
# S'il reste des variables on n'ajoute pas le texte
[[ -z ${VarTest} ]] && continue
# Déprotection des < > et | et %
Line="${Line//@@@@@Hizo@@@@@/<}"
Line="${Line//#####Hizo#####/>}"
Line="${Line//&&&&&Hizo&&&&&/|}"
Line="${Line//¦¦¦¦¦Hizo¦¦¦¦¦/%}"
# Ajout du texte
Item["Line"]+="${Line}"
done <<< "${VarTemp//[<>]/$'\n'}"
fi
}
function DisplayTexts
{
########################
## Affichage du titre ##
########################
### Message apparaissant avant la liste
[[ ${Title} ]] && printf "${Effects["Title"]}${Title} " >&2
# S'il ya une limite basse et haute
if [[ ${Max} > 0 && ${Min} > 0 ]]
then
[[ ${Min} == ${Max} ]] && printf "(${Effects["Commentaries"]}$(LangText "title_min_max_equal")${Effects["Unset"]})\n" "${Max}" >&2 || printf "(${Effects["Commentaries"]}$(LangText "title_min_max")${Effects["Unset"]})\n" "${Min}" "${Max}" >&2
# S'il ya une limite haute
elif [[ ${Max} > 0 ]]
then
printf "(${Effects["Commentaries"]}$(LangText "title_max")${Effects["Unset"]})\n" "${Max}" >&2
# S'il ya une limite basse
elif [[ ${Min} > 0 ]]
then
printf "(${Effects["Commentaries"]}$(LangText "title_min")${Effects["Unset"]})\n" "${Min}" >&2
else
printf "\n" >&2
fi
################################
## Affichage des propositions ##
################################
### Mode colonnes
if [[ ${Columns} ]]
then
for Number in ${!Choix[@]}
do
# Remplissage du tableau
FormatReader "${Choix[${Number}]}" "InputText" "${Number}"
# Affichage de la proposition
echo -e "${Item["Line"]}"
done | column -x >&2
### Mode sans colonnes
else
for Number in ${!Choix[@]}
do
# Remplissage du tableau
FormatReader "${Choix[${Number}]}" "InputText" "${Number}"
# Affichage de la proposition
echo -e "${Item["Line"]}" >&2
done
fi
################################
## Affichage des possibilités ##
################################
# Si on ne doit pas utiliser la barre
[[ -z ${Bar} ]] && return
local Possibilities
# Traitement des options une à une
for letter in h c v d l e
do
# Création de tableaux contenant les informations
case ${letter} in
d)
[[ ${Debug} ]] && DefaultText=$(LangText info_debug_off) || DefaultText=$(LangText info_debug_on)
OptionLetter=$(LangText info_debug_letter)
;;
e)
DefaultText=$(LangText info_exit_on)
OptionLetter=$(LangText info_exit_letter)
;;
h)
DefaultText=$(LangText info_help_on)
OptionLetter=$(LangText info_help_letter)
;;
l)
[[ ${LANGUAGE} =~ "en" ]] && DefaultText=$(LangText info_lang_on) || DefaultText=$(LangText info_lang_off)
OptionLetter=$(LangText info_lang_letter)
;;
c)
[[ ${Effects["Exists"]} ]] && DefaultText=$(LangText info_effect_off) || DefaultText=$(LangText info_effect_on)
OptionLetter=$(LangText info_effect_letter)
;;
v)
[[ ${Columns} ]] && DefaultText=$(LangText info_view_off) || DefaultText=$(LangText info_view_on)
OptionLetter=$(LangText info_view_letter)
;;
esac
# Remplissage de la ligne d'information
Possibilities+=("[${Effects["Numbers"]}${OptionLetter}${Effects["Unset"]}] ${Effects["Texts"]}${DefaultText}${Effects["Unset"]}")
Possibilities+=(" - ")
done
# Destruction du dernier -
unset Possibilities[-1]
# Affichage de l'aide
echo -e "\n${Possibilities[@]}" >&2
}
###################
## Texte affiché ##
###################
function LastText
{
# Texte de base
TexteBase="${Effects["Prompt"]}$(LangText "prompt_text")${Effects["Unset"]}"
if [[ ${Reponses[@]} && ${ReponseTemp} ]]
then
LastText="${Effects["Texts"]}${TexteBase}${Effects["Numbers"]}${Reponses[@]} ${Effects["Commentaries"]}${ReponseTemp}${Effects["Unset"]}"
elif [[ ${Reponses[@]} ]]
then
LastText="${Effects["Texts"]}${TexteBase}${Effects["Numbers"]}${Reponses[@]} ${Effects["Unset"]}"
elif [[ ${ReponseTemp} ]]
then
LastText="${Effects["Texts"]}${TexteBase}${Effects["Commentaries"]}${ReponseTemp}${Effects["Unset"]}"
else
LastText="${Effects["Texts"]}${TexteBase}${Effects["Unset"]}"
fi
}
########################
## Textes en fr et en ##
########################
### Variables pour le fichier de traduction
[[ "${0}" != "hizoselect" ]] && export TEXTDOMAINDIR="." # Variable importante pour le mode sans installation
export TEXTDOMAIN=hizoselect
. gettext.sh
function LangText
{
# Utilisation d'une fonction appelée à chaque besoin pour éviter le temps de chargement de toutes les valeurs
# pour extraire ls textes dans un fichier pot :
# xgettext --msgid-bugs-address=hizo@free.fr --package-name=hizoselect --copyright-holder="Belleguic terence <hizo@free.fr>" -L shell --add-comments=TranslationAssistance -o - hizoselect > hizoselect.pot
# pour mettre à jour le fichier po (qui est une copie du pot à la base) : msgmerge --update fr/hizoselect.po hizoselect.pot
# pour créer le fichier mo : msgfmt -o fr/LC_MESSAGES/hizoselect.mo fr/hizoselect.po
### Textes
case ${1,,} in
#TranslationAssistance ==============================> Texts of the errors
"argument") eval_gettext "The %s argument needs a value." ;;
"error_choice") eval_gettext "The number %s is out of selection." ;;
"error_default_check") eval_gettext "Error in the default values: %s is not in the list." ;;
"error_double_espace") eval_gettext "Double spacing is impossible." ;;
"error_default_limit") eval_gettext "The number of default values is greater than the number of items." ;;
"error_default_limit2") eval_gettext "Max value is greater than the number of items with several mode disabled." ;;
"error_default_mode") eval_gettext "Impossible to use %s because %s mode is disabled." ;;
"error_default_star") eval_gettext "Impossible to associate * with another value." ;;
"error_effects") eval_gettext "The effects are define by a number between 0 and 255 for effects or by bold dim smul smso." ;;
"error_input") eval_gettext "The input argument must have %n." ;;
"error_insufficient") eval_gettext "Insufficient number of items." ;;
"error_key") eval_gettext "%s key isn't usable." ;;
"error_key_arg") eval_gettext "%s needs the %s argument." ;;
"error_limit_max") eval_gettext "Maximum limit reached." ;;
"error_limit_zero") eval_gettext "The maximum limit cannot be equal to 0." ;;
"error_max") eval_gettext "%s can no longer serve as a basis." ;;
"error_min") eval_gettext "Number of answer insufficient." ;;
"error_min_sup_choix") eval_gettext "The min value cannot be greater than the number of items." ;;
"error_min_sup_max") eval_gettext "The min value cannot be greater than the max value." ;;
"error_minor") eval_gettext "- needs a MIN value before." ;;
"error_numbers") eval_gettext "The second number must be greater than the first." ;;
"error_range_max") eval_gettext "The range needs a second number." ;;
"error_sign") eval_gettext "A number must precede the - sign." ;;
"error_sign_already") eval_gettext "Impossible to add more - signs." ;;
"error_sign_duplicate") eval_gettext "This value range will unnecessarily duplicate." ;;
"error_unknow") eval_gettext "The %s argument is unknow." ;;
"error_used") eval_gettext "%s number already entered." ;;
"error_wtf") eval_gettext "Please explain to hizo@free.fr how this error happened." ;;
"error_zero") eval_gettext "A number cannot start by 0." ;;
#TranslationAssistance ==============================> Texts
"prompt_entry") eval_gettext "Press the 'Entry' key to see the next example or to exit." ;;
"prompt_text") eval_gettext "Selection: " ;;
"title_min_max_equal") eval_gettext "%s expected answers" ;;
"title_min_max") eval_gettext "Between %s and %s expected answers" ;;
"title_min") eval_gettext "Minimum of %s expected answers" ;;
"title_max") eval_gettext "Maximum of %s expected answers" ;;
### Textes de l'aide dynamique
#TranslationAssistance ==============================> Texts of the dynamic help
"help1") eval_gettext "Help with the use of HizoSelect" ;;
"help2") eval_gettext "Number of expected answers:" ;;
"help3") eval_gettext "Possible answers:" ;;
"help4") eval_gettext "The numbers select their items." ;;
"help5") eval_gettext "The ? select random items." ;;
"help6") eval_gettext "The range select items starts from the first number to the second number included." ;;
"help7") eval_gettext "The * select all items." ;;
"help8") eval_gettext "Press any key for exiting the help." ;;
"help9") eval_gettext "It's possible to select several times a same item." ;;
"help10") eval_gettext "Each item can be only select one time." ;;
### Textes de l'argument aide
#TranslationAssistance ==============================> Texts of the help argument
"arg_help1") eval_gettext "Options:" ;;
"arg_help2") eval_gettext "Effects of commentaries, errors, numbers, prompt text, secret texts, texts and title." ;;
"arg_help3") eval_gettext "Formats the display in column mode." ;;
"arg_help4") eval_gettext "Hides error messages." ;;
"arg_help5") eval_gettext "Pre-filled answers." ;;
"arg_help6") eval_gettext "Demonstration of commands." ;;
"arg_help7") eval_gettext "Displays this help." ;;
"arg_help9") eval_gettext "Format of the items." ;;
"arg_help10") eval_gettext "Maximal number of answers." ;;
"arg_help11") eval_gettext "Minimal number of answers." ;;
"arg_help12") eval_gettext "Allows multiple returns from the same value." ;;
"arg_help13") eval_gettext "Disables all." ;;
"arg_help14") eval_gettext "Disables random." ;;
"arg_help15") eval_gettext "Disables range." ;;
"arg_help16") eval_gettext "Format of the returned items." ;;
"arg_help17") eval_gettext "Displayed text while waiting for the choice." ;;
"arg_help18") eval_gettext "Displayed text before the list of items." ;;
"arg_help19") eval_gettext "Avoids redundant items." ;;
"arg_help20") eval_gettext "Version of the hizoselect command." ;;
"arg_help21") eval_gettext "Examples:" ;;
"arg_help22") eval_gettext "More informations:" ;;
"arg_help23") eval_gettext "item(s) " ;;
"arg_help24") eval_gettext "int " ;;
"arg_help25") eval_gettext "text " ;;
"arg_help26") eval_gettext "Disables display of the help bar." ;;
### Textes des exemples
#TranslationAssistance ==============================> Texts of the examples
"example1") eval_gettext "What example(s) do you want see?" ;;
"example2") eval_gettext "%t=Would you marry me? %c=One number by default with a limit to 1 item and output change" ;;
"example3") eval_gettext "%t=Choose your menu %c=All by default with a input number for read command" ;;
"example4") eval_gettext "%t=Write the name 'Belleguic' %c=Numbers by default with columns format and several mode enable" ;;
"example5") eval_gettext "%t=What can be the age of a minor? %c=Range by default with no-all and no-random" ;;
"example6") eval_gettext "%t=I remove duplicates for you %c=Uniq item option and prompt text change" ;;
"example7") eval_gettext "%t=Advanced input/output argument %c=How-to use format" ;;
"example8") eval_gettext "%t=Use a for loop %c=How-to use returns with for loop" ;;
"example9") eval_gettext "%t=Use multi read %c=How-to use multi while read loop" ;;
"example10") eval_gettext "Command:" ;;
"example11") eval_gettext "Would you marry me? (One number by default)" ;;
"example12") eval_gettext "The number %n is %t (%c) and his secret value is %s." ;;
"example13") eval_gettext "%t=Yes %c=I want it! %s=y" ;;
"example14") eval_gettext "%t=No %c=Sorry... %s=n" ;;
"example15") eval_gettext "I want eat a %t" ;;
"example16") eval_gettext "Choose your menu (All by default):" ;;
"example17") eval_gettext "%t=Entry %c=Vegetables" ;;
"example18") eval_gettext "%t=Dish %c=Steak and fries" ;;
"example19") eval_gettext "%t=Dessert %c=Flan" ;;
"example20") eval_gettext "Write the name 'Belleguic' (Numbers by default)" ;;
"example21") eval_gettext "You write:" ;;
"example22") eval_gettext "What can be the age of a minor?" ;;
"example23") eval_gettext "A minor may be aged: %s years" ;;
"example24") eval_gettext "I remove duplicates for you:" ;;
"example25") eval_gettext "You have choiced: %t" ;;
"example26") eval_gettext "I wait after you:" ;;
"example27") eval_gettext "Advanced input/output argument:" ;;
"example28") eval_gettext "[%n] (mandatory) <%t and %c and %s (text and commentary and secret text)|%t and %c (text and commentary)|%t and %s (text and secret text)|%c and %s (commentary and secret text)|%t (text)|%c (commentary)|%s (secret text)>" ;;
"example29") eval_gettext "\<%n\> (always exists) \| <%t and %c and %s (text and commentary and secret text)|%t and %c (text and commentary)|%t and %s (text and secret text)|%c and %s (commentary and secret text)|%t (text)|%c (commentary)|%s (secret text)>" ;;
"example34") eval_gettext "What do you hate?" ;;
"example35") eval_gettext "Clown noses" ;;
"example36") eval_gettext "Plastic guns" ;;
"example37") eval_gettext "Yourself" ;;
"example38") eval_gettext "Other people" ;;
"example39") eval_gettext "I choosen %s." ;;
"example40") eval_gettext "Let's go to eat at %s!" ;;
"example41") eval_gettext "I want then menu at %s." ;;
"example42") eval_gettext "I want eat %s." ;;
"example43") eval_gettext "What do you want eat?" ;;
"example44") eval_gettext "What menu do you want?" ;;
"example45") eval_gettext "Where do you want to eat?" ;;
### Textes de la barre d'aide
#TranslationAssistance ==============================> h letter for help
"info_help_letter") eval_gettext "h" ;;
"info_help_on") eval_gettext "Help" ;;
#TranslationAssistance ==============================> c letter for effects
"info_effect_letter") eval_gettext "c" ;;
"info_effect_on") eval_gettext "Enable effects" ;;
"info_effect_off") eval_gettext "Disable effects" ;;
#TranslationAssistance ==============================> v letter for view
"info_view_letter") eval_gettext "v" ;;
"info_view_on") eval_gettext "View in columns" ;;
"info_view_off") eval_gettext "View in lines" ;;
#TranslationAssistance ==============================> d letter for debug
"info_debug_letter") eval_gettext "d" ;;
"info_debug_on") eval_gettext "Enable debug" ;;
"info_debug_off") eval_gettext "Disable debug" ;;
#TranslationAssistance ==============================> l letter for lang
"info_lang_letter") eval_gettext "l" ;;
"info_lang_on") eval_gettext "French translation" ;;
"info_lang_off") eval_gettext "English translation" ;;
#TranslationAssistance ==============================> e letter for exit
"info_exit_letter") eval_gettext "e" ;;
"info_exit_on") eval_gettext "Exit" ;;
esac
}
#########################
## Début des commandes ##
#########################
### Nettoyage de l'ecran
clear >&2
### Traduction des textes et chargement des valeurs
LangText
### Effets
EffectsSetUp off
##############################
## Traitement des arguments ##
##############################
# getopts ne sert qu'en cas d'utilisation de argument d'1 lettre et qu'on puisse les assembler, donc pas d’intérêt ici
# utilisation de ${@} et non de ${1} car si la variable est vide ça stoppe
while [[ ${@} ]]
do
# Variable stoppant les arguments
if [[ -z ${StopArg} ]]
then
# Teste chaque argument
# Les shift internes servent pour décaler d'un niveau de plus pour éliminer la valeur ${2}
# Met en minuscule les arguments longs mais pas les courts
[[ ${1} =~ ^-[a-Z]$ ]] && Value="${1}" || Value="${1,,}"
case "${Value}" in
"--")
# Valeur spéciale permettant d'indiquer que les arguments sont terminées
StopArg=true ;;
"-c"|"--columns")
Columns=true ;;
"-d"|"--default")
[[ ${2} != -* ]] && Default=(${2})
[[ -z ${Default[@]} ]] && { printf "${Effects["Errors"]}$(LangText "argument")${Effects["Unset"]}\n" "${1}" >&2; ExitErreur; }
Default=(${Default[@]//[,;+]/ }) # Transformation en espace de différents sigles
shift ;;
"-e"|"--effects")
[[ ${2} == -* || -z ${2} ]] && { [[ ${Debug} ]] && printf "${Effects["Errors"]}$(LangText "argument")${Effects["Unset"]}\n" "${1}" >&2; exit 1; }
if [[ ${2} == "auto" ]]
then
EffectsSetUp "auto-arg"
elif [[ ${2} ]]
then
# Variable conservant en mémoire les couleurs
declare -Ag DefineEffects
# Boucle sur les différents noms de couleur
for NameAndLetter in "Commentaries %c" "Errors %e" "Numbers %n" "Secret %s" "Texts %t" "Title %T" "Prompt %p"
do
# Récupération des valeurs l'initiale
Letter=${NameAndLetter/#* }
Name=${NameAndLetter/% *}
# Si la variable est utilisée
if [[ ${2} =~ "${Letter}" ]]
then
# on récupére la valeur
Effect="${2#*${Letter}=}"
Effect="${Effect%% *}"
# Boucle sur les effets
for Effect in ${Effect//// }
do
# Si c'est un nombre, c'est la couleur du texte
if [[ ${Effect} =~ ^[0-9]*$ ]]
then
Effects[${Name}]=$(tput setaf ${Effect})
DefineEffects[${Name}]=$(tput setaf ${Effect})
Effects["Exists"]=true
DefineEffects["Exists"]=true
# Si c'est un bg + un nombre
elif [[ ${Effect,,} =~ ^bg[0-9]*$ ]]
then
Effects[${Name}]+=$(tput setab ${Effect/#bg})
DefineEffects[${Name}]+=$(tput setab ${Effect/#bg})
Effects["Exists"]=true
DefineEffects["Exists"]=true
# Si c'est un effet de texte
elif [[ ${Effect,,} =~ ^"bold"|"blink"|"dim"|"rev"|"smul"|"smso"$ ]]
then
Effects[${Name}]+=$(tput ${Effect})
DefineEffects[${Name}]+=$(tput ${Effect})
Effects["Exists"]=true
DefineEffects["Exists"]=true
# Dans les autres cas, message d'erreur
else
[[ ${Debug} ]] && echo -e "${Effects["Errors"]}$(LangText "error_effects")${Effects["Unset"]}" >&2; exit 1
fi
done
fi
done
fi
shift
;;
"-E"|"--ex"|"--eg"|"--examples")
IFS=$'\n' Choice=($("${0}" --title "$(LangText example1)" --output "%n" \
"$(LangText example2)" \
"$(LangText example3)" \
"$(LangText example4)" \
"$(LangText example5)" \
"$(LangText example6)" \
"$(LangText example7)" \
"$(LangText example8)" \
"$(LangText example9)"))
for Example in ${Choice[@]}
do
# Nettoyage du terminal
clear >&2
[[ "${Example}" == "Exit" ]] && exit 1
case "${Example}" in
1) # Demande de mariage
echo -e "$(LangText example10)
${Effects["Numbers"]}${0} ${Effects["Errors"]}--max ${Effects["Unset"]}\"${Effects["Commentaries"]}1${Effects["Unset"]}\" ${Effects["Errors"]}--title ${Effects["Unset"]}\"${Effects["Commentaries"]}$(LangText example11)${Effects["Unset"]}\" ${Effects["Errors"]}--default ${Effects["Unset"]}\"${Effects["Commentaries"]}1${Effects["Unset"]}\" ${Effects["Errors"]}--output ${Effects["Unset"]}\"${Effects["Commentaries"]}\\\n$(LangText example12)\\\n${Effects["Unset"]}\" \"${Effects["Texts"]}$(LangText example13)${Effects["Unset"]}\" ${Effects["Unset"]}\"${Effects["Texts"]}$(LangText example14)${Effects["Unset"]}\"\n"
;;
2) # Choix de menu
echo -e "$(LangText example10)
${Effects["Numbers"]}${0}${Effects["Errors"]} ${Effects["Errors"]}--default ${Effects["Unset"]}\"${Effects["Commentaries"]}*${Effects["Unset"]}\" ${Effects["Errors"]}--output ${Effects["Unset"]}\"${Effects["Commentaries"]}$(LangText example15)${Effects["Unset"]} \"${Effects["Errors"]}--title ${Effects["Unset"]}\"${Effects["Commentaries"]}$(LangText example16)${Effects["Unset"]}\" "${Effects["Texts"]}$(LangText example17)${Effects["Unset"]}\" "${Effects["Texts"]}$(LangText example18)${Effects["Unset"]}\" \"${Effects["Texts"]}$(LangText example19)${Effects["Unset"]}\"\n"
;;
3) # Ecriture d'un nom avec permission d'ecrire plusieurs fois la même valeur et affichage en colonnes
echo -e "$(LangText example10)
${Effects["Numbers"]}${0} ${Effects["Errors"]}--several --columns ${Effects["Errors"]}--title ${Effects["Unset"]}\"${Effects["Commentaries"]}$(LangText example20)${Effects["Unset"]}\" ${Effects["Errors"]}--default ${Effects["Unset"]}\"${Effects["Commentaries"]}2 5 12 12 5 7 21 9 3${Effects["Unset"]}\" ${Effects["Texts"]}{a..z}${Effects["Unset"]}\n
echo -e \"$(LangText example21) \${Name//[[:space:]]/}\n"
;;
4) # Plage des ages des mineurs
echo -e "$(LangText example10)
${Effects["Numbers"]}${0} ${Effects["Errors"]}--columns ${Effects["Errors"]}--default ${Effects["Unset"]}\"${Effects["Commentaries"]}1-17${Effects["Unset"]}\" ${Effects["Errors"]}--title ${Effects["Unset"]}\"${Effects["Commentaries"]}$(LangText example22)${Effects["Unset"]}\" ${Effects["Texts"]}{1..30}${Effects["Unset"]}\n
printf \"\\\n$(LangText example23)\" \"${Ages//\$'\n'/ - }"
;;
5) # Propositions uniques
echo -e "$(LangText example10)
${Effects["Numbers"]}${0} ${Effects["Errors"]}--uniq-item --title ${Effects["Unset"]}\"${Effects["Commentaries"]}$(LangText example24)${Effects["Unset"]}\" ${Effects["Errors"]}--output ${Effects["Unset"]}\"${Effects["Commentaries"]}$(LangText example25)${Effects["Unset"]}\" ${Effects["Errors"]}--prompt ${Effects["Unset"]}\"${Effects["Commentaries"]}$(LangText example26)${Effects["Unset"]}\" ${Effects["Texts"]}{a..f} {f..a}${Effects["Unset"]}\n"
;;
6) # Utilisation des formats
echo -e "$(LangText example10)
${Effects["Numbers"]}${0} ${Effects["Errors"]}--default ${Effects["Unset"]}\"${Effects["Commentaries"]}*${Effects["Unset"]}\" ${Effects["Errors"]}--title ${Effects["Unset"]}\"${Effects["Commentaries"]}$(LangText example27)${Effects["Unset"]}\" ${Effects["Errors"]}--input ${Effects["Unset"]}\"${Effects["Commentaries"]}$(LangText example28)${Effects["Unset"]}\" ${Effects["Errors"]}--output ${Effects["Unset"]}\"${Effects["Commentaries"]}$(LangText example29)${Effects["Unset"]}\" \"${Effects["Texts"]}%t=Bonjour %c=French %s=Hello${Effects["Unset"]}\" \"${Effects["Texts"]}%t=Buongiorno %c=Italiano${Effects["Unset"]}\" \"${Effects["Texts"]}%t=Hallo %s=Hello${Effects["Unset"]}\" \"${Effects["Texts"]}%c=Japness %s=Hello${Effects["Unset"]}\" \"${Effects["Texts"]}%t=안녕하세요${Effects["Unset"]}\" \"${Effects["Texts"]}%c=صباح الخير${Effects["Unset"]}\" \"${Effects["Texts"]}%s=ஹலோ${Effects["Unset"]}\"\n"
;;
7) # Utilisation d'une boucle for
echo -e "$(LangText example10)
IFS=$'\\\n' Choice=(\$(${Effects["Numbers"]}${0}${Effects["Errors"]} --title ${Effects["Unset"]}\"${Effects["Commentaries"]}$(LangText example34)${Effects["Unset"]}\" "${Effects["Texts"]}$(LangText example35)${Effects["Unset"]}\" \"${Effects["Texts"]}$(LangText example36)${Effects["Unset"]}\" \"${Effects["Texts"]}$(LangText example37)${Effects["Unset"]}\" \"${Effects["Texts"]}$(LangText example38)${Effects["Unset"]}"))
for Value in \"\${Choice[@]}\"; do printf \"$(LangText example39)\" \"${Value}\"; done\n"
;;
8) # Utilisation de boucles whilre read imbriquées
echo -e "$(LangText example10)
while read ${Effects["Errors"]}-u 4${Effects["Unset"]} Restaurant
do
printf \"$(LangText example40)\\\n\" \"\${Restaurant}\"
while read ${Effects["Errors"]}-u 3${Effects["Unset"]} Menu
do
printf \"$(LangText example41)\\\n\" \"${Menu}\"
while read Dish
do
printf \"$(LangText example42)\\\n\" \"\${Dish}\"
done < <(${Effects["Numbers"]}${0}${Effects["Errors"]} --title ${Effects["Unset"]}\"${Effects["Commentaries"]}$(LangText example43)${Effects["Unset"]}\" \"${Effects["Texts"]}Cassoulet${Effects["Unset"]}\" \"${Effects["Texts"]}Coq au vin${Effects["Unset"]}\" \"${Effects["Texts"]}Fois gras${Effects["Unset"]}\" \"${Effects["Texts"]}Galettes${Effects["Unset"]}\" \"${Effects["Texts"]}Tartiflette${Effects["Unset"]}\")
done ${Effects["Errors"]}3${Effects["Unset"]}< <(${Effects["Numbers"]}${0}${Effects["Errors"]} --title ${Effects["Unset"]}\"${Effects["Commentaries"]}$(LangText example44)${Effects["Unset"]}\" \"${Effects["Texts"]}20\$${Effects["Unset"]}\" \"${Effects["Texts"]}35\$${Effects["Unset"]}\" \"${Effects["Texts"]}50\$${Effects["Unset"]}\")
done ${Effects["Errors"]}4${Effects["Unset"]}< <(${Effects["Numbers"]}${0}${Effects["Errors"]} --title ${Effects["Unset"]}\"${Effects["Commentaries"]}$(LangText example45)${Effects["Unset"]}\" \"${Effects["Texts"]}Chez bebert${Effects["Unset"]}\" \"${Effects["Texts"]}Au bon foin${Effects["Unset"]}\" \"${Effects["Texts"]}Chez tata boudin${Effects["Unset"]}\")\n"
;;
# Permet d'éviter des ennuis
*) continue ;;
esac
# Texte d'attente
read -p "${Effects["Prompt"]}$(LangText "prompt_entry")${Effects["Unset"]}"
done
exit 0 ;;
"-h"|"-?"|"--help")
echo -e "\n${Effects["Numbers"]}$(LangText "arg_help1")${Effects["Unset"]}
\t${Effects["Errors"]}-c, --columns${Effects["Unset"]}\t\t\t\t$(LangText "arg_help3")
\t${Effects["Errors"]}-d, --default${Effects["Texts"]} $(LangText "arg_help23")${Effects["Unset"]}\t\t$(LangText "arg_help5")
\t${Effects["Errors"]}-e, --effects${Effects["Texts"]} auto %c %e %n %p %s %t %T${Effects["Unset"]}\t$(LangText "arg_help2")
\t${Effects["Errors"]}-E, --examples${Effects["Unset"]}\t\t\t\t$(LangText "arg_help6")
\t${Effects["Errors"]}-h, --help${Effects["Unset"]}\t\t\t\t$(LangText "arg_help7")
\t${Effects["Errors"]}-i, --input${Effects["Texts"]} %c %n %s %t${Effects["Unset"]}\t\t\t$(LangText "arg_help9")
\t${Effects["Errors"]}-M, --max${Effects["Texts"]} $(LangText "arg_help24")${Effects["Unset"]}\t\t\t$(LangText "arg_help10")
\t${Effects["Errors"]}-m, --min${Effects["Texts"]} $(LangText "arg_help24")${Effects["Unset"]}\t\t\t$(LangText "arg_help11")
\t${Effects["Errors"]}-a, --no-all${Effects["Unset"]}\t\t\t\t$(LangText "arg_help13")
\t${Effects["Errors"]}-b, --no-bar${Effects["Unset"]}\t\t\t\t$(LangText "arg_help26")
\t${Effects["Errors"]}-D, --no-debug${Effects["Unset"]}\t\t\t\t$(LangText "arg_help4")
\t${Effects["Errors"]}-r, --no-random${Effects["Unset"]}\t\t\t\t$(LangText "arg_help14")
\t${Effects["Errors"]}-R, --no-range${Effects["Unset"]}\t\t\t\t$(LangText "arg_help15")
\t${Effects["Errors"]}-o, --output${Effects["Texts"]} %c %n %s %t${Effects["Unset"]}\t\t$(LangText "arg_help16")
\t${Effects["Errors"]}-p, --prompt${Effects["Texts"]} $(LangText "arg_help25")${Effects["Unset"]}\t\t\t$(LangText "arg_help17")
\t${Effects["Errors"]}-s, --several${Effects["Unset"]}\t\t\t\t\t$(LangText "arg_help12")
\t${Effects["Errors"]}-t, --title${Effects["Texts"]} $(LangText "arg_help25")${Effects["Unset"]}\t\t\t$(LangText "arg_help18")
\t${Effects["Errors"]}-u, --uniq-item${Effects["Unset"]}\t\t\t\t$(LangText "arg_help19")
\t${Effects["Errors"]}-v, --version${Effects["Unset"]}\t\t\t\t$(LangText "arg_help20")
${Effects["Numbers"]}$(LangText "arg_help21")${Effects["Unset"]}
\t${Effects["Secrets"]}hizoselect${Effects["Errors"]} --examples${Effects["Unset"]}
${Effects["Numbers"]}$(LangText "arg_help22")${Effects["Unset"]}
\t${Effects["Secrets"]}man${Effects["Errors"]} hizoselect${Effects["Unset"]}" >&2
exit 0 ;;
"-i"|"--input")
[[ ${2} != -* ]] && InputText=${2}
[[ -z ${InputText} ]] && { printf "${Effects["Errors"]}$(LangText "argument")${Effects["Unset"]}\n" "${1}" >&2; ExitErreur; }
shift ;;
"-m"|"--min")
[[ ${2} != -* ]] && Min=${2}
[[ -z ${Min} ]] && { printf "${Effects["Errors"]}$(LangText "argument")${Effects["Unset"]}\n" "${1}" >&2; ExitErreur; }
shift ;;
"-M"|"--max")
[[ ${2} != -* ]] && Max=${2}
[[ -z ${Max} ]] && { printf "${Effects["Errors"]}$(LangText "argument")${Effects["Unset"]}\n" "${1}" >&2; ExitErreur; }
shift ;;
"--no-all") unset All ;;
"-b"|"--no-bar") unset Bar ;;
"-D"|"--no-debug") unset Debug ;;
"--no-random") unset Random ;;
"--no-range") unset Range ;;
"-o"|"--output")
[[ ${2} != -* ]] && OutputText="${2}"
[[ -z ${OutputText} ]] && { printf "${Effects["Errors"]}$(LangText "argument")${Effects["Unset"]}\n" "${1}" >&2; ExitErreur; }
shift ;;
"-p"|"--prompt")
[[ ${2} != -* ]] && PromptText="${2}"
[[ -z ${PromptText} ]] && { printf "${Effects["Errors"]}$(LangText "argument")${Effects["Unset"]}\n" "${1}" >&2; ExitErreur; }
[[ ${PromptText: -1} == [0-9] ]] && PromptText+=" " # Ajout d'un espace si la derniere valeur du texte est un nombre car ça va gener le read
Texts["prompt_text"]="${PromptText} "
shift ;;
"-s"|"--several") unset Uniq ;;
"-t"|"--title")
[[ ${2} != -* ]] && Title="${2}"
[[ -z ${Title} ]] && { printf "${Effects["Errors"]}$(LangText "argument")${Effects["Unset"]}\n" "${1}" >&2; ExitErreur; }
shift ;;
"-u"|"--uniq-item")
UniqueItem=true ;;
"-v"|"--version")
echo -e "HizoScript version ${Version}.\n${Licence}." >&2
exit 0 ;;
-*)
# Si un autre argument est donné
printf "${Effects["Errors"]}$(LangText "error_unknow")${Effects["Unset"]}\n" "${1}" >&2; ExitErreur ;;
*)
# Si c'est du texte sans argument, c'est que c'est une réponse possible
# Si la variable est vide, on ne la prend pas
if [[ ${1} && ${UniqueItem} ]]
then
# N'ajoute la valeur que si elle n'existe pas
[[ -z $(grep -w "${1}" <<< "${Choix[@]}") ]] && Choix+=("${1}")
elif [[ ${1} ]]
then
# Ajoute la valeur quelque soit le cas
Choix+=("${1}")
fi ;;
esac
else
# Si on est ici, c'est qu'on a utilisé --, du coup, tout ce qui suit sert de proposition
# Si la variable est vide, on ne la prend pas
if [[ ${1} && ${UniqueItem} ]]
then
# N'ajoute la valeur que si elle n'existe pas
[[ -z $(grep -w "${1}" <<< "${Choix[@]}") ]] && Choix+=("${1}")
elif [[ ${1} ]]
then
# Ajoute la valeur quelque soit le cas
Choix+=("${1}")
fi
fi
# On décale les arguments ${1} est détruit, ${2} devient ${1}, ${3} devient ${2}...
shift
done
### Suppression de la valeur 0 maintenant que la liste est remplie
unset Choix[0]
# Bloque le mode --all avec --max si la limite est superieur au nombre de proposition
[[ ${All} && -z ${Uniq} && ${Max} -gt 0 && ${Max} -lt ${#Choix[@]} ]] && unset All
# Bloque le mode --all avec --max si la limite est inferieur au nombre de proposition
[[ ${All} && ${Max} -gt 0 && ${Max} -lt ${#Choix[@]} ]] && unset All
# Bloque le mode --range si le nombe de réponse possible est de 1
[[ ${Range} && ${Max} -eq 1 ]] && unset Range
###################
## Vérifications ##
###################
# Vérifie qu'il y a bien des propositions
[[ ${#Choix[@]} -lt 1 ]] && { echo -e "${Effects["Errors"]}$(LangText "error_insufficient")${Effects["Unset"]}" >&2; ExitErreur; }
# Vérifie que min ne soit pas plus grande que max
[[ ${Min} -gt 0 && ${Max} -gt 0 && ${Min} -gt ${Max} ]] && { [[ ${Debug} ]] && echo -e "${Effects["Errors"]}$(LangText "error_min_sup_max")${Effects["Unset"]}" >&2; ExitErreur; }
# Vérifie que min ne soit pas plus grand que le nombre de réponse si uniq est actif
[[ ${Uniq} && ${Min} -gt ${#Choix[@]} ]] && { [[ ${Debug} ]] && echo -e "${Effects["Errors"]}$(LangText "error_min_sup_choix")${Effects["Unset"]}" >&2; ExitErreur; }
# Si le mode uniq est actif et que la limite dépasse le nombre de proposition
[[ ${Uniq} && ${Max} -gt ${#Choix[@]} ]] && { [[ ${Debug} ]] && echo -e "${Effects["Errors"]}$(LangText "error_default_limit2")${Effects["Unset"]}" >&2; ExitErreur; }
# Vérifications en lien avec le mode all
[[ "${Default[@]}" =~ "*" && ${#Default[@]} > 1 ]] && { [[ ${Debug} ]] && echo -e "${Effects["Errors"]}$(LangText "error_default_star")${Effects["Unset"]}" >&2; ExitErreur; }
[[ -z ${All} && "${Default[@]}" =~ "*" ]] && { [[ ${Debug} ]] && printf "${Effects["Errors"]}$(LangText "error_default_mode")${Effects["Unset"]}\n" "*" "all" >&2; ExitErreur; }
# Vérifications en lien avec le mode random
[[ -z ${Random} && "${Default[@]}" =~ "?" ]] && { [[ ${Debug} ]] && printf "${Effects["Errors"]}$(LangText "error_default_mode")${Effects["Unset"]}\n" "?" "random" >&2; ExitErreur; }
# Vérifications en lien avec le mode range
[[ -z ${Range} && "${Default[@]}" =~ "-" ]] && { [[ ${Debug} ]] && printf "${Effects["Errors"]}$(LangText "error_default_mode")${Effects["Unset"]}\n" "-" "range" >&2; ExitErreur; }
# Vérifie les valeurs par défaut
for Number in "${Default[@]}"
do
# Si la valeur est ? ou *, on saute le tour
[[ "${Number}" == [?*] ]] && continue
# Si le chiffre commence par un 0, on arrête là
if [[ "${Number:0:1}" == "0" ]]
then
[[ ${Debug} ]] && echo -e "${Effects["Errors"]}$(LangText "error_zero")${Effects["Unset"]}" >&2
ExitErreur
# Si c'est une plage
elif [[ "${Number}" =~ "-" ]]
then
RangeCheck ${Number} || ExitErreur
# Teste du nombre
elif [[ -z $(printf "%s\n" "${!Choix[@]}" | grep "^${Number}$") ]]
then
[[ ${Debug} ]] && echo -e "${Effects["Errors"]}$(LangText "error_default_check")${Effects["Unset"]}" "${Number}" >&2
ExitErreur
fi
done
# Création d'une limite sous-entendue liée au nombre de proposition
[[ ${Max} -eq 0 && ${Uniq} ]] && MaxImplied=${#Choix[@]}
# Vérifie le nombre de valeur par défaut
if [[ ${Default[@]} ]]
then
AnswerLimit "${Default[*]}" "${!Choix[*]}" "ModeGT" || { [[ ${Debug} ]] && printf "${Effects["Errors"]}$(LangText "error_default_limit")${Effects["Unset"]}\n" "${Number}" >&2; ExitErreur; }
fi
##########################
## Affichage des textes ##
##########################
# Affichage du titre et des propositions
DisplayTexts
##########################
## Attente des réponses ##
##########################
# Saut de ligne esthétique
echo >&2
### Variables
# Pour le nettoyage complet de la ligne
Clear=$(tput el)
# Valeur par défaut
[[ ${Default[@]} ]] && Reponses=("${Default[@]}") || Reponses=()
# Affichage du texte d'attente
LastText
echo -en "${LastText}" >&2
# Variables contenant les lettres raccourcis pour eviter de les charger à chaque tour de read
DebugLetter=$(LangText info_debug_letter)
EffectLetter=$(LangText info_effect_letter)
ViewLetter=$(LangText info_view_letter)
LangLetter=$(LangText info_lang_letter)
ExitLetter=$(LangText info_exit_letter)
HelpLetter=$(LangText info_help_letter)
# Boucle attendant qu'en entre une valeur au clavier
while IFS='' read -r -sn 1 Touche
do
unset ValueTemp
# Traitement de la touche
case "${Touche,,}" in
# Ajout des chiffres
[0-9])
# Si * était dans default
[[ "${Reponses[@]}" =~ "*" ]] && unset Reponses
# Si la variable temporaire est vide ou contient un nombre
if [[ -z ${ReponseTemp} || ${ReponseTemp} =~ ^[0-9]+$ ]]
then
# Indique le nombre à utiliser
[[ ${ReponseTemp} ]] && Number="${ReponseTemp}${Touche}" || Number="${Touche}"
# Si le nombre peut grandir
NumberDigit ${Number} "${!Choix[*]}" "${Reponses[*]}"
case ${?} in
# On peut aller plus loin mais on vérifie q'il reste de la place
0|1) AnswerLimit "${Reponses[*]}" "${!Choix[*]}" && ReponseTemp+=${Touche} || continue ;;
# On ne peut aller plus loin
2) AnswerAdd "${Number}" "${Reponses[*]}" "${!Choix[*]}" && { Reponses+=(${Number}); unset ReponseTemp; } || continue ;;
# Il faut stopper là
3|4|5) continue ;;
esac
elif [[ "${ReponseTemp}" =~ "-" ]]
then
ValueTemp="${ReponseTemp%-*}"
ReponseTemp="${ReponseTemp#*-}"
# Indique le nombre à utiliser
[[ ${ReponseTemp} ]] && Number="${ReponseTemp}${Touche}" || Number="${Touche}"
# Si le nombre peut grandir
NumberDigit ${Number} "${!Choix[*]}" "${Reponses[*]}"
case ${?} in
# On peut aller plus loin mais on vérifie q'il reste de la place
0|1) AnswerLimit "${Reponses[*]}" "${!Choix[*]}" && ReponseTemp+="${ValueTemp}-${Number}" || continue ;;
# On ne peut aller plus loin
2)
# Vérification de la plage
if RangeCheck "${ValueTemp}-${Number}"
then
# Si la limite n'est pas atteinte
if AnswerAdd "${ValueTemp}-${Number}" "${Reponses[*]}" "${!Choix[*]}" && AnswerLimit "${ActualList[*]}" "${Items[*]}"
then
# Ajoute la nouvelle valeur à la liste
Reponses+=("${ValueTemp}-${Number}")
unset ReponseTemp
else
# Rend la valeur initiale à la variable temp
ReponseTemp="${ValueTemp}-${ReponseTemp}"
continue
fi
else
# Rend la valeur initiale à la variable temp
ReponseTemp="${ValueTemp}-${ReponseTemp}"
continue
fi ;;
# Il faut stopper là
3) continue ;;
# Rend la valeur initiale à la variable temp
4|5) ReponseTemp="${ValueTemp}-${ReponseTemp}"; continue ;;
esac
# Dans les autres cas
else
echo -en "\r${Clear}${Effects["Errors"]}$(LangText "error_wtf")${Effects["Unset"]} ${LastText}" >&2
continue
fi
# Affichage du nouveau texte
LastText
echo -en "\r${Clear}${LastText}" >&2
;;
# En cas de changement du mode d'affichage ou de debug ou de langue
${DebugLetter}|${EffectLetter}|${ViewLetter}|${LangLetter})
# Nettoyage du terminal
clear >&2
# Inversion de la valeur
if [[ ${Touche,,} == ${ViewLetter} ]]
then
[[ ${Columns} ]] && unset Columns || Columns=true
elif [[ ${Touche,,} == ${DebugLetter} ]]
then
[[ ${Debug} ]] && unset Debug || Debug=true
elif [[ ${Touche,,} == ${EffectLetter} ]]
then
[[ ${Effects["Exists"]} ]] && EffectsSetUp off || EffectsSetUp on
elif [[ ${Touche,,} == ${LangLetter} ]]
then
[[ ${LANGUAGE} =~ "en" ]] && export LANGUAGE=fr || export LANGUAGE=en
DebugLetter=$(LangText info_debug_letter)
EffectLetter=$(LangText info_effect_letter)
ViewLetter=$(LangText info_view_letter)
LangLetter=$(LangText info_lang_letter)
ExitLetter=$(LangText info_exit_letter)
HelpLetter=$(LangText info_help_letter)
fi
# Affichage des textes
DisplayTexts
# Affichage du nouveau texte
LastText
echo
echo -n "${LastText}" >&2
;;
${HelpLetter})
# Nettoyage du terminal
clear >&2
# Affichage de l'aide
echo -e "${Effects["Errors"]}$(LangText "help1")${Effects["Unset"]}" >&2
[[ ${Min} -gt 0 || ${Max} -gt 0 || ${MaxImplied} -gt 0 ]] && echo -e "\n$(LangText "help2")" >&2
[[ ${Min} -gt 0 ]] && printf " - ${Effects["Commentaries"]}$(LangText "title_min")${Effects["Unset"]}\n" "${Min}" >&2
[[ ${Max} -gt 0 ]] && printf " - ${Effects["Commentaries"]}$(LangText "title_max")${Effects["Unset"]}\n" "${Max}" >&2
[[ ${MaxImplied} -gt 0 ]] && printf " - ${Effects["Commentaries"]}$(LangText "title_max")${Effects["Unset"]}\n" "${MaxImplied}" >&2
echo -e "\n$(LangText "help3")" >&2
[[ ${Uniq} ]] && echo -e "${Effects["Texts"]}$(LangText "help10")${Effects["Unset"]}" || echo -e "${Effects["Texts"]}$(LangText "help10")${Effects["Unset"]}" >&2
echo -e " - [${Effects["Numbers"]}0-9${Effects["Unset"]}] : ${Effects["Texts"]}$(LangText "help4")${Effects["Unset"]}${Effects["Unset"]}" >&2
[[ ${Random} ]] && echo -e " - [${Effects["Numbers"]}?${Effects["Unset"]}] : ${Effects["Texts"]}$(LangText "help5")${Effects["Unset"]}" >&2
[[ ${Range} ]] && echo -e " - [${Effects["Numbers"]}x-y${Effects["Unset"]}] : ${Effects["Texts"]}$(LangText "help6")${Effects["Unset"]}" >&2
[[ ${All} ]] && echo -e " - [${Effects["Numbers"]}*${Effects["Unset"]}] : ${Effects["Texts"]}$(LangText "help7")${Effects["Unset"]}" >&2
echo -e "\n$(LangText "help8")" >&2
# Read attendant qu'une touche soit enfoncée avec cache du curseur
tput civis; read -sn 1; tput cnorm
# Nettoyage du terminal
clear >&2
# Affichage des textes
DisplayTexts
# Affichage du nouveau texte
LastText
echo
echo -n "${LastText}" >&2
;;
# Si - est utilisé
"-")
# Si la valeur temporaire est vide, et que la valeur précédente de la liste est un nombre, on l'utilise
if [[ -z ${ReponseTemp} && ${Reponses[@]} && ${Reponses[-1]} =~ ^[0-9]+$ ]]
then
ReponseTemp="${Reponses[-1]}"
unset Reponses[-1]
fi
# Si l'option n'est pas utilisée, on saute la touche
if [[ -z ${Range} ]]
then
[[ ${Debug} ]] && printf "\r${Clear}${Effects["Errors"]}$(LangText "error_key_arg")${Effects["Unset"]} ${LastText}" "-" "--range" >&2
continue
# Si ReponseTemp est vide
elif [[ -z ${ReponseTemp} ]]
then
echo -en "\r${Clear}${Effects["Errors"]}$(LangText "error_sign")${Effects["Unset"]} ${LastText}" >&2
continue
# Si ReponseTemp contient un autre -
elif [[ ${ReponseTemp} =~ "-" ]]
then
echo -en "\r${Clear}${Effects["Errors"]}$(LangText "error_sign_already")${Effects["Unset"]} ${LastText}" >&2
continue
fi
# Bloque le - si la plage va faire doublon, pour éviter 2-3 1-
if [[ ${Uniq} ]]
then
# Récup les valeurs actuels
ActualList=($(AnswerGet "${Reponses[*]}" "${!Choix[*]}"))
# Recherche une valeur trop proche de celle qui vient d'etre utilisée
[[ $(grep -w "$[ReponseTemp + 1]" <<< "${ActualList[@]}") ]] && { echo -en "\r${Clear}${Effects["Errors"]}$(LangText "error_sign_duplicate")${Effects["Unset"]} ${LastText}" >&2; continue; }
fi
# Ajout du - à ReponseTemp
ReponseTemp+="-"
# Affichage du nouveau texte
LastText
echo -en "\r${Clear}${LastText}" >&2
;;
"?")
# Si l'option n'est pas utilisée, on saute la touche
[[ -z ${Random} ]] && { [[ ${Debug} ]] && printf "\r${Clear}${Effects["Errors"]}$(LangText "error_key_arg")${Effects["Unset"]} ${LastText}" "?" "--random" >&2; continue; }
# Si * était dans default
[[ "${Reponses[@]}" =~ "*" ]] && unset Reponses
# Verifie qu'on peut ajouter une valeur
AnswerAdd "?" "${Reponses[*]}" "${!Choix[*]}" && { Reponses+=("?"); unset ReponseTemp; } || continue
# Affichage du nouveau texte
LastText
echo -en "\r${Clear}${LastText}" >&2
;;
# Remplacement du contenu par le * avec un clear de la ligne
"*")
# Si l'option n'est pas utilisée, on saute la touche
[[ -z ${All} ]] && { [[ ${Debug} ]] && printf "\r${Clear}${Effects["Errors"]}$(LangText "error_key_arg")${Effects["Unset"]} ${LastText}" "*" "--all" >&2; continue; }
# Remplace la liste par *
Reponses=("*")
# Destruction de la variable temporaire
unset ReponseTemp
# Affichage du nouveau texte
LastText
echo -en "\r${Clear}${LastText}" >&2
;;
# Remplacement des tab et des virgules par des espaces
" "|","|";"|"+"|$'\011')
# Vérifie le respect de la limitation
AnswerLimit "${Reponses[*]}" "${!Choix[*]}" || continue
# Pour eviter les doubles espaces
if [[ ${#ReponseTemp} -eq 0 ]]
then
[[ ${Debug} ]] && echo -en "\r${Clear}${Effects["Errors"]}$(LangText "error_double_espace")${Effects["Unset"]} ${LastText}" >&2
continue
fi
# Si la variable temporaire contient -
if [[ "${ReponseTemp}" =~ "-" ]]
then
# Vérification du 2e nombre, il faut qu'il soit supérieur au 1er
if RangeCheck ${ReponseTemp}
then
ReponseTemp="${ReponseTemp%-*}-"
continue
else
AnswerAdd "${ReponseTemp}" "${Reponses[*]}" "${!Choix[*]}" && { Reponses+=("${ReponseTemp}"); unset ReponseTemp; } || continue
fi
# Ajout du nombre à la liste
elif [[ ${Uniq} && ${ReponseTemp} != "?" ]]
then
# Réponse déjà présente
if [[ ${Reponses[@]} && $(grep -w "${ReponseTemp}" <<< "${Reponses[@]}") ]]
then
[[ ${Debug} ]] && printf "\r${Clear}${Effects["Errors"]}$(LangText "error_used")${Effects["Unset"]} ${LastText}" "${ReponseTemp}" >&2
continue
else
AnswerAdd "${ReponseTemp}" "${Reponses[*]}" "${!Choix[*]}" && { Reponses+=("${ReponseTemp}"); unset ReponseTemp; } || continue
fi
else
AnswerAdd "${ReponseTemp}" "${Reponses[*]}" "${!Choix[*]}" && { Reponses+=("${ReponseTemp}"); unset ReponseTemp; } || continue
fi
LastText
echo -en "\r${Clear}${LastText}" >&2
;;
# Lors de la validation via la touche entrée
""|$'\012')
# Suppression du - final si c'est le cas (validation du genre 8-)
ReponseTemp=${ReponseTemp/%-}
# Ajout ou non de la variable temporaire
AnswerAdd "${ReponseTemp}" "${Reponses[*]}" "${!Choix[*]}" && { Reponses+=(${ReponseTemp}); unset ReponseTemp; }
# Vérifie le nombre de réponse
if [[ ${Min} -gt 0 ]]
then
# Compte le nombre de réponse
AnswerNumber="$(AnswerGet "${Reponses[*]}" "${!Choix[*]}" | wc -w)"
# Si le nombre de réponse est inférieure au min
if [[ ${Min} -gt 0 && ${Min} -gt ${AnswerNumber} ]]
then
LastText
[[ ${Debug} ]] && echo -en "\r${Clear}${Effects["Errors"]}$(LangText "error_min")${Effects["Unset"]} ${LastText}" >&2 || echo -en "\r${Clear}${LastText} " >&2
continue
fi
fi
# Texte final
echo -en "\r${Clear}${Effects["Texts"]}${TexteBase}${Effects["Numbers"]}${Reponses[@]}${Effects["Unset"]}" >&2
# S'il n'y a eu aucune réponse, renvoie le texte par défaut et stop ici
[[ -z ${Reponses[@]} ]] && ExitErreur
# Arret de la boucle
break
;;
# Lors de l'utilisation de la touche retour arrière
$'\177')
### Récupération de la valeur à traiter
# S'il y a un nombre en cours
if [[ ${#ReponseTemp} -gt 0 ]];
then
[[ ${ReponseTemp: -1} != "-" ]] && ReponseTemp="${ReponseTemp::-1}"
# Si la liste n'est pas vide
elif [[ ${Reponses[@]} ]]
then
ReponseTemp="${Reponses[-1]}"
unset Reponses[-1]
# Sinon c'est un texte vide
else
unset Reponses ReponseTemp
fi
### Traitement de la valeur
# Remise en place du texte de base si c'etait *
if [[ ${ReponseTemp} == "*" ]]
then
unset Reponses ReponseTemp
# Suppression du ?
elif [[ ${ReponseTemp} == "?" ]]
then
unset ReponseTemp
# Pour les nombres
elif [[ ${ReponseTemp} =~ ^[0-9]+$ ]]
then
# Si le nombre peut servir de base on le conserve
if [[ ${#ReponseTemp} -eq 1 ]] && NumberDigit ${ReponseTemp} "${!Choix[*]}" "${Reponses[*]}"
then
ReponseTemp="${ReponseTemp}"
# Si le nombre - 1 chiffre peut servir de base on le conserve
elif [[ ${#ReponseTemp} -eq 2 ]] && NumberDigit ${ReponseTemp:0:-1} "${!Choix[*]}" "${Reponses[*]}"
then
ReponseTemp=${ReponseTemp:0:-1}
# Si le nombre - 2 chiffres peut servir de base on le conserve
elif [[ ${#ReponseTemp} -eq 3 ]] && NumberDigit ${ReponseTemp:0:-2} "${!Choix[*]}" "${Reponses[*]}"
then
ReponseTemp=${ReponseTemp:0:-2}
else
unset ReponseTemp
fi
# Pour les plages
elif [[ ${ReponseTemp} =~ "-" ]]
then
MaxValue=${ReponseTemp#*-}
# Si le nombre max peut servir de base on le conserve
if [[ ${#MaxValue} -eq 1 ]] && NumberDigit ${MaxValue} "${!Choix[*]}" "${Reponses[*]}"
then
ReponseTemp="${ReponseTemp}"
# Si le nombre max - 1 chiffre peut servir de base on le conserve
elif [[ ${#MaxValue} -eq 2 ]] && NumberDigit ${MaxValue:0:-1} "${!Choix[*]}" "${Reponses[*]}"
then
ReponseTemp="${ReponseTemp%-*}-${MaxValue:0:-1}"
# Si le nombre max - 2 chiffres peut servir de base on le conserve
elif [[ ${#MaxValue} -eq 3 ]] && NumberDigit ${MaxValue:0:-2} "${!Choix[*]}" "${Reponses[*]}"
then
ReponseTemp="${ReponseTemp%-*}-${MaxValue:0:-2}"
# Si l'element de test est -
elif [[ ${ReponseTemp: -1} == "-" ]]
then
# Si le nombre peut servir de base ou non
NumberDigit ${ReponseTemp%-*} "${!Choix[*]}" "${Reponses[*]}" && ReponseTemp=${ReponseTemp%-*} || { Reponses+=(${ReponseTemp%-*}); unset ReponseTemp; }
# Si le nombre max de ne pas servir de base, on le supprime mais on laisse ${min}-
else
ReponseTemp="${ReponseTemp%-*}-"
fi
fi
# nouveau texte
LastText
echo -en "\r${Clear}${LastText}" >&2
;;
# Lettre de l'exit
${ExitLetter})
# Réinitialisation du texte et arrêt de la boucle
echo -en "\r${Clear}${Effects["Texts"]}${TexteBase}${Effects["Errors"]}$(LangText info_exit_on)${Effects["Unset"]}" >&2
ExitErreur
;;
# Touches spéciales (debut, fin, page up ou down, Fx, fleches...)
$'\033')
# Permet de savoir s'il y a un autre caractère qui suit, si ce n'est pas le cas, c'est qu'on a utilisé echap
read -t 0
# Réinitialisation du texte et arrêt de la boucle si la touche echap a été utilisée
if [[ ${?} -eq 1 ]]
then
unset Reponses ReponseTemp
LastText
echo -en "\r${Clear}${LastText}" >&2
ExitErreur
else
[[ ${Debug} ]] && printf "\r${Clear}${Effects["Errors"]}$(LangText "error_key")${Effects["Unset"]} ${LastText}" "special" >&2
fi
# Permet de décharger les autres caractères qui suivent en cas de touches spéciales
while true
do
read -r -s -n 1
read -t 0
[[ ${?} -eq 1 ]] && break
done
;;
*)
[[ ${Debug} ]] && printf "\r${Clear}${Effects["Errors"]}$(LangText "error_key")${Effects["Unset"]} ${LastText}" "${Touche}" >&2
;;
esac
done
# Saut de ligne esthétique
echo >&2
#########################
## Renvoie des valeurs ##
#########################
### Traite chaque numéro retourné par la fonction AnswerGet
for Number in $(AnswerGet "${Reponses[*]}" "${!Choix[*]}")
do
# Si c'est vide, on saute
[[ -z ${Number} ]] && continue
# Remplissage du tableau
FormatReader "${Choix[${Number}]}" "OutputText" "${Number}"
# Envoie du texte
echo "${Item["Line"]}"
done
### Débloque l’expansion de ? et de *
set +f
### Arrêt normal
exit 0
Historique des versions précédentes :
Ajout de lang en sur les commandes d'exemples
Diminution du nombre minimal de proposition à 1 car on a alors le choix entre continuer et arrêter
Remplacement de --wait par --prompt
? peut être utilisé plusieurs fois et mélangé avec des nombres
? et * ainsi que - sont utilisables par défaut
Ajout des arguments --no --no-all --no-range --no-random pour les désactiver
Les arguments --all, --random et --range ne servent qu'à afficher une explication
Remplacement de --numbers et --only-numbers par --output qui permet beaucoup plus de choses
Remplacement de --display par --input qui permet plus de choses
Amélioration d'une grande partie du code
Suppression de --upper et --lower au profit de --range (par défaut) qui permet plus de choses
Modification du --colors et suppression de --no-colors
Création d'un système d'exemple plus poussés
Plus de limite dans le nombre de proposition
Mise à jour de la vidéo de présentation
Corrections de bug
Remplacement de --uniq par --no-uniq
Mise en place de l'argument --lower pour permettre la sélection inférieure à un nombre : <Nombre
Mise en place de l'argument --upper pour permettre la sélection supérieure à un nombre : >Nombre
Ces 2 arguments sont incompatibles avec --limit
Fusion des arguments --color-* en --colors
Ajout d'un argument --debug pour voir les erreurs de touches
Ajout d'un argument --unique-proposal pour éviter les propositions doublons
Changement de nom en hizoselect (le deb créé de sliens pour HizoSelect et multiselect)
Refonte du read.
Le read fonctionne jusqu'à 999 propositions (normalement smile ).
Le read empêche les doubles espaces.
Le read prévient lorsque la limite de réponse est atteinte.
Le read bloque les touches spéciales (style page up et page down, les Fx, suppr, les flèches...).
Ajout de l'argument --uniq pour empêcher les doublons dans les réponses (mêmes numéros).
Ajout de l'argument --random permettant d'utiliser ? pour renvoyer une valeur aléatoire.
Ajout de l'argument --columns pour afficher les réponses en colonnes.
Remplacement de --error par --exit
Remplacement de --secret et --commentary par --separtor, l'ordre est toujours important : Text@@Com@
@Secret
Beaucoup de changements...
Mise à jour des manpages et du texte d'aide
Remplacement de --all et --all-text par --all[=text]
Ajout de la possibilité d'utiliser des arguments courts
Modification complète du système de traitement des arguments
Modification du système de texte
Modification du système de couleurs et ajout des arguments des couleurs (--color-numbers --color-values --color-commentary --color-error)
Ajout de --default pour pré-rentrer des réponses
Ajout de --all pour ajouter une ligne pour toutes les sélectionner
Ajout de --all-text pour modifier le texte de la réponse *
Modification de nombreux noms de variables