ufile: support des inclusions, d'un fichier de configuration alternatif

This commit is contained in:
Jephté Clain 2017-04-22 09:49:25 +04:00
parent d535df3629
commit c82c90840e
2 changed files with 116 additions and 40 deletions

View File

@ -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=()

139
ufile
View File

@ -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] <files...>
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
eval "[[ \"\$filename\" == $(qwc "$pattern") ]]" || continue
destname="$filename"
if [ -n "$renamef" ]; then
newname=
dest=
"$renamef" "$filename" "$pf" "$destdir" || continue
if [ -z "$newname" ]; then
destname="$filename"
elif [[ "$newname" == */* ]]; then
splitpath "$newname" destdir destname
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"