Acabo de armar una buena estructura de datos y una cadena de procesamiento para generar este comportamiento de conmutación, no se necesitan bibliotecas. Estoy seguro de que se habrá implementado varias veces, y encontré este hilo en busca de ejemplos, pensé que lo incluiría.
Ni siquiera necesitaba indicadores en particular (el único indicador aquí es un modo de depuración, creando una variable que verifico como condición para iniciar una función descendente if (!exists(debug.mode)) {...} else {print(variables)})
. Las lapply
siguientes declaraciones de comprobación de indicador producen lo mismo que:
if ("--debug" %in% args) debug.mode <- T
if ("-h" %in% args || "--help" %in% args)
donde args
está la variable leída de los argumentos de la línea de comandos (un vector de caracteres, equivalente ac('--debug','--help')
cuando los proporciona, por ejemplo)?
Es reutilizable para cualquier otro indicador y evita toda la repetición, y no hay bibliotecas, por lo que no hay dependencias:
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))
Tenga en cuenta que flag.details
aquí los comandos se almacenan como cadenas, luego se evalúan con eval(parse(text = '...'))
. Optparse es obviamente deseable para cualquier script serio, pero el código de funcionalidad mínima también es bueno a veces.
Salida de muestra:
$ Rscript check_mail.Rscript --help
--debug Imprime variables en lugar de ejecutar la función XYZ ...
-h --help Mostrar definiciones de banderas