This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
EveryOS's profile picture

[UPDATED!] GetOpts, a linux-styled argument parser

Started by EveryOS, 30 November 2016 - 02:11 PM
EveryOS #1
Posted 30 November 2016 - 03:11 PM
GetOpts, a linux-styled argument parser
*Updated. The old version is depreciated, and will soon be removed.

MORE PLANNED UPDATES:
  • Add substitution of a table of arg sets for the number of args.
  • Test function for itable reversion
  • Add more itable management functions
NOTE: Make sure to pass the true as an argument to getOpts.newStruct, otherwise help and escaping will not be generated!

pastebin get PSFnwfPp getOpts

Example Program
local getOpts = loadfile('getOpts')()
local struct = getOpts.newStruct(true)

struct:setHeader('Line printer. A getOpts example.')
struct:add('-nl', '--newLine', 'Creates new line', function() print() end, 0)
struct:addM('-e', 'anon', 'Enables progam', function() end, 0)
struct:add(nil, '--text', 'Sets the text to print.',
  function(args, parser)
	args = parser.functions.toITable(args) --The toITable function can also be called as getOpts.toITable
	if not (#args > 0) then
	  error('Required <text>')
	  getOpts.help(parser)
	  return
	end
	for k, v in ipairs(args) do
	  write(v.." ")
	end
  end
, nil, "<text>")
struct:add('-st', '--simpletext', 'Prints one word.',
  function(args, parser)
	args = parser.functions.toITable(args) --The toITable function can also be called as getOpts.toITable
	if not args[1] then
	  error('Required <text>')
	  getOpts.help(parser)
	  return
	end
	write(args[1])
  end
, 1, "<text>")

local left = getOpts.parse(struct, {...}, true)
if not left then return end

print()
print('Leftover args:')
for k, v in pairs(getOpts.toITable(left)) do print(v) end
To download and try this program:
pastebin get PSFnwfPp getOpts
pastebin get kLNpFQj4 test
test
test -e
test --text hi
test -e -h
test -e --text not escaped -% escaped!
test -e --text --aflag
test -e --text %--naddaflag
test Even Returns Leftovers! -e
test -e -st Specify Max # of args (optional)


Try playing around with it

APIS:

[object parserObject]
  :add(aliases, fullname, help, runFunc, maxArgs or nil, usage) --runFunc is a function with args [args [, [object parserObject]]]
  :addM([same args as :add]) --Same as add, but creates mandatory args
  :setHeader(head) --Creates the help header
  .opts --a table with more tables, stores flag info
  .functions --Only available in flags
	.escape(escapepoint) --Escaping. If a number is provided, anything >= that number will be escaped. If a table is provided, those specific arguments are escaped.
	.toITable() --Removes gaps from tables
	.getFlagPos() --Untested, returns pos of current flag
	
  
loadfile('getOpts', _G)()
  .getArgs(string) returns table  --A tokeniser
  .toITable(table) --removes gaps from table
  .help(struct.opts, struct.header) --Prints help screen
  .parse(struct, args) returns table --Returns left over args, this is the main function
  .newStruct(autoGenItems) returns [object parserObject]

What has changed?
  • Items can now be called multiple times
  • New functions
  • Reversed args for the function used for :add func argument, now args, parser instead of parser, args
  • Now run in chronological order
  • You can figure out which numbered item from the original table args were. The indices on the argument tables contain gaps.
  • Added anon functions. The -% flag is now an anon function and is no longer hard-coded in
  • added usage arg to :add
WARNING:
Initializing a struct without the autoGenItems flag will not contain help and -%. Re-initializing the parser.opts table will also remove these.



Old postGetOpts, a table parser

pastebin get UHDHsbx2 getOpts

With just the following code:

local getOpts = loadfile('getOpts')()
local struct = getOpts.newStruct(true)

struct:setHeader('Line printer. A getOpts example.')
struct:add('-nl', '--newLine', 'No args. Creates new line', function() print() end, 0)
struct:addM(nil, '--text', '<text>. Sets the text to print.', function(parser, args) if not args[1] then printError('Required <text>') fHelp(parser) return end  for k, v in pairs(args) do write(v.." ") end end)

local left = parse(struct, {...})
if not left then return end

print()
print('Leftover args:')
for k, v in pairs(left) do print(v) end
Try the following with this simple program:

<progSaveLoc> --text testText
<progSaveLoc> --text text -nl
<progSaveLoc>
<progSaveLoc> -nl
<progSaveLoc> --newLine --text newLine!! Yay!
<progSaveLoc> Leftover Arguments --text Leftovers!
<progSaveLoc> --text escaping example A -% ESCAPED!
<progSaveLoc> %% %--escaping %-e --text Escaping Example B
<progSaveLoc> -h --text some text

You will have a working parser-based program.

APIS:
loadfile('getOpts', _G)()
  .getArgs(string) returns table  --A tokeniser
  .help(struct.opts, struct.header) --Prints help screen
  .parse(struct, args) returns table --Returns left over args, this is the main function
  .newStruct(autoGenHelp) returns table
	:add(aliases, fullname, help, runFunc, maxArgs or nil)
	:addM([same args as :add]) --Same as add, but creates mandatory args
	:setHeader(head) --Creates the help header
Edited on 19 December 2017 - 02:05 PM
TheRockettek #2
Posted 30 November 2016 - 04:20 PM
dammit i was gonna make one today :^) Looks like someone beat me to it. Also i swear soneone already made one of these?
EveryOS #3
Posted 30 November 2016 - 08:31 PM
ironic. well it is very buggy i made it on a mobile device and debuged it later
Admicos #4
Posted 30 November 2016 - 09:14 PM
dammit i was gonna make one today :^) Looks like someone beat me to it. Also i swear soneone already made one of these?

Was it me?

Joking aside, i feel like your output looks a little "messy". But i haven't tried the rest of it myself. Other than that, it looks ok.
EveryOS #5
Posted 30 November 2016 - 11:05 PM
Oh, I didn't realize you already made something like this, with, ironically, the exact same name.

Well anyways, here's were I'm planning on going from here


--I'll completely redo the parse function. It doesn't work very well with tables containing multiple items.

--Ill add checkForArg(t, arg or aliases)
--Ill add newStruct():nonm(arg or aliases)
--Ill add newStruct():m(arg or aliases)
Ill edit newStruct() to take argument autoCreateBasicFramework, a boolean value

Also, there is a feature I didn't tell you about, mainly because it doesn't work correctly.
EveryOS #6
Posted 20 July 2017 - 09:09 PM
Im going to be redoing this soon. In the meantime, may you remove this topic?
Dave-ee Jones #7
Posted 20 July 2017 - 11:52 PM
Im going to be redoing this soon. In the meantime, may you remove this topic?

You could just edit the main post, and keep it up and once it's done comment at the bottom with an update?
EveryOS #8
Posted 21 July 2017 - 06:29 PM
OK
EveryOS #9
Posted 26 September 2017 - 05:24 PM
Updated post! I'll re-add image soon.
EveryOS #10
Posted 13 December 2017 - 05:44 PM
GetOpts has been updated (again!). The post has been updated.
Edited on 13 December 2017 - 04:45 PM
EveryOS #11
Posted 19 December 2017 - 03:05 PM
EVEN MORE UPDATES!

Turns out I already implemented function-less flags. I made -% function-less and fixed broken escape function