Parsing command options in Lua

My favorite way to solve the problem of parsing in Lua is alt-getopt.
33 readers like this.
Woman sitting in front of her laptop

kris krüg

When you enter a command into your terminal, there are usually options, also called switches or flags, that you can use to modify how the command runs. This is a useful convention defined by the POSIX specification, so as a programmer, it's helpful to know how to detect and parse options.

As with most languages, there are several ways to solve the problem of parsing options in Lua. My favorite is alt-getopt.

Installing

The easiest way to obtain and use alt-getopt in your code is to install it with LuaRocks. For most use-cases, you probably want to install it into your local project directory:

$ 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)

Alternately, you can download the code from GitHub.

Adding a library to your Lua code

Assuming you've installed the library locally, then you can define your Lua package path and then require the alt-getopt package:

package.path = package.path .. ';local/share/lua/5.1/?.lua'

local alt_getopt = require("alt_getopt")

If you've installed it to a known system location, you can omit the package.path line (because Lua already knows to look for system-wide libraries.)

Now you're set to parse options in Lua.

Option parsing in Lua

The first thing you must do to parse options is to define the valid options your application can accept. The alt_getopt library sees all options primarily as short options, meaning that you define options as single letters. You can add long versions later.

When you define valid options, you create a list delimited by colons (:), which is interpreted by the get_opts function provided by alt-getopts.

First, create some variables to represent the options. The variables short_opt and optarg represent the short option and the option argument. These are arbitrary variable names, so you can call them anything (as long as it's a valid name for a variable).

The table long_opts must exist, but I find it easiest to define the values of the long options after you've decided on the short options, so leave it empty for now.

local long_opts = {}

local short_opt
local optarg

With those variables declared, you can iterate over the arguments provided by the user, checking to see whether any argument matches your approved list of valid short options.

If a valid option is found, you use the pairs function in Lua to extract the value of the option.

To create an option that accepts no argument of its own but is either on or off (often called a switch), you place the short option you want to define to the right of a colon (:) character.

In this example, I've created a loop to check for the short option -a, which is a switch:

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

At the end of this sample code, I included a for-loop to iterate over any remaining arguments in the command because anything not detected as a valid option must be an argument (probably a file name, URI, or whatever it is that your application operates upon).

Test the code:

$ lua test.lua -a 
value of a is 1

The test script has successfully detected the option -a, and has assigned it a value of 1 to represent that it does exist.

Try it again with an extra argument:

$ lua test.lua -a hello
value of a is 1
ARGV [2] = hello

Options with arguments

Some options require an argument all their own. For instance, you might want to allow the user to point your application to a custom configuration file, set an attribute to a color, or set the resolution of a graphic. In alt_getopt, options that accept arguments are placed on the left of the colon (:) in the short options list.

short_opt,optarg = alt_getopt.get_opts (arg, "c:a", long_opts)

Test the code:

$ lua test.lua -a -c my.config
value of a is 1
value of c is my.config

Try it again, this time with a spare argument:

$ lua test.lua -a -c my.config hello
value of a is 1
value of c is my.config
ARGV [4] = hello

Long options

Short options are great for power users, but they don't tend to be very memorable. You can create a table of long options that point to short options so users can learn long options before abbreviating their commands with single-letter options.

local long_opts = {
   alpha = "a",
   config = "c"
}

Users now have the choice between long and short options:

$ lua test.lua --config my.config --alpha hello
value of a is 1
value of c is my.config
ARGV [4] = hello

Option parsing

Here's the full demonstration code for your reference:

#!/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

There are further examples in the project's Git repository. Including options for your users is an important feature for any application, and Lua makes it easy to do. There are other libraries aside from alt_getopt, but I find this one easy and quick to use.

What to read next
Seth Kenlon
Seth Kenlon is a UNIX geek, free culture advocate, independent multimedia artist, and D&D nerd. He has worked in the film and computing industry, often at the same time.

1 Comment

Great! I love Lua!

Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.