Advertisement
TheOddByte

[ComputerCraft] ArgsParser

Feb 28th, 2016
1,340
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.54 KB | None | 0 0
  1. --[[
  2.     [Library] ArgsParser
  3.     @version 1.1, 2016-03-27
  4.     @author TheOddByte
  5. --]]
  6.  
  7.  
  8.  
  9. local ArgsParser   = {}
  10. ArgsParser.__index = ArgsParser
  11.  
  12.  
  13.  
  14. local function len( t )
  15.     assert( type( t ) == "table", "table expected, got " .. type( t ) )
  16.     local length = 0
  17.     for k, v in pairs( t ) do
  18.         length = length + 1
  19.     end
  20.     return length
  21. end
  22.  
  23. local function displayUsage( self, detailed, err )
  24.    
  25.     local w, h    = term.getSize()
  26.     local program = shell.getRunningProgram()
  27.     local length  = 0
  28.    
  29.     term.write( "Usage: " .. program )
  30.     for i = 1, #self.positional do
  31.         write( " <" .. self.positional[i].name .. ">" )
  32.         if #self.positional[i].name + 2 > length then
  33.            length = #self.positional[i].name + 2
  34.         end
  35.     end
  36.     for k, v in pairs( self.optional ) do
  37.         write( " [" .. k .. "]" )
  38.         if #k + 2 > length then
  39.             length = #k + 2
  40.         end
  41.     end
  42.     print( "" )
  43.    
  44.     local function wr( x, y, text )
  45.         term.setCursorPos( x, y )
  46.         term.write( text )
  47.     end
  48.    
  49.     --# Show detailed info
  50.     if detailed then
  51.         print( #self.positional > 0 and "\n\nPositional arguments:" or "\n\nNo positional arguments\n" )
  52.         if #self.positional > 0 then
  53.             local x, y = term.getCursorPos()
  54.             for i, v in ipairs( self.positional ) do
  55.                 wr( 3, y, v.name )
  56.                 wr( 3 + length, y, v.help and v.help or "No help available" )
  57.                 y = y + 1
  58.                 if y >= h then
  59.                     y = h
  60.                     os.pullEvent( "key" )
  61.                     term.scroll( 1 )
  62.                 end
  63.             end
  64.             print( "" )
  65.         end
  66.        
  67.         print( len( self.optional ) > 0 and "\n\nOptional arguments:" or "\n\nNo optional arguments\n" )
  68.         if len( self.optional ) > 0 then
  69.             local x, y = term.getCursorPos()
  70.             for k, v in pairs( self.optional ) do
  71.                 wr( 3, y, k )
  72.                 wr( 3 + length, y, v.help and v.help or "No help available" )
  73.                 y = y + 1
  74.                 if y >= h then
  75.                     y = h
  76.                     os.pullEvent( "key" )
  77.                     term.scroll( 1 )
  78.                 end
  79.             end
  80.             print( "" )
  81.         end
  82.        
  83.         print( #self.examples > 0 and "\n\nExamples:" or "\n\nNo examples\n")
  84.         if #self.examples > 0 then
  85.             local x, y = term.getCursorPos();
  86.             for i, v in ipairs( self.examples ) do
  87.                 wr( 3, y, program .. " " .. v )
  88.                 y = y + 1
  89.                 if y >= h then
  90.                     y = h
  91.                     os.pullEvent( "key" )
  92.                     term.scroll( 1 )
  93.                 end
  94.             end
  95.         end            
  96.     end
  97.    
  98.     --# Print the error if it's supplied
  99.     if err then
  100.         print( "\nerror: " .. err )
  101.     end
  102.    
  103.     print("")
  104.     error()
  105. end
  106.  
  107.  
  108. ArgsParser.init = function()
  109.     local parser = {
  110.         examples   = {};
  111.         positional = {};
  112.         optional   = {
  113.             ["--help"] = {
  114.                 alt      = "-h";
  115.                 optional = true;
  116.                 help     = "Show this help message and exit";
  117.                 action   = function( self )
  118.                     displayUsage( self, true )
  119.                 end
  120.             }
  121.         }
  122.     }
  123.     return setmetatable( parser, ArgsParser )
  124. end
  125.  
  126.  
  127.  
  128. function ArgsParser:addArgument( name, alt, help, _type )
  129.     --# Check for errors
  130.     assert( type( name ) == "string", "string exptected, got " .. type( name ) )
  131.    
  132.     --# Check if it was an optional argument
  133.     local optional = name:sub( 1, 1 ) == "-"
  134.    
  135.     --# Create the argument
  136.     local arg = {
  137.         name       = optional and nil or name;
  138.         alt        = optional and alt and ( alt:sub( 1, 1 ) == "-" and alt or nil ) or nil;
  139.         optional   = optional;
  140.         help       = help;
  141.         type       = _type;
  142.     }
  143.     if optional then
  144.         self.optional[name] = arg
  145.     else
  146.         table.insert( self.positional, arg )
  147.     end
  148. end
  149.  
  150.  
  151.  
  152. function ArgsParser:addExample( example )
  153.     assert( type( example ) == "string", "string exptected, got " .. type( example ) )
  154.     table.insert( self.examples, example )
  155. end
  156.  
  157.  
  158.  
  159.  
  160. function ArgsParser:parse( args )
  161.     local i = 1
  162.     local t = {}
  163.    
  164.    
  165.     if #args < 1 then
  166.         displayUsage( self, false, "too few arguments" )
  167.     end
  168.    
  169.     for i, v in ipairs( args ) do
  170.         if v == "-h" or v == "--help" then
  171.             displayUsage( self, true )
  172.         end
  173.     end
  174.  
  175.     --# Handle positional arguments first
  176.     if #self.positional > 0 then
  177.         if #args < #self.positional then
  178.             displayUsage( self, false, "too few arguments" )
  179.         end
  180.        
  181.         for i = 1, #self.positional do
  182.             for k, v in pairs( self.optional ) do
  183.                 if args[i] == k then
  184.                     displayUsage( self, false, "missing argument parameter" )
  185.                 else
  186.                     t[self.positional[i].name] = args[i]
  187.                 end
  188.             end
  189.         end
  190.     end
  191.    
  192.     --# Handle the optional arguments
  193.     while i <= #args do
  194.         for k, v in pairs( self.optional ) do
  195.             if args[i] == k or args[i] == v.alt then
  196.                 if v.action and type( v.action ) == "function" then
  197.                     return v.action( self )
  198.                 else
  199.                     if args[ i + 1 ] then
  200.                         for name, value in pairs( self.optional ) do
  201.                             if args[ i + 1 ] == param then
  202.                                 return
  203.                             end
  204.                         end
  205.                         if v.type then
  206.                             if v.type == "number" then
  207.                                 args[ i + 1 ] = type( tonumber( args[ i + 1 ] ) ) == "number" and tonumber( args[ i + 1 ] ) or displayUsage( self, false, "invalid type, expected number" )
  208.                             elseif v.type == "boolean" then
  209.                                 args[ i + 1 ] = ( args[ i + 1 ] == "true" or args[ i + 1 ] == "false" ) and args[ i + 1 ] or displayUsage( self, false, "invalid type, expected boolean" )
  210.                             end
  211.                         end
  212.                         t[k:gsub( "-", "" )] = args[ i + 1 ]
  213.                         i = i + 2
  214.                     end
  215.                 end
  216.             end
  217.         end
  218.         i = i + 1
  219.     end
  220.     return t
  221. end
  222.  
  223.  
  224. return ArgsParser
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement