Je viens de mettre en place une belle structure de données et une chaîne de traitement pour générer ce comportement de commutation, aucune bibliothèque nécessaire. Je suis sûr qu'il aura été mis en œuvre de nombreuses fois, et je suis tombé sur ce fil à la recherche d'exemples - pensais que j'y participerais.
Je n'avais même pas particulièrement besoin d'indicateurs (le seul indicateur ici est un mode de débogage, créant une variable que je vérifie comme condition de démarrage d'une fonction en aval if (!exists(debug.mode)) {...} else {print(variables)})
. Les lapply
instructions de vérification d'indicateur ci-dessous produisent la même chose que:
if ("--debug" %in% args) debug.mode <- T
if ("-h" %in% args || "--help" %in% args)
où args
est la variable lue dans les arguments de la ligne de commande (un vecteur de caractères, équivalent à c('--debug','--help')
lorsque vous les fournissez par exemple)
Il est réutilisable pour tout autre indicateur et vous évitez toutes les répétitions, et pas de bibliothèques donc pas de dépendances:
args <- commandArgs(TRUE)
flag.details <- list(
"debug" = list(
def = "Print variables rather than executing function XYZ...",
flag = "--debug",
output = "debug.mode <- T"),
"help" = list(
def = "Display flag definitions",
flag = c("-h","--help"),
output = "cat(help.prompt)") )
flag.conditions <- lapply(flag.details, function(x) {
paste0(paste0('"',x$flag,'"'), sep = " %in% args", collapse = " || ")
})
flag.truth.table <- unlist(lapply(flag.conditions, function(x) {
if (eval(parse(text = x))) {
return(T)
} else return(F)
}))
help.prompts <- lapply(names(flag.truth.table), function(x){
# joins 2-space-separatated flags with a tab-space to the flag description
paste0(c(paste0(flag.details[x][[1]][['flag']], collapse=" "),
flag.details[x][[1]][['def']]), collapse="\t")
} )
help.prompt <- paste(c(unlist(help.prompts),''),collapse="\n\n")
# The following lines handle the flags, running the corresponding 'output' entry in flag.details for any supplied
flag.output <- unlist(lapply(names(flag.truth.table), function(x){
if (flag.truth.table[x]) return(flag.details[x][[1]][['output']])
}))
eval(parse(text = flag.output))
Notez flag.details
qu'ici, les commandes sont stockées sous forme de chaînes, puis évaluées avec eval(parse(text = '...'))
. Optparse est évidemment souhaitable pour tout script sérieux, mais le code à fonctionnalité minimale est parfois bon aussi.
Exemple de sortie:
$ Rscript check_mail.Rscript --help
--debug Affiche les variables plutôt que d'exécuter la fonction XYZ ...
-h --help Afficher les définitions d'indicateur