##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 ## Fonction de support pour udir: gestion des paramètres des répertoires ##@cooked nocomments ##@require base uprovide udir urequire base UDIR_TEMPLATE="\ # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 # Utiliser 'udir --help-vars' pour une description de la signification des # variables suivantes: udir_desc=\"\" udir_note=\"\" udir_types=()" function udir_check() { # Vérifier si le fichier $1 existe # Si $1 est un répertoire, prendre $1/.udir local udirf="$1" [ -d "$udirf" ] && udirf="$udirf/.udir" [ -f "$udirf" ] } function udir_create_maybe() { # Si le fichier $1 n'existe pas, le créer comme un template .udir # Si $1 est un répertoire, prendre $1/.udir local udirf="$1" [ -d "$udirf" ] && udirf="$udirf/.udir" [ -f "$udirf" ] || echo "$UDIR_TEMPLATE" >"$udirf" } function udir_dump() { # Dumper toutes les variables définies pour le fichier $1 # Si $1 est un répertoire, prendre $1/.udir local udirf="$(abspath "${1:-.}")" [ -d "$udirf" ] && udirf="$udirf/.udir" if [ -f "$udirf" ]; then echo_setv udir "$(dirname "$udirf")" echo_setv udirf "$udirf" <"$udirf" filter_comment -m fi } function udir_eval() { # Evaluer la commande "$2..$*" dans le contexte des variables définies pour # le répertoire $1. La commande est évaluée dans un sous-shell pour ne pas # polluer l'espace de noms courant. # note: on évalue les commandes dans un sous-shell au lieu d'utiliser des # variables locales, parce que bash 2.xx a un bug avec l'évaluation de la # définition de tableaux locaux. i.e. # eval "local array=(value)" # a pour résultat "$array" == "(value)", ce qui est incorrect. local udirf="$1"; shift (eval "$(udir_dump "$udirf")"; [ -n "$*" ] && eval "$@") } function udir_dump_all() { # Dumper toutes les variables définies pour le répertoire $1 et *tous ses # parents* jusqu'à la racine local -a udirs local udir="$1" [ -f "$udir" ] && udir="$(dirname "$udir")" parentdirs udirs "$udir" reverse for udir in "${udirs[@]}"; do udir_dump "$udir/.udir" done } function udir_eval_all() { # Evaluer la commande "$2..$*" dans le contexte des variables définies pour # le répertoire $1 et *tous ses parents* jusqu'à la racine local udirf="$1"; shift (eval "$(udir_dump_all "$udirf")"; [ -n "$*" ] && eval "$@") } function udir_parse() { # Dans le fichier $1, lire les noms des variables # Si $1 est un répertoire, prendre $1/.udir # Les noms des variables sont placés dans le tableau $2(=UDIR_VARS), et les noms # des tableaux sont placés dans le tableau $3(=UDIR_ARRAYS) # note: les regex qui sont entre "" au lieu de // le sont à cause d'un bug # de awk sous macosx local __up_udir="$1" [ -d "$__up_udir" ] && __up_udir="$__up_udir/.udir" local __up_vars="${2:-UDIR_VARS}" local __up_arrays="${3:-UDIR_ARRAYS}" eval "$(<"$__up_udir" filter_comment -m | awk 'BEGIN { vars = "'"$__up_vars"'=("; first_var = 1; arrays = "'"$__up_arrays"'=("; first_array = 1; } /^[ \t]*#/ { next } $0 ~ /^[ \t]*[a-zA-Z_][a-zA-Z0-9_]*=\(/ { match($0, /^[ \t]*[a-zA-Z_][a-zA-Z0-9_]*=\(/) name = substr($0, RSTART, RLENGTH) sub(/^([ \t]*)?/, "", name) sub("=\\($", "", name) if (first_array) first_array = 0 else arrays = arrays " " arrays = arrays name next } $0 ~ /^[ \t]*[a-zA-Z_][a-zA-Z0-9_]*=/ { match($0, /^[ \t]*[a-zA-Z_][a-zA-Z0-9_]*=/) name = substr($0, RSTART, RLENGTH) sub(/^([ \t]*)?/, "", name) sub("=$", "", name) if (first_var) first_var = 0 else vars = vars " " vars = vars name next } END { print vars ")" print arrays ")" }')" } function udir_update() { # Dans le fichier $1, mettre à jour les variables $2..* # Si $1 est un répertoire, prendre $1/.udir # Chaque argument de cette fonction est de la forme name[=value] # Si value n'est pas précisée, la variable obtient une valeur nulle # (i.e. var=) # Si la variable ne figure pas dans le fichier, elle est rajoutée à la fin # du fichier. # Cette fonction nécessite gawk. local udir="$1"; shift [ -d "$udir" ] && udir="$udir/.udir" udir_create_maybe "$udir" local mode="$(fix_mode "$udir")" local script i param name value script="BEGIN { in_section=0 max = $#" i=0 for param in "$@"; do name="${param%%=*}" script="$script names[$i] = $(qawk "$name")" if [ "$name" != "$param" ]; then value="${param#*=}" script="$script values[$i] = $(qawk "$value")" else script="$script values[$i] = \"\"" fi script="$script seen[$i] = 0" let i=$i+1 done script="$script"' } function write_unseen() { for (i = 0; i < max; i++) { if (!seen[i]) { print names[i] "=" values[i] seen[i] = 1 } } } ' i=0 for param in "$@"; do name="${param%%=*}" script="$script \$0 ~ /^[ $TAB]*(##*[ $TAB]*)?$name[ $TAB]*=/ { \$0 = gensub(/^([ $TAB]*##*)?([ $TAB]*$name[ $TAB]*=[ $TAB]*).*\$/, \"\\\\2\" values[$i], \"\") seen[$i] = 1 }" let i=$i+1 done script="$script { print } END { write_unseen() }" ac_set_tmpfile tmpfile <"$udir" >"$tmpfile" awk "$script" && cat "$tmpfile" >"$udir" unfix_mode "$udir" "$mode" ac_clean "$tmpfile" } function udir_edit() { local udirf="$1" [ -d "$udirf" ] && udirf="$udirf/.udir" udir_create_maybe "$udirf" "${EDITOR:-vi}" +1 "$udirf" }