ouech l'ariketa

afin de faciliter mes présentations sur bash, je bricolais dans les raccourcis clavier et sur les fonctions et tout s'améliorait un peu chaque fois. après chaque présentation, il y aurait éventuellement quelqu'un qui m'aurait démandait comment faire avancer les exemples comme je venais de faire dans ma présentaiton. j'ai enfin tout organisé, generalisé, et je l'ai publié ici: ariketa

la prémisse alors est de charger une tableau bash avec tout les exemples que tu comptes présenter, puis, en utilisant les raccourcis clavier, tu avances/récules dans les exemples, chaque fois étant libre de les éditer, de les éxecuter, de leur appliquer une coloration syntaxique, ou de les differ. les raccourcis clavier ont étés choisis en évitant d'écraser ceux qui éxistent par défaut, alors tous les bons trucs auxqels on s'attend de la commande bind -P, comme par exemple shell-expand-line [1] et edit-and-execute-command [2], eh ben ils vont continuer de bien fonctionner.

tableau de tuples improvisé en appuyant sur la dévellopement des paramètres

même si les structures de données emboîtées n'existent pas directement dans bash, y'a des approches variées qui peuvent servir pour en faire des fonctionalités approximitives dans des contextes prédéterminés. parmi les soucis que je commençais à avoir une fois que j'avais donné à plusieurs reprises ma présentation était celui ou j'oublierais combien d'exemples (de plus) qu'il y aurait à propos des informations sur une diapo ou une thème spécifique. ça se trouvait que j'avancerais trop pendant une demi-seconde - pas bien la fin du monde mais ça risque d'interrompre ton flow hein? pour combattre ce problème, j'ai préfixé chacun de mes exemples par un tag, éffectivement aproxximant une tableau de tuples. suivant se trouve un exemple que j'ai employé dans ma présentation récente à Linuxfest Northwest, taggé "while and until" pour indiquer la section pertinent dans mon diaporama:

_examples=(
    'while and until:
    count=0
    until (( ++count > 3 ))
    do
        echo $count
    done'
)

lorsque j'avais imposé une structure basée sur une simple délinéation de chaîne, je pouvais employer la développement des paramètres comme handler pour mes tuples. pour décomposer un exemple, il faudrait tout enlever du début de la chaîne jusqu'au délinéateur spécifié. j'ai choisi le deux-points suivi par une nouvelle ligne (:$'\n' [3]); ça se fait avec la développement suivante:

${var#*:$'\n'}

cette développement de paramètres nous laisse alors que le code de l'exemple (càd sas le tag). de manière parallèle on peut développer que le tag en enlevant tout les charactères depuis le fin de la chaîne jusqu'au délinéateur:

${var%%:$'\n'*}

vu que je ne voulais pas que tout brise au cas ou y'a un exemple qui soit pas taggé, et aussi pour la facilité de la réutilisation, j'en ai fait des fonctions pour décomposer les exemples et les tags. il est à noter que ce système souffre d'une fragilité importante - s'il y a des exemples non-taggés, ils seront pas traités correctement si jamais y'a la même chaîne de charactères qu'on ait choisit comme délinéateur dns l'exemple, dont le :\n dans ce cas. il existe bien des alternatifs que j'adopterai possiblement dans le future pour ariketa. pour le moment, la fonction qui décompose les exemples est simple, vu qu'on peut pas fiablement détecter les fausses positives (de manière simple), mais la fonction qui décompose les tags renvoie un état faux dans le cas ou y'avait rien qui ressemblait le délinéateur [4], comme on n'aurait pas envie de forcer tout un exemple dans la région du tag sur l'écran dans l'en-tête d'ariketa:

_example.unpack() {
    printf "%s" "${1#*:$'\n'}"
}

_tag.unpack() {
    local _tag="${1%%:$'\n'*}"
    (( ${#_tag} < ${#1} )) || return 1
    printf "%s" "$_tag"
}

sans compter les limitations actuelle de cette implémentation, tout ce qui restait était de bricoler des fonctions pour indiquer si les tags adjacents sont partagés avec celui de l'exemple actuel ou non, et pour tout rassembler de format concis, si y'a bien un tag avec l'exemple [5]:

_tag.same_as_next? () {
    [[ "$(_tag.unpack "${_examples[$_I]}")" \
    == "$(_tag.unpack "${_examples[$((_I+1))]}")" ]] \
        || return 1
    printf "%s" "${1:-+}"
}

_tag.same_as_prev? () {
    [[ "$(_tag.unpack "${_examples[$_I]}")" \
    == "$(_tag.unpack "${_examples[$((_I-1))]}")" ]] \
        || return 1
    printf "%s" "${1:-+}"
}

_tag.display () {
    local _tag=$(_tag.unpack "${_examples[$_I]}") \
        && printf "[$(_tag.same_as_prev?) %s $(_tag.same_as_next?)]" "${_tag}"
}

du coup on a un en-tête concis qui montre le tag actuel, avec des + à gauche et/ou à droite qui indiquerait la présence d'un exemple du même tag dans la direction respective:

> ## example 54 / 91  [+ while and until +]
[1]résoudre les éxpansions sur la ligne de commande actuelle sans éxecuter la ligne complète.
[2]lancer ton éditeur avec la ligne de commande actuelle comme contenu, puis l'éxecuter quand tu l'sauves et tu quittes l'éditeur.
[3]les guillemets $' agissent plutot comme les guillemets double ("..."), sauf que les séquences d'échappement introduites par des contre-obliques seront traités selon le standard ANSI-C (\n, par exemple). afin de nous permettre de faire cela dans une contexte intérieur à une développement de paramètres, e.g. "${var#*$'\n'}", il faudra que l'option shell extquote soit activée; heureusement qu'elle est activée par défaut.
[4]pour y vérifier, on regarde simplement s'il y a bien moins de charactères dans la chaîne produite par la développement qu'il y en avait avant; si bien le :$'\n'* ne se trouve pas dans la chaîne, toute la chaîne serait préservée telle quelle sans rien enlever au moment de la développement.
[5]des points en plus si tu vois l'amélioration simple auquel je pensais en écrivant quelques unes des fonctions _tag..

links

social