Analizando opciones de comando en Lua
Mi forma favorita de resolver el problema del análisis en Lua es alt-getopt.
Cuando ingresas un comando en tu terminal, generalmente hay opciones, también llamadas interruptores o banderas, que puedes usar para modificar la forma en que se ejecuta el comando. Esta es una convención útil definida por la especificación POSIX, por lo que, como programador, es útil saber cómo detectar y analizar opciones.
Como ocurre con la mayoría de los lenguajes, hay varias formas de resolver el problema de las opciones de análisis en Lua. Mi favorito es alt-getopt.
Instalación
La forma más sencilla de obtener y utilizar alt-getopt en su código es instalarlo con LuaRocks. Para la mayoría de los casos de uso, probablemente quieras instalarlo en el directorio de tu proyecto local:
$ mkdir local
$ luarocks --tree=local install alt-getopt
Installing https://luarocks.org/alt-getopt-0.X.Y-1.src.rock
[...]
alt-getopt 0.X.Y-1 is now installed in /tux/myproject/local (license: MIT/X11)
Alternativamente, puedes descargar el código desde GitHub.
Agregar una biblioteca a su código Lua
Suponiendo que haya instalado la biblioteca localmente, puede definir la ruta de su paquete Lua y luego require
el paquete alt-getopt:
package.path = package.path .. ';local/share/lua/5.1/?.lua'
local alt_getopt = require("alt_getopt")
Si lo ha instalado en una ubicación conocida del sistema, puede omitir la línea package.path
(porque Lua ya sabe buscar bibliotecas en todo el sistema).
Ahora estás listo para analizar opciones en Lua.
Análisis de opciones en Lua
Lo primero que debe hacer para analizar las opciones es definir las opciones válidas que su aplicación puede aceptar. La biblioteca alt_getopt ve todas las opciones principalmente como opciones cortas, lo que significa que usted define las opciones como letras individuales. Puede agregar versiones largas más adelante.
Cuando defines opciones válidas, creas una lista delimitada por dos puntos (:
), que es interpretada por la función get_opts
proporcionada por alt-getopts .
Primero, cree algunas variables para representar las opciones. Las variables short_opt
y optarg
representan la opción corta y el argumento de la opción. Estos son nombres de variables arbitrarios, por lo que puedes llamarlos como quieras (siempre que sea un nombre válido para una variable).
La tabla long_opts
debe existir, pero me resulta más fácil definir los valores de las opciones largas después de haber decidido las opciones cortas, así que déjala vacía por ahora.
local long_opts = {}
local short_opt
local optarg
Con esas variables declaradas, puede iterar sobre los argumentos proporcionados por el usuario, verificando si algún argumento coincide con su lista aprobada de opciones cortas válidas.
Si se encuentra una opción válida, utiliza la función pairs
en Lua para extraer el valor de la opción.
Para crear una opción que no acepte ningún argumento propio pero que esté activada o desactivada (a menudo denominada interruptor), coloque la opción corta desea definir a la derecha de un carácter de dos puntos (:
).
En este ejemplo, he creado un bucle para comprobar la opción corta -a
, que es un modificador:
short_opt,optarg = alt_getopt.get_opts (arg, ":a", long_opts)
local optvalues = {}
for k,v in pairs (short_opt) do
table.insert (optvalues, "value of " .. k .. " is " .. v .. "\n")
end
table.sort (optvalues)
io.write (table.concat (optvalues))
for i = optarg,#arg do
io.write (string.format ("ARGV [%s] = %s\n", i, arg [i]))
end
Al final de este código de muestra, incluí un bucle for para iterar sobre los argumentos restantes en el comando porque cualquier cosa que no se detecte como una opción válida debe ser un argumento (probablemente un nombre de archivo, URI o lo que sea que su aplicación opera).
Pruebe el código:
$ lua test.lua -a
value of a is 1
El script de prueba detectó con éxito la opción -a
y le asignó un valor de 1 para representar que existe.
Inténtalo de nuevo con un argumento extra:
$ lua test.lua -a hello
value of a is 1
ARGV [2] = hello
Opciones con argumentos
Algunas opciones requieren un argumento propio. Por ejemplo, es posible que desee permitir que el usuario apunte su aplicación a un archivo de configuración personalizado, establezca un atributo en un color o establezca la resolución de un gráfico. En alt_getopt, las opciones que aceptan argumentos se colocan a la izquierda de los dos puntos (:
) en la lista corta de opciones.
short_opt,optarg = alt_getopt.get_opts (arg, "c:a", long_opts)
Pruebe el código:
$ lua test.lua -a -c my.config
value of a is 1
value of c is my.config
Inténtalo de nuevo, esta vez con un argumento extra:
$ lua test.lua -a -c my.config hello
value of a is 1
value of c is my.config
ARGV [4] = hello
Opciones largas
Las opciones cortas son excelentes para los usuarios avanzados, pero no suelen ser muy memorables. Puede crear una tabla de opciones largas que apunten a opciones cortas para que los usuarios puedan aprender las opciones largas antes de abreviar sus comandos con opciones de una sola letra.
local long_opts = {
alpha = "a",
config = "c"
}
Los usuarios ahora pueden elegir entre opciones largas y cortas:
$ lua test.lua --config my.config --alpha hello
value of a is 1
value of c is my.config
ARGV [4] = hello
Análisis de opciones
Aquí está el código de demostración completo para su referencia:
#!/usr/bin/env lua
package.path = package.path .. ';local/share/lua/5.1/?.lua'
local alt_getopt = require("alt_getopt")
local long_opts = {
alpha = "a",
config = "c"
}
local short_opt
local optarg
short_opt,optarg = alt_getopt.get_opts (arg, "c:a", long_opts)
local optvalues = {}
for k,v in pairs (short_opt) do
table.insert (optvalues, "value of " .. k .. " is " .. v .. "\n")
end
table.sort (optvalues)
io.write (table.concat (optvalues))
for i = optarg,#arg do
io.write (string.format ("ARGV [%s] = %s\n", i, arg [i]))
end
Hay más ejemplos en el repositorio Git del proyecto. Incluir opciones para sus usuarios es una característica importante para cualquier aplicación y Lua lo hace fácil. Hay otras bibliotecas además de alt_getopt, pero ésta me parece fácil y rápida de usar.