]> git.ipfire.org Git - ipfire-3.x.git/commitdiff
naoki: Refactoring of command line parsing.
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 18 Mar 2010 22:06:14 +0000 (23:06 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 18 Mar 2010 22:06:14 +0000 (23:06 +0100)
naoki/terminal.py

index 49a5985926222d1785353bf507bb04dfb763efaa..b28292ea91267c72c92d383c18da645cedb09c9b 100644 (file)
@@ -3,8 +3,249 @@
 import fcntl
 import os
 import struct
+import sys
 import termios
 
+from constants import *
+
+class ParsingError(Exception):
+       pass
+
+
+class Parser(object):
+       def __init__(self, name, arguments=[], parsers=[]):
+               self.name = name
+               self.arguments = arguments
+               self.parsers = parsers
+
+               self.subparser = None
+
+       def __repr__(self):
+               return "<Parser %s>" % self.name
+
+       def check(self, args):
+               if not args:
+                       return False
+
+               return self.name == args[0]
+
+       def parse(self, args):
+               if args and self.name == args[0]:
+                       args = args[1:]
+
+               for argument in self.arguments:
+                       args = argument.parse(args)
+
+               if args and self.parsers:
+                       for parser in self.parsers:
+                               if not parser.check(args):
+                                       continue
+
+                               self.subparser = parser
+                               break
+
+                       if self.subparser:
+                               args = self.subparser.parse(args)
+
+               return args
+
+       @property
+       def values(self):
+               ret = {
+                       "name" : self.name
+               }
+               if self.subparser:
+                       ret["subaction"] = self.subparser.values
+
+               for argument in self.arguments:
+                       ret[argument.name] = argument.value()
+
+               return ret
+
+
+class _Argument(object):
+       DEFAULT_HELP = "No help available"
+
+       def __init__(self, name, args, **kwargs):
+               self.name = name
+               self.args = args
+               self.help = kwargs.get("help", self.DEFAULT_HELP)
+
+               self._parsed = False
+               self._parsed_args = []
+
+       def parse(self, args):
+               raise NotImplementedError
+
+       def value(self):
+               raise NotImplementedError
+
+
+class Option(_Argument):
+       def parse(self, args):
+               self._parsed = True
+
+               new_args = []
+               for arg in args:
+                       if arg in self.args:
+                               self._parsed_args.append(arg)
+                       else:
+                               new_args.append(arg)
+
+               return new_args
+
+       def value(self):
+               for arg in self._parsed_args:
+                       if arg in self.args:
+                               return True
+
+               return False
+
+
+class Choice(_Argument):
+       def __init__(self, *args, **kwargs):
+               _Argument.__init__(self, *args, **kwargs)
+
+               self.choices = kwargs.get("choices", [])
+
+       def parse(self, args):
+               self._parsed = True
+
+               new_args = []
+               next_arg = False
+               for arg in args:
+                       if next_arg:
+                               if self.choices and not arg in self.choices:
+                                       raise ParsingError, "'%s' is not an allowed choice" % arg
+
+                               self._parsed_args.append(arg)
+                               next_arg = False
+                               continue
+
+                       if arg in self.args:
+                               self._parsed_args.append(arg)
+                               next_arg = True
+                       else:
+                               new_args.append(arg)
+
+               return new_args
+
+       def value(self):
+               if self._parsed_args:
+                       return self._parsed_args[-1]
+
+               return None
+
+
+class List(_Argument):
+       def __init__(self, name, **kwargs):
+               _Argument.__init__(self, name, [], **kwargs)
+
+       def parse(self, args):
+               self._parsed = True
+               self._parsed_args = args
+
+               return []
+
+       def value(self):
+               return self._parsed_args
+
+
+class Commandline(object):
+       def __init__(self, naoki):
+               self.naoki = naoki
+
+               # Parse the stuff
+               args = self.__parse()
+
+               # ... afterwards, process global directives
+               self.__process_global(args)
+
+       def __process_global(self, args):
+               # Set quiet mode
+               self.naoki.logging.quiet(args.quiet)
+
+               # XXX Set architecture
+
+       def __parse(self):
+               parser = Parser("root",
+                       arguments=[
+                               Option("help",  ["-h", "--help"],  help="Show help text"),
+                               Option("quiet", ["-q", "--quiet"], help="Set quiet mode"),
+                               Option("debug", ["-d", "--debug"], help="Set debugging mode"),
+                               Choice("arch",  ["-a", "--arch"], help="Set architecture",
+                                       choices=[arch for arch in arches.all]),
+                       ],
+                       parsers=[
+                               # Build
+                               Parser("build",
+                                       arguments=[
+                                               List("packages"),
+                                       ]),
+
+                               # Toolchain
+                               Parser("toolchain",
+                                       parsers=[
+                                               Parser("download"),
+                                               Parser("build"),
+                                       ]),
+
+                               # Package
+                               Parser("package",
+                                       parsers=[
+                                               Parser("info",
+                                                       arguments=[
+                                                               Option("long", ["-l", "--long"]),
+                                                               Option("machine", ["--machine"]),
+                                                               Option("wiki", ["--wiki"]),
+                                                               List("packages"),
+                                                       ]),
+                                               Parser("tree"),
+                                               Parser("list",
+                                                       arguments=[
+                                                               Option("long", ["-l", "--long"]),
+                                                       ]),
+                                               Parser("groups",
+                                                       arguments=[
+                                                               Option("wiki", ["--wiki"]),
+                                                       ]),
+                                       ]),
+
+                               # Source
+                               Parser("source",
+                                       parsers=[
+                                               Parser("download",
+                                                       arguments=[
+                                                               List("packages"),
+                                                       ]),
+                                               Parser("upload",
+                                                       arguments=[
+                                                               List("packages"),
+                                                       ]),
+                                               Parser("clean"),
+                                       ]),
+
+                               # Check
+                               Parser("check",
+                                       parsers=[
+                                               Parser("host"),
+                                       ]),
+
+                               # Batch
+                               Parser("batch",
+                                       parsers=[
+                                               Parser("cron"),
+                                       ]),
+                       ])
+
+               args = parser.parse(sys.argv[1:])
+
+               if args:
+                       raise ParsingError, "Unknown argument(s) passed: %s" % args
+
+               return parser.values
+
+
 DEFAULT_COLUMNS = 80
 DEFAULT_LINES = 25
 
@@ -44,3 +285,7 @@ def get_lines():
 
 def get_columns():
        return get_size()[1]
+
+
+if __name__ == "__main__":
+       cl = Commandline(naoki=None)