More methods!

main
Nicholas Hope 2022-10-05 21:32:07 -04:00
parent 607894648c
commit 9331f13786
1 changed files with 125 additions and 138 deletions

View File

@ -28,7 +28,7 @@ class Bind(object):
bindTypes = []
instances = {}
def __init__(self, key='', fields={}, *, parent=None):
def __init__(self, key='', fields={}, /,*, parent=None):
if parent is None:
self.alias = False
self.key = str(key)
@ -72,15 +72,11 @@ class Bind(object):
self.instances[type(self)] = [self]
def verify(self):
try:
self.alias = self.fields.pop('alias')
self.alias = self.optional('alias', default=False)
if not isinstance(self.alias, bool):
self.errors.append(
f'alias should be "yes" or "no", not "{self.alias}"'
self.err(
f'`alias` should be "yes" or "no", not "{self.alias}"'
)
self.alias = False
except popErrors:
self.alias = False
try:
typeName, self.key = self.key.split(' ', 1)
@ -107,6 +103,21 @@ class Bind(object):
if (not self.alias) and (self.key not in validKeyList):
self.errors.append(f'invalid key name: "{self.key}"')
def optional(self, name, /,*, default=None):
try:
return self.fields.pop(name)
except popErrors:
return default
def cmdListFrom(self, name, /,*, default=None):
result = self.fields.pop(name)
if isinstance(result, str):
return result.split(';')
elif isinstance(result, list):
return result
else:
return default
def toTargetType(self):
if self.TargetType is None:
# do nothing
@ -128,21 +139,20 @@ class Bind(object):
class Impulse(Bind):
def verify(self):
self.command = None
self.command: list = None
if not isinstance(self.fields, dict):
self.fields = {'command': self.fields}
try:
self.command = self.fields.pop('command')
if isinstance(self.command, str):
self.command = self.command.split(';')
elif not isinstance(self.command, list):
self.err('`command` field must be argument of string or list')
self.command = None
except KeyError:
self.command = self.cmdListFrom(
'command',
default=self.fields
)
if self.command is None:
self.err('`command` field must be string or list')
except popErrors:
self.err('requires `command` field')
def toTF2(self) -> str:
if self.alias:
bindOrAlias = 'alias'
@ -167,11 +177,8 @@ class Impulse(Bind):
'secondary': 'slot2',
'melee': 'slot3'
}
try:
cmd = simpleSCs[cmd]
except KeyError:
# not a shortcut
pass
# if is shortcut, change
cmd = simpleSCs.get(cmd, cmd)
if cmd == 'voice':
cmd = 'voicemenu'
@ -183,8 +190,8 @@ class Impulse(Bind):
elif cmd == 'loadout' and restOfCmd.isalpha():
cmd = 'load_itempreset'
try:
restOfCmd = restOfCmd.lower()
restOfCmd = str(['a','b','c','d'].index(restOfCmd))
loadoutNum = ['a','b','c','d'].index(restOfCmd.lower())
restOfCmd = str(loadoutNum)
except ValueError:
# not a load_itempreset shortcut
pass
@ -221,40 +228,32 @@ class Impulse(Bind):
'exit': '1 1',
'sentry': '2 0'
}
for shortBuild, num in buildingNums.items():
if building == shortBuild:
return num
return buildingNums.get(building, building)
class Hold(Bind):
def verify(self):
self.press = None
self.release = None
self.press: list = None
self.release: list = None
if not isinstance(self.fields, dict):
self.fields = {'press': self.fields}
# verify press
try:
self.press = self.fields.pop('press')
if isinstance(self.press, str):
self.press = self.press.split(';')
elif not isinstance(self.press, list):
self.err('`press` field must be string or list')
self.press = None
except KeyError:
self.err('requires `press` field')
self.press = self.cmdListFrom('press')
if self.press is None:
return
self.err('`press` field must be string or list')
except popErrors:
self.err('requires `press` field')
# verify release
try:
self.release = self.fields.pop('release')
if isinstance(self.release, str):
self.release = self.release.split(';')
elif not isinstance(self.release, list):
self.release = self.cmdListFrom('release')
if self.release is None:
self.err('`release` field must be string or list')
self.release = None
except popErrors:
if self.press is None:
return
self.warn('has no `release`, creating one')
# no release specified, do -action for each item in press
self.release = []
@ -271,11 +270,11 @@ class Hold(Bind):
# Making impulse instances from self.press and .release
# allows them to share the shortcuts
pressObj = Impulse(f'+{holdStr}', self.press)
pressObj = Impulse('+' + holdStr, self.press)
pressObj.alias = True
pressStr = pressObj.toTF2()
releaseObj = Impulse(f'-{holdStr}', self.release)
releaseObj = Impulse('-' + holdStr, self.release)
releaseObj.alias = True
releaseStr = releaseObj.toTF2()
@ -296,34 +295,29 @@ class Hold(Bind):
class Toggle(Bind):
def verify(self):
self.on = None
self.off = None
self.on : list = None
self.off: list = None
if not isinstance(self.fields, dict):
self.fields = {'on': self.fields}
# verify on
try:
self.on = self.fields.pop('on')
if isinstance(self.on, str):
self.on = self.on.split(';')
elif not isinstance(self.on, list):
self.err('`on` field must be string or list')
self.on = None
except KeyError:
self.err('requires `on` field')
self.on = self.cmdListFrom('on')
if self.on is None:
return
self.err(f'`on` field must be string or list')
except popErrors:
self.err('requires `on` field')
# verify off
try:
self.off = self.fields.pop('off')
if isinstance(self.off, str):
self.off = self.off.split(';')
elif not isinstance(self.off, list):
self.err('`off` field must be string or list')
self.off = self.cmdListFrom('off')
if self.off is None:
self.err(f'`off` field must be string or list')
except popErrors:
# no off specified, do -action for each item in on
self.off = []
if self.on is None:
return
for cmd in self.on:
if cmd[0] == '+':
self.off.append('-' + cmd[1:])
@ -361,21 +355,16 @@ class Double(Bind):
bindNames = []
def verify(self):
self.primary = None
self.primStr = f'{self.key}_primary'
self.secondary = None
self.secondStr = f'{self.key}_secondary'
self.condition = None
self.isToggle = False
# name of a bind type
self.type = None
# either 'released' (default) or 'both'
self.cancelBoth = False
self.primary: Bind = None
self.secondary: Bind = None
self.condition: str = None
self.type: str = None
# toggler
try:
self.condition = self.fields.pop('condition')
@ -384,15 +373,12 @@ class Double(Bind):
except popErrors:
self.err('requires `condition` field')
try:
self.isToggle = self.fields.pop('toggle')
self.isToggle = self.optional('toggle', default=False)
if not isinstance(self.isToggle, bool):
self.err(
'`toggle` field should be "yes" or "no", '
+ f'not "{self.isToggle}"'
'`toggle` field should be "yes" or "no",'
+ f' not "{self.isToggle}"'
)
except popErrors:
self.isToggle = False
# type
try:
@ -407,56 +393,57 @@ class Double(Bind):
return
# cancel mode, must happend after type has been inferred
try:
cancel = self.fields.pop('cancel')
cancel = self.optional('cancel', default='released')
if not isinstance(cancel, str):
self.err(f'`cancel` field must be "released" or "both"')
else:
if cancel == 'both':
if self.type == 'hold':
self.cancelBoth = True
else:
self.err(
'`cancel` field only affects "hold", '
+ f'not "{self.type}"'
'`cancel` field only affects "hold",'
+ f' not "{self.type}"'
)
elif cancel != 'released':
elif cancel == 'released':
self.cancelBoth = False
else:
self.err(
'`cancel` field must be "released" '
+ f'or "both", not "{cancel}"'
'`cancel` field must be "released"'
+ f' or "both", not "{cancel}"'
)
except popErrors:
cancel = 'released'
# primary action
try:
mainSection = self.fields.pop('primary')
mainBind = Bind(f'{self.type} {self.primStr}', mainSection)
mainBind = mainBind.toTargetType()
self.errors.extend(mainBind.errors)
self.warnings.extend(mainBind.warnings)
self.errors.remove(f'invalid key name: "{self.primStr}"')
self.primary = mainBind
self.primary = self.getSection('primary', self.primStr)
except popErrors:
self.err('requires `primary` field')
self.primary = None
# secondary action
try:
altSection = self.fields.pop('secondary')
altBind = Bind(f'{self.type} {self.secondStr}', altSection)
altBind = altBind.toTargetType()
self.errors.extend(altBind.errors)
self.warnings.extend(altBind.warnings)
self.errors.remove(f'invalid key name: "{self.secondStr}"')
self.secondary = altBind
self.secondary = self.getSection('secondary', self.secondStr)
except popErrors:
self.err('requires `secondary` field')
self.secondary = None
if self.primary is self.secondary is None:
self.err('has neither primary nor secondary')
def getSection(self, popName, key, /) -> Bind:
section = self.fields.pop(popName)
bind = Bind(f'{self.type} {key}', section)
bind = bind.toTargetType()
bind.errors.remove(f'invalid key name: "{key}"')
self.prettifyList(bind.errors, key)
self.errors.extend(bind.errors)
self.prettifyList(bind.warnings, key)
self.warnings.extend(bind.warnings)
return bind
def prettifyList(self, strList, origStr):
repStr = ' '.join(origStr.split('_', 1))
for i, cmd in enumerate(strList):
strList[i] = cmd.replace(origStr, repStr)
def toTF2(self) -> str:
# Get code for primary and secondary actions.