Argument_parser_number_9
One thing I return to again and again, is parsing arguments. I have studied most of the available options for ruby: optimist, optimist_xl, rationalist, slop etc.
I have also built several parsers of my own.. using different approaches.
Today I started thinking: What is the main problem when parsing arguments.
Well, the main problem is to know whether an item is a key or a value.
Example:
--name Olle --age 32 --verbose my_file.txt
We can’t just read key/value key/value .. because then --verbose gets the value my_file.txt
The solution is obvious: refuse valueless arguments!
--name Olle --age 32 --verbose false -- my_file.txt
- Everything after
--is positionals. - Everything before
--is key/value pairs.
We don’t accept and adapt to a stupid standard. Instead we create our own and educate the end user.
Given this our main loop becomes:
loop {
k, v = enum.next, (enum.next rescue nil)
}
My version is using a plugin system where a plugin can run before, during or after parsing.
Plugins run in the order loaded. A plugin can CONFLICT with another plugin. And a plugin has its hook(s): :pre :coerce :post (before, during, after).
My parser now has five (optional) plugins:
- equals (accepts : and = when setting a value. Ex:
--name=Olle) - list (accepts
-v 3 -v 4 -v 5as a list. Also accepts-v list/3,4,5) - positional (splits arguments on single ‘–’. Left is named, right is positional)
- short_split (converts
-abc 1to-a 1 -b 1 -c 1) - single_short (treats
-abcas-a bcand-s3as-s 3)
arg_parser.rb is 31 lines; plugin_manager.rb is 32 lines.