##@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"
}
