From c82c90840e8b88e185b85ba017e0cca911a4f9af Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Sat, 22 Apr 2017 09:49:25 +0400 Subject: [PATCH] ufile: support des inclusions, d'un fichier de configuration alternatif --- lib/default/ufile | 13 ++--- ufile | 143 +++++++++++++++++++++++++++++++++++----------- 2 files changed, 116 insertions(+), 40 deletions(-) diff --git a/lib/default/ufile b/lib/default/ufile index 7070f3e..cb065f1 100644 --- a/lib/default/ufile +++ b/lib/default/ufile @@ -1,12 +1,9 @@ # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 -# règles pour le classement des fichiers. chaque règle est de la forme +# Fichiers externes à inclure. Chacun de ces fichiers peut contenir des +# définitions de fonctions et de la variables RULES +INCLUDES=() + +# Règles pour le classement des fichiers. Chaque règle est de la forme # pattern:destdir[:renamef] -# renamef est une fonction qui permet de supporter le renommage d'un fichier -# lors de son classement. Sa signature est 'renamef filename pf destdir' où -# filename est le nom du fichier source, pf son chemin complet et destdir la -# valeur de destdir mentionnée dans la règle. La fonction doit définir la -# variable newname qui est le nouveau nom. Si le nouveau nom contient un chemin, -# destdir est ignoré et le fichier est déplacé dans le répertoire spécifié. Si -# la fonction retourne un code d'erreur autre que zéro, la règle est ignorée. RULES=() diff --git a/ufile b/ufile index 8b2f731..bd259c4 100755 --- a/ufile +++ b/ufile @@ -2,28 +2,53 @@ # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 source "$(dirname "$0")/lib/ulib/ulib" || exit 1 urequire DEFAULTS -set_defaults ufile function display_help() { uecho "$scriptname: classer des fichiers selon certains règles -Les règles sont dans le fichier ~/etc/default/ufile -Consulter ce fichier pour les détails +Les règles sont spécifiées dans le fichier ~/etc/default/ufile + +Dans ce fichier, le tableau RULES contient des règles qui sont chacune de la +forme pattern:destdir[:renamef] + +- pattern est au format glob et identifie les fichiers auxquels s'applique la + règle +- destdir est le répertoire de destination dans lequel classer le fichier +- renamef est une fonction qui permet de supporter le renommage d'un fichier + lors de son classement. Sa signature est 'renamef filename pf destdir' où + filename est le nom du fichier source, pf son chemin complet et destdir la + valeur de destdir mentionnée dans la règle. + La fonction doit définir la variable dest qui est le nouveau nom. Si la + fonction retourne un code d'erreur autre que zéro, la règle est ignorée. + Si le nouveau nom contient un chemin, destdir est ignoré et le fichier est + déplacé dans le répertoire spécifié. USAGE $scriptname [options] OPTIONS + -c, --config CONFIG + Utiliser le fichier de configuration spécifié au lieu de la valeur par + défaut ~/etc/default/ufile -n, --fake Afficher les opérations qui seraient faites -l, --list Lister les règles définies -e, --edit - Lancer un éditeur pour mettre à jour les règles" + Lancer un éditeur sur le fichier de configuration" +} + +function joinp() { + # afficher le chemin $1/$2 + local pf="$1" + [ -n "$2" -a "${pf%/}" == "$pf" ] && pf="$pf/" + pf="$pf${2#/}" + echo "$pf" } args=(% --help '$exit_with display_help' + -c:,--config: config= -n,--fake fake=1 -l,--list action=list -e,--edit action=edit @@ -33,21 +58,54 @@ parse_args "$@"; set -- "${args[@]}" [ -n "$action" ] || action=file +## charger toutes les règles + +RULES=() +INCLUDES=() +if [ -n "$config" ]; then + if [ "$action" != edit ]; then + # le fichier doit exister, sauf en mode édition où il sera créé s'il + # n'existe pas déjà + [ -f "$config" ] || die "$config: fichier introuvable" + fi + if [ -f "$config" ]; then + source "$config" || die "$config: erreur lors de la lecture du fichier" + fi +else + set_defaults ufile +fi +array_copy rules RULES +for include in "${INCLUDES[@]}"; do + if [ -f "$include" ]; then + RULES=() + source "$include" + array_extend rules RULES + else + ewarn "$include: fichier introuvable" + fi +done +array_copy RULES rules + +## actions particulières + if [ "$action" == list ]; then + echo "# $(echo_seta2 INCLUDES)" array_to_lines RULES exit 0 elif [ "$action" == edit ]; then - setx ufile=get_user_defaults_file ufile - if [ ! -f "$ufile" ]; then - einfo "Le fichier $(ppath "$ufile") n'existe pas. Il sera créé avec un contenu par défaut" - mkdirof "$ufile" || die - cp "$scriptdir/lib/defaults/ufile" "$ufile" + [ -n "$config" ] || setx config=get_user_defaults_file ufile + if [ ! -f "$config" ]; then + einfo "Le fichier $(ppath "$config") n'existe pas. Il sera créé avec un contenu par défaut" + mkdirof "$config" || die + cp "$scriptdir/lib/default/ufile" "$config" fi - "${EDITOR:-vi}" "$ufile" + "${EDITOR:-vi}" "$config" exit $? +else + die "bug: $action: action non implémentée" fi -[ "$action" == file ] || die "bug: $action: action non implémentée" +## classement des fichiers if [ -n "$fake" ]; then function docmd() { qvals "$@"; } @@ -56,16 +114,29 @@ else fi [ $# -gt 0 ] || die "Vous devez spécifier des fichiers à classer" -[ ${#RULES[*]} -gt 0 ] || die "Vous devez spécifier des règles pour le classement des fichiers dans ~/default/ufile" +[ ${#RULES[*]} -gt 0 ] || die "Vous devez spécifier des règles pour le classement des fichiers dans ~/etc/default/ufile" +# vérifier les règles +for rule in "${RULES[@]}"; do + splitpair "$rule" pattern r2 + splitpair "$r2" destdir r3 + splitpair "$r3" renamef r4 + if [ -z "$destdir" -o "${destdir#"~/"}" != "$destdir" ]; then + : + elif [ "${destdir#/}" == "$destdir" ]; then + ewarn "$rule: règle potentiellement problématique: destdir devrait être absolu" + fi +done + +# faire le classement effectif for file in "$@"; do [ -f "$file" -o -n "$fake" ] || { eerror "$file: fichier introuvable. il sera ignoré" continue } setx pf=abspath "$file" - setx dir=dirname "$pf" - setx filename=basename "$pf" + setx dir=dirname -- "$pf" + setx filename=basename -- "$pf" found= for rule in "${RULES[@]}"; do splitpair "$rule" pattern r2 @@ -73,30 +144,38 @@ for file in "$@"; do splitpair "$r3" renamef r4 if [ "${destdir#"~/"}" != "$destdir" ]; then destdir="$HOME/${destdir#"~/"}" - elif [ "${destdir#/}" == "$destdir" ]; then - die "règle '$rule' invalide: destdir doit être absolu" fi - if eval "[[ \"\$filename\" == $(qwc "$pattern") ]]"; then - if [ -n "$renamef" ]; then - newname= - "$renamef" "$filename" "$pf" "$destdir" || continue - if [ -z "$newname" ]; then - destname="$filename" - elif [[ "$newname" == */* ]]; then - splitpath "$newname" destdir destname + + eval "[[ \"\$filename\" == $(qwc "$pattern") ]]" || continue + + destname="$filename" + if [ -n "$renamef" ]; then + dest= + "$renamef" "$filename" "$pf" "$destdir" || continue + if [ -n "$dest" ]; then + if [[ "$dest" == */* ]]; then + setx dest=abspath "$dest" + setx destdir=dirname -- "$dest" + setx destname=dirname -- "$dest" else - destname="$newname" + destname="$dest" fi - else - destname="$filename" fi - estep "$filename --> $destdir/$destname" - ask_yesno -i "Voulez-vous continuer?" O || { found=x; break; } - docmd mkdir -p "$destdir" || die "$destdir: impossible de créer le répertoire" - docmd mv -i "$file" "$destdir/$destname" || die "problème lors du déplacement du fichier" - found=1 + fi + + if [ -z "$destdir" ]; then + eerror "$rule: règle invalide: destdir est vide" break fi + + setx dest=joinp "$destdir" "$destname" + estep "$filename --> $dest" + ask_yesno -i "Voulez-vous continuer?" O || { found=x; break; } + + docmd mkdir -p "$destdir" || die "$destdir: impossible de créer le répertoire" + docmd mv -i "$file" "$dest" || die "problème lors du déplacement du fichier" + found=1 + break done if [ -z "$found" ]; then ewarn "$file: aucune correspondance n'a été trouvée"