Skip to content

Commit 9adb705

Browse files
o-limamireh
authored andcommitted
Add callbacks for options parsing
This allows the user to specify a function to be called whenever an option is parsed. Just pass a callback function to `cli:add_opt` and that function will be called when the parser successfully parses the option. Arguments to the callback function are: * The option key specified on the command-line * The value being assigned to the option * The alternate key for the option (i.e. expanded-key)
1 parent 0fef574 commit 9adb705

File tree

4 files changed

+123
-19
lines changed

4 files changed

+123
-19
lines changed

examples/00_general.lua

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ Try this file with the following commands lines;
99

1010
local cli = require "cliargs"
1111

12+
local function print_version(key, value, altkey)
13+
-- this is called when the flag -v or --version is set
14+
if key == 'version' then
15+
print("cli_example.lua: version 1.2.1")
16+
os.exit(0)
17+
end
18+
end
19+
1220
cli:set_name("cli_example.lua")
1321

1422
-- Required arguments:
@@ -26,8 +34,8 @@ cli:set_name("cli_example.lua")
2634
-- Flags: a flag is a boolean option. Defaults to false
2735
-- A flag with short-key notation only
2836
cli:add_flag("-d", "script will run in DEBUG mode")
29-
-- A flag with both the short-key and --expanded-key notations
30-
cli:add_flag("-v, --version", "prints the program's version and exits")
37+
-- A flag with both the short-key and --expanded-key notations, and callback function
38+
cli:add_flag("-v, --version", "prints the program's version and exits", print_version)
3139
-- A flag with --expanded-key notation only
3240
cli:add_flag("--verbose", "the script output will be very verbose")
3341

@@ -43,12 +51,6 @@ end
4351
-- upon successful parsing cliargs will delete itslef to free resources
4452
-- for k,item in pairs(args) do print(k .. " => " .. tostring(item)) end
4553

46-
-- checking for flags: is -v or --version set?
47-
if args["v"] then
48-
print("cli_example.lua: version 1.2.1")
49-
os.exit(0)
50-
end
51-
5254
print("Input file: " .. args["INPUT"])
5355
print("Output file: " .. args["o"])
5456

examples/02_parse_callbacks.lua

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--[[
2+
3+
Shows how to define a callback to be invoked as soon as an option is parsed.
4+
Callbacks are useful for abruptive options like "--help" or "--version" where
5+
you might want to stop the execution of the parser/program if passed.
6+
7+
Try this file with the following commands lines;
8+
example.lua --version
9+
example.lua -v
10+
example.lua
11+
--]]
12+
13+
local cli = require "cliargs"
14+
15+
local function print_version(key, value, altkey)
16+
-- this is called when the flag -v or --version is set
17+
if key == 'version' then
18+
print("example.lua: version 1.2.1")
19+
os.exit(0)
20+
end
21+
end
22+
23+
cli:set_name("try_my_version.lua")
24+
cli:add_flag("-v, --version", "prints the program's version and exits", print_version)
25+
26+
-- Parses from _G['arg']
27+
local args = cli:parse()
28+
29+
if not args then
30+
-- something wrong happened and an error was printed
31+
os.exit(1)
32+
end
33+
34+
-- if we got to this point, it means -v (or --version) were not passed:
35+
print "Why, hi!"

spec/cliargs_parsing_spec.lua

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,4 +314,49 @@ describe("Testing cliargs library parsing commandlines", function()
314314
assert.is.truthy(result)
315315
assert.are.equal("", result.compress)
316316
end)
317+
318+
describe("Tests parsing with callback", function()
319+
local cb = {}
320+
321+
local function callback(key, value, altkey)
322+
cb.key, cb.value, cb.altkey = key, value, altkey
323+
end
324+
325+
before_each(function()
326+
cb = {}
327+
end)
328+
329+
it("tests short-key option", function()
330+
_G.arg = { "-k", "myvalue" }
331+
cli:add_option("-k, --long-key=VALUE", "key descriptioin", "", callback)
332+
local expected = { k = "myvalue", ["long-key"] = "myvalue" }
333+
local result = cli:parse()
334+
assert.are.same(expected, result)
335+
assert.are.equal(cb.key, "k")
336+
assert.are.equal(cb.value, "myvalue")
337+
assert.are.equal(cb.altkey, "long-key")
338+
end)
339+
340+
it("tests expanded-key option", function()
341+
_G.arg = { "--long-key", "val" }
342+
cli:add_option("-k, --long-key=VALUE", "key descriptioin", "", callback)
343+
local expected = { k = "val", ["long-key"] = "val" }
344+
local result = cli:parse()
345+
assert.are.same(expected, result)
346+
assert.are.equal(cb.key, "long-key")
347+
assert.are.equal(cb.value, "val")
348+
assert.are.equal(cb.altkey, "k")
349+
end)
350+
351+
it("tests expanded-key flag with not short-key", function()
352+
_G.arg = { "--version" }
353+
cli:add_flag("--version", "prints the version and exits", callback)
354+
local expected = { version = true }
355+
local result = cli:parse()
356+
assert.are.same(expected, result)
357+
assert.are.equal(cb.key, "version")
358+
assert.are.equal(cb.value, true)
359+
assert.are.equal(cb.altkey, nil)
360+
end)
361+
end)
317362
end)

src/cliargs.lua

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ end
139139
---
140140
--- ### Parameters
141141
--- 1. **key**: the argument's "name" that will be displayed to the user
142-
--- 1. **desc**: a description of the argument
142+
--- 2. **desc**: a description of the argument
143143
---
144144
--- ### Usage example
145145
--- The following will parse the argument (if specified) and set its value in `args["root"]`:
@@ -162,9 +162,9 @@ end
162162
---
163163
--- ### Parameters
164164
--- 1. **key**: the argument's "name" that will be displayed to the user
165-
--- 1. **desc**: a description of the argument
166-
--- 1. **default**: *optional*; specify a default value (the default is "")
167-
--- 1. **maxcount**: *optional*; specify the maximum number of occurences allowed (default is 1)
165+
--- 2. **desc**: a description of the argument
166+
--- 3. **default**: *optional*; specify a default value (the default is "")
167+
--- 4. **maxcount**: *optional*; specify the maximum number of occurences allowed (default is 1)
168168
---
169169
--- ### Usage example
170170
--- The following will parse the argument (if specified) and set its value in `args["root"]`:
@@ -192,13 +192,14 @@ end
192192
--- if the 2nd notation is used then a value can be defined after an `=` (`'-key, --expanded-key=VALUE'`).
193193
--- As a final option it is possible to only use the expanded key (eg. `'--expanded-key'`) both with and
194194
--- without a value specified.
195-
--- 1. **desc**: a description for the argument to be shown in --help
196-
--- 1. **default**: *optional*; specify a default value (the default is "")
195+
--- 2. **desc**: a description for the argument to be shown in --help
196+
--- 3. **default**: *optional*; specify a default value (the default is "")
197+
--- 4. **callback**: *optional*; specify a function to call when this option is parsed (the default is nil)
197198
---
198199
--- ### Usage example
199200
--- The following option will be stored in `args["i"]` and `args["input"]` with a default value of `my_file.txt`:
200201
--- `cli:add_option("-i, --input=FILE", "path to the input file", "my_file.txt")`
201-
function cli:add_opt(key, desc, default)
202+
function cli:add_opt(key, desc, default, callback)
202203
-- parameterize the key if needed, possible variations:
203204
-- 1. -key
204205
-- 2. -key VALUE
@@ -219,6 +220,14 @@ function cli:add_opt(key, desc, default)
219220
),
220221
"Default argument: expected a string, nil, or {}"
221222
)
223+
assert(
224+
(
225+
type(callback) == "function"
226+
or callback == nil
227+
or (getmetatable(callback) or {}).__call
228+
),
229+
"Callback argument: expected a function or nil"
230+
)
222231

223232
local k, ek, v = disect(key)
224233

@@ -244,6 +253,7 @@ function cli:add_opt(key, desc, default)
244253
label = key,
245254
flag = (default == false),
246255
value = default,
256+
callback = callback,
247257
}
248258

249259
table.insert(self.optional, entry)
@@ -256,9 +266,10 @@ end
256266
---
257267
--- ### Parameters
258268
-- 1. **key**: the argument's key
259-
-- 1. **desc**: a description of the argument to be displayed in the help listing
260-
function cli:add_flag(key, desc)
261-
self:add_opt(key, desc, false)
269+
-- 2. **desc**: a description of the argument to be displayed in the help listing
270+
-- 4. **callback**: *optional*; specify a function to call when this flag is parsed (the default is nil)
271+
function cli:add_flag(key, desc, callback)
272+
self:add_opt(key, desc, false, callback)
262273
end
263274

264275
--- Parses the arguments found in #arg and returns a table with the populated values.
@@ -268,7 +279,7 @@ end
268279
--- ### Parameters
269280
--- 1. **arguments**: set this to arg
270281
--- 1. **noprint**: set this flag to prevent any information (error or help info) from being printed
271-
--- 1. **dump**: set this flag to dump the parsed variables for debugging purposes, alternatively
282+
--- 2. **dump**: set this flag to dump the parsed variables for debugging purposes, alternatively
272283
--- set the first option to --__DUMP__ (option with 2 trailing and leading underscores) to dump at runtime.
273284
---
274285
--- ### Returns
@@ -372,6 +383,17 @@ function cli:parse(arguments, noprint, dump)
372383
else
373384
entry.value = optval
374385
end
386+
387+
-- invoke the option's parse-callback, if any
388+
if entry.callback then
389+
local altkey = entry.key
390+
391+
if optkey == entry.key then
392+
altkey = entry.expanded_key
393+
end
394+
395+
entry.callback(optkey, optval, altkey)
396+
end
375397
end
376398

377399
-- missing any required arguments, or too many?

0 commit comments

Comments
 (0)