196 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
			
		
		
	
	
			196 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
| ##@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
 | |
|         set_var_cmd udir "$(dirname "$udirf")"
 | |
|         set_var_cmd 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] = $(quoted_awk "$name")"
 | |
|         if [ "$name" != "$param" ]; then
 | |
|             value="${param#*=}"
 | |
|             script="$script
 | |
|   values[$i] = $(quoted_awk "$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"
 | |
| }
 | 
