-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathterminal_parser.py
90 lines (73 loc) · 3.09 KB
/
terminal_parser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
"""
terminal_parser.py: Responsible for parsing command arguments, may include further functions for formatting terminal text
Contributors: Andrew Combs
"""
import types
from ast import literal_eval
# TODO: Better naming conventions
class Parser(object):
def __init__(self, commands: list):
self.lookup = {}
for command in commands:
self.add_command(*command)
def add_command(self, command: str, function: types.FunctionType, args: list, flags: list, defkwargs: dict):
"""
Adds a command to the parser's local dictionary.
command [str]: The name of the argument
function [function]: The function the command passes arguments for
args [list]: A list of types in order of how arguments should be passed
flags [list]: A list of strings containing the name of boolean flag values
defkwargs [dict]: All the default arguments that should be filled in to the function (must come last)
"""
self.lookup[command] = (function, args, flags, defkwargs)
# TODO: Make code more readable
def parse(self, given: str) -> tuple:
"""
Parses a string using the local parser's dictionary
given [str]: input string to be parsed
"""
nodes = given.split(" ")
nodes = [n for n in nodes if n]
cmd = nodes[0]
if cmd not in self.lookup.keys(): return "ERROR", "COMMAND NOT FOUND", f"'{cmd}' DOES NOT EXIST"
func = self.lookup[cmd]
args = nodes[1:]
flags = [i for i in args if "--" in i]
# this is rather janky
# Parsing arguments (*args)
std_types = [int, float, str, bool]
parsed_args = []
for t, arg in zip(func[1], args):
try:
if t in std_types:
parsed_args.append(t(arg))
elif t is object:
parsed_args.append(literal_eval(arg))
else:
parsed_args.append(t(literal_eval(arg)))
except ValueError:
return "ERROR", "MISMATCHED TYPES", f"{type(arg)} IS NOT {t}"
# Parsing flags (**kwargs)
parsed_flags = func[3]
for flag in flags:
if flag in func[2]:
parsed_flags[flag[2:]] = True
else:
return "ERROR", "FLAG NOT FOUND", f"FLAG {flag} DOES NOT EXIT IN FUNCTION"
info = (cmd, tuple(parsed_args), parsed_flags)
return info
def execute(self, info=None):
"""
Executes a function given info parameters
info [tuple]: info required in order of (command_name, args, kwargs)
"""
cmd = info[0]
# Actual error logging needed here
if cmd == "ERROR": return info
if cmd not in self.lookup.keys(): return "ERROR", "COMMAND NOT FOUND", f"{cmd} DOES NOT EXIST"
func = self.lookup[cmd]
if len(info[1]) != len(func[1]):
return (
"ERROR", "INVALID NUMBER OF ARGUMENTS",
f"{cmd} REQUIRES {len(func[1])} ARGUMENTS, {len(info[1])} GIVEN")
return func[0](*info[1], **info[2])