me
/
LeekBots
Archived
1
0
Fork 0
This repository has been archived on 2019-06-07. You can view files and clone it, but cannot push or open issues/pull-requests.
LeekBots/CommandTree.py

140 lines
5.1 KiB
Python

#Sheychen 2017
#CC BY
import itertools
class CommandTree:
def __init__(self):
self.commands = {}
#self.options = {}
def addCommand(self, path, text, func, params):
if self.commands.get(path) is None:
self.commands[path] = {
'text': text,
'func': func,
'params': params
}
else:
print('Command {0}: Allready added'.format(path))
return self
def runCommand(self, path, args):
command = self.commands[path]
params = []
for data, param in itertools.zip_longest(args[len(path.split()):], command['params']):
if not param is None:
name = param.get('name', '')
if len(name) > 0:
name += ':'
if data is None:
if not param.get('optional', False):
print('Wrong params count in "{0}", {1} isn\'t optional.'.
format(path, name))
return
else:
ptype = param.get('type')
if type(ptype) is type:
try:
data = ptype(data)
except (TypeError, ValueError) as e:
print('Wrong type in "{0}", {1}"{2}" must be an {3}.'.format(
path, name, data, ptype.__name__))
return
if ptype == int:
pmin = param.get('min')
if type(pmin) is int:
if data < pmin:
print('Wrong value in "{0}", {1}"{2}" must be >= {3}.'.
format(path, name, data, pmin))
return
pmax = param.get('max')
if type(pmax) is int:
if data > pmax:
print('Wrong value in "{0}", {1}"{2}" must be <= {3}.'.
format(path, name, data, pmax))
return
plist = param.get('list')
if type(plist) is list:
if not data in plist:
print(
'Wrong value in "{0}", {1}"{2}" must be one of ({3}).'.
format(path, name, data, ', '.join(
str(x) for x in plist)))
return
else:
print('"{0}" only accepts {1} params.'.format(
path, len(command['params'])))
return
params.append(data)
command['func'](params)
def helpCommand(self, command, args):
print('TODO print params details')
print('{0}: {1}'.format(command, self.commands[command]['text']))
def listCommands(self, paths):
print('TODO print short params')
print(
'See "help <command>" for more details or "help <command path>" to filter commands'
)
paths.sort()
last = []
for path in paths:
current = path.split()
for i in range(0, min(len(last), len(current))):
if current[i] == last[i]:
current[i] = ' ' * len(current[i])
last = path.split()
print('{0}: {1}'.format(
' '.join(current), self.commands[path]['text'].split('\n')[0]))
def parse(self, args):
#TODO parse options
path = args
name = path.pop(0)
commands = list(self.commands.keys())
if len(args) > 0:
run = self.runCommand
if path[0] == 'help':
path.pop(0)
run = self.helpCommand
for i in range(0, len(path)):
newcommands = []
for command in commands:
splits = command.split()
if len(splits) >= i:
if splits[i] == path[i]:
newcommands.append(command)
commands = newcommands
if len(commands) <= 1:
break
if len(commands) == 0:
print('Unknown command "{0}"'.format(' '.join(path)))
print('See "{0} help"'.format(name))
elif len(commands) == 1:
run(commands[0], args)
else:
self.listCommands(commands)
else:
self.listCommands(commands)
'''
def addOption(self, key, names, options):
if self.options.get(key) is None:
self.options[key] = {'names': names, 'options': options}
else:
print('Option {0}: Allready added'.format(key))
return self
def getOption(self, key):
option = self.options.get(key)
if not option is dict:
return option.get('value')
else:
return option
'''