New alias system
parent
40c8b4ee42
commit
90f39b2737
|
@ -2,26 +2,48 @@
|
||||||
|
|
||||||
# Used for the conditions in the <double> type
|
# Used for the conditions in the <double> type
|
||||||
condDict = {}
|
condDict = {}
|
||||||
|
defaultDict = {}
|
||||||
|
bindOrAlias = "bind"
|
||||||
|
from json import dumps
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
def makeCFG(cfg, default=False):
|
||||||
|
global bindOrAlias
|
||||||
|
global condDict
|
||||||
|
global defaultDict
|
||||||
|
|
||||||
|
bindOrAlias = "bind"
|
||||||
|
if default:
|
||||||
|
# Write to defaultDict instead of condDict
|
||||||
|
condDict = defaultDict
|
||||||
|
else:
|
||||||
|
condDict = deepcopy(defaultDict)
|
||||||
|
|
||||||
def makeCFG(cfg):
|
|
||||||
condDict.clear()
|
|
||||||
ret = ''
|
ret = ''
|
||||||
for key, data in cfg.items():
|
for key, data in cfg.items():
|
||||||
# I know all of these fields exist because it was verified in verify.py
|
isAlias = False
|
||||||
bindType = firstTypeIn(data.keys())
|
if "alias" in data:
|
||||||
bindContent = data[bindType]
|
isAlias = data.pop("alias")
|
||||||
ret += branch(key, bindContent, bindType)
|
if isAlias:
|
||||||
|
bindOrAlias = "alias"
|
||||||
|
else:
|
||||||
|
bindOrAlias = "bind"
|
||||||
|
ret += branch(key, data)
|
||||||
|
|
||||||
# Doubles are weird. All of the toggles got put into a dictionary.
|
# Doubles are weird. All of the toggles got put into a dictionary.
|
||||||
# This takes all of the nested dictionaries and turns them into the right string
|
# This takes all of the nested dictionaries and turns them into the right string
|
||||||
for key, toggles in condDict.items():
|
for key, toggles in condDict.items():
|
||||||
ret += f'alias +{key}_toggles "{toggles["plus_toggles"]}"\n' +\
|
plusToggleStr = ';'.join(toggles["plus_toggles"])
|
||||||
f'alias -{key}_toggles "{toggles["minus_toggles"]}"\n' +\
|
minusToggleStr = ';'.join(toggles["minus_toggles"])
|
||||||
f'bind {key} "+{key}_toggles"\n'
|
ret += f'alias +{key}_toggles "{plusToggleStr}"\n' +\
|
||||||
|
f'alias -{key}_toggles "{minusToggleStr}"\n' +\
|
||||||
|
f'{bindOrAlias} {key} "+{key}_toggles"\n'
|
||||||
|
|
||||||
|
del condDict # free deep copy
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def firstTypeIn(inputList):
|
def typeOf(dictIn):
|
||||||
""" Find the first element common to both lists """
|
""" Find the first element common to both lists """
|
||||||
types = [
|
types = [
|
||||||
"impulse",
|
"impulse",
|
||||||
|
@ -31,10 +53,13 @@ def firstTypeIn(inputList):
|
||||||
"repeat"
|
"repeat"
|
||||||
]
|
]
|
||||||
for t in types:
|
for t in types:
|
||||||
if t in inputList:
|
if t in dictIn.keys():
|
||||||
return t
|
return t
|
||||||
|
|
||||||
def branch(keyName, bindContent, bindType):
|
def branch(keyName, bindContent):
|
||||||
|
bindType = typeOf(bindContent)
|
||||||
|
bindContent = bindContent.pop(bindType)
|
||||||
|
|
||||||
if bindType == "impulse":
|
if bindType == "impulse":
|
||||||
return impulse(keyName, bindContent)
|
return impulse(keyName, bindContent)
|
||||||
|
|
||||||
|
@ -54,6 +79,7 @@ def branch(keyName, bindContent, bindType):
|
||||||
return repeat(keyName, bindContent)
|
return repeat(keyName, bindContent)
|
||||||
|
|
||||||
def impulse(key, instruction):
|
def impulse(key, instruction):
|
||||||
|
global bindOrAlias
|
||||||
if isinstance(instruction, list):
|
if isinstance(instruction, list):
|
||||||
instruction = ';'.join(instruction)
|
instruction = ';'.join(instruction)
|
||||||
|
|
||||||
|
@ -64,7 +90,7 @@ def impulse(key, instruction):
|
||||||
|
|
||||||
instruction = ';'.join(allInstructions)
|
instruction = ';'.join(allInstructions)
|
||||||
|
|
||||||
return f'bind {key} "{instruction}"\n'
|
return f'{bindOrAlias} {key} "{instruction}"\n'
|
||||||
|
|
||||||
def impulseShortcuts(instruction):
|
def impulseShortcuts(instruction):
|
||||||
splitCommand = instruction.split(' ')
|
splitCommand = instruction.split(' ')
|
||||||
|
@ -116,13 +142,15 @@ def expandBuildings(building):
|
||||||
return num
|
return num
|
||||||
|
|
||||||
def simpleHold(key, instruction):
|
def simpleHold(key, instruction):
|
||||||
|
global bindOrAlias
|
||||||
# This isn't quite right, fix later!
|
# This isn't quite right, fix later!
|
||||||
if instruction[0] != '+':
|
if instruction[0] == '+' or instruction[0] == '-':
|
||||||
return f'bind {key} "+{instruction}"\n'
|
return f'{bindOrAlias} {key} "{instruction}"\n'
|
||||||
else:
|
else:
|
||||||
return f'bind {key} "{instruction}"\n'
|
return f'{bindOrAlias} {key} "+{instruction}"\n'
|
||||||
|
|
||||||
def listHold(key, options):
|
def listHold(key, options):
|
||||||
|
global bindOrAlias
|
||||||
pressStr = options["press"]
|
pressStr = options["press"]
|
||||||
if isinstance(pressStr, list):
|
if isinstance(pressStr, list):
|
||||||
pressStr = ';'.join(pressStr)
|
pressStr = ';'.join(pressStr)
|
||||||
|
@ -133,10 +161,12 @@ def listHold(key, options):
|
||||||
|
|
||||||
ret = f'alias +{key}_bind "{pressStr}"\n' +\
|
ret = f'alias +{key}_bind "{pressStr}"\n' +\
|
||||||
f'alias -{key}_bind "{releaseStr}"\n' +\
|
f'alias -{key}_bind "{releaseStr}"\n' +\
|
||||||
f'bind {key} "+{key}_bind"\n'
|
f'{bindOrAlias} {key} "+{key}_bind"\n'
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def toggle(key, instruction):
|
def toggle(key, instruction):
|
||||||
|
global bindOrAlias
|
||||||
onStr = f'turn_{key}_on'
|
onStr = f'turn_{key}_on'
|
||||||
offStr = f'turn_{key}_off'
|
offStr = f'turn_{key}_off'
|
||||||
togStr = f'toggle_{key}'
|
togStr = f'toggle_{key}'
|
||||||
|
@ -144,59 +174,47 @@ def toggle(key, instruction):
|
||||||
ret = f'alias {onStr} "+{instruction}; alias {togStr} {offStr}"\n' +\
|
ret = f'alias {onStr} "+{instruction}; alias {togStr} {offStr}"\n' +\
|
||||||
f'alias {offStr} "-{instruction}; alias {togStr} {onStr}"\n' +\
|
f'alias {offStr} "-{instruction}; alias {togStr} {onStr}"\n' +\
|
||||||
f'alias {togStr} "{onStr}"\n' +\
|
f'alias {togStr} "{onStr}"\n' +\
|
||||||
f'bind {key} "{togStr}"\n'
|
f'{bindOrAlias} {key} "{togStr}"\n'
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def double(key, options):
|
def double(key, options):
|
||||||
primaryAction = options["primary"]
|
primaryAction = options["primary"]
|
||||||
pBindType = firstTypeIn(primaryAction.keys())
|
|
||||||
pBindContent = primaryAction[pBindType]
|
|
||||||
|
|
||||||
secAction = options["secondary"]
|
secAction = options["secondary"]
|
||||||
sBindType = firstTypeIn(secAction.keys())
|
|
||||||
sBindContent = secAction[sBindType]
|
|
||||||
|
|
||||||
mainStr = f'{key}_main'
|
mainStr = f'{key}_main'
|
||||||
altStr = f'{key}_alt'
|
altStr = f'{key}_alt'
|
||||||
togStr = f'toggle_{key}'
|
pTogStr = f'+toggle_{key}'
|
||||||
|
mTogStr = f'-toggle_{key}'
|
||||||
|
|
||||||
recursiveCode = branch(mainStr, pBindContent, pBindType) +\
|
global bindOrAlias
|
||||||
branch(altStr, sBindContent, sBindType)
|
oldBindOrAlias = bindOrAlias
|
||||||
|
bindOrAlias = "alias"
|
||||||
|
recursiveCode = branch(mainStr, primaryAction) +\
|
||||||
|
branch(altStr, secAction)
|
||||||
|
bindOrAlias = oldBindOrAlias
|
||||||
|
|
||||||
newcode = []
|
ret = recursiveCode +\
|
||||||
for line in recursiveCode.split('\n'):
|
f'alias {pTogStr} "{bindOrAlias} {key} {altStr}"\n' +\
|
||||||
# For every line gotten by the recursive call, change all "bind"s to "alias",
|
f'alias {mTogStr} "{bindOrAlias} {key} {mainStr}"\n'+\
|
||||||
# since mainStr and altStr aren't valid bind targes
|
f'{bindOrAlias} {key} "{mainStr}"\n'
|
||||||
llist = line.split(' ')
|
|
||||||
for i in range(len(llist)):
|
|
||||||
alphanumChars = ''.join(c for c in llist[i] if c.isalnum())
|
|
||||||
if alphanumChars == 'bind':
|
|
||||||
if llist[i][0].isalnum():
|
|
||||||
llist[i] = 'alias'
|
|
||||||
else:
|
|
||||||
# If the first character isn't a normal character.
|
|
||||||
# Almost always because it is a double quote
|
|
||||||
llist[i] = llist[i][0] + 'alias'
|
|
||||||
newcode.append(' '.join(llist))
|
|
||||||
|
|
||||||
ret = '\n'.join(newcode) +\
|
|
||||||
f'alias +{togStr} "bind {key} {altStr}"\n' +\
|
|
||||||
f'alias -{togStr} "bind {key} {mainStr}"\n'+\
|
|
||||||
f'bind {key} "{mainStr}"\n'
|
|
||||||
|
|
||||||
condName = options["condition"]
|
condName = options["condition"]
|
||||||
|
global condDict
|
||||||
if condName in condDict:
|
if condName in condDict:
|
||||||
# If the condition key (like "mouse4") already has toggles,
|
# If the condition key (like "mouse4") already has toggles,
|
||||||
# just append another toggle string (it gets encased in quotes later)
|
# just append another toggle string
|
||||||
condDict[condName]["plus_toggles"] += f"; +{togStr}"
|
plusToggles = condDict[condName]["plus_toggles"]
|
||||||
condDict[condName]["minus_toggles"] += f"; -{togStr}"
|
minusToggles = condDict[condName]["minus_toggles"]
|
||||||
|
if pTogStr not in plusToggles:
|
||||||
|
plusToggles.append(pTogStr)
|
||||||
|
minusToggles.append(mTogStr)
|
||||||
else:
|
else:
|
||||||
# If the condition key doesn't already exist, make it with the correct values
|
# If the condition key doesn't already exist, make it
|
||||||
condDict.update( {
|
condDict.update( {
|
||||||
condName: {
|
condName: {
|
||||||
"plus_toggles": f"+{togStr}",
|
"plus_toggles": [ pTogStr ],
|
||||||
"minus_toggles": f"-{togStr}"
|
"minus_toggles": [ mTogStr ]
|
||||||
}
|
}
|
||||||
} )
|
} )
|
||||||
|
|
||||||
|
|
|
@ -3,18 +3,22 @@ def verifyConfig(cfg: dict) -> (dict, dict):
|
||||||
verifiedConfig = {}
|
verifiedConfig = {}
|
||||||
|
|
||||||
# Do defaults first
|
# Do defaults first
|
||||||
aliasErrors = []
|
errors = {}
|
||||||
|
|
||||||
defaults = None
|
defaults = None
|
||||||
|
|
||||||
if "default" in cfg:
|
if "default" in cfg:
|
||||||
defaults = cfg.pop("default")
|
defaults = cfg.pop("default")
|
||||||
|
errMessages = []
|
||||||
for key, data in defaults.items():
|
for key, data in defaults.items():
|
||||||
isAlias = ("alias" in data and data["alias"] == True)
|
isAlias = False
|
||||||
errMessages = validBind(key, data, alias = isAlias)
|
if "alias" in data:
|
||||||
if len(errMessages) > 0:
|
isAlias = data["alias"]
|
||||||
for msg in errMessages:
|
if not isinstance(isAlias, bool):
|
||||||
aliasErrors.append(f"Error in defaults: {msg}")
|
errMessages.append(f'"alias" field in "{key}" makes no sense: "{isAlias}"')
|
||||||
|
errMessages.extend(validBind(key, data, alias = isAlias) )
|
||||||
|
if len(errMessages) > 0:
|
||||||
|
errors.update( {"default": errMessages} )
|
||||||
|
|
||||||
classList = [
|
classList = [
|
||||||
"scout",
|
"scout",
|
||||||
|
@ -28,9 +32,6 @@ def verifyConfig(cfg: dict) -> (dict, dict):
|
||||||
"spy"
|
"spy"
|
||||||
]
|
]
|
||||||
|
|
||||||
errors = aliasErrors.copy()
|
|
||||||
|
|
||||||
|
|
||||||
for cclass in classList:
|
for cclass in classList:
|
||||||
classCFG = None
|
classCFG = None
|
||||||
className = cclass
|
className = cclass
|
||||||
|
@ -47,33 +48,35 @@ def verifyConfig(cfg: dict) -> (dict, dict):
|
||||||
# It may be less efficient this way, but
|
# It may be less efficient this way, but
|
||||||
# it makes for more descriptive error messages
|
# it makes for more descriptive error messages
|
||||||
continue
|
continue
|
||||||
|
errMessages = []
|
||||||
for key, data in classCFG.items():
|
for key, data in classCFG.items():
|
||||||
errMessages = []
|
|
||||||
isAlias = False
|
isAlias = False
|
||||||
if "alias" in data:
|
if "alias" in data:
|
||||||
isAlias = data["alias"]
|
isAlias = data["alias"]
|
||||||
if not isinstance(isAlias, bool):
|
if not isinstance(isAlias, bool):
|
||||||
errMessages.append(f'Key "{key}" has alias not set to true or false. Did you accidentally put it in quotes?')
|
errMessages.append(f'"alias" field in "{key}" makes no sense: "{isAlias}"')
|
||||||
errMessages.extend( validBind(key, data, alias = isAlias) )
|
errMessages.extend( validBind(key, data, alias = isAlias) )
|
||||||
if len(errMessages) > 0:
|
if len(errMessages) > 0:
|
||||||
for msg in errMessages:
|
errors.update( {className: errMessages} )
|
||||||
errors.append(f"Error in {cclass}: {msg}")
|
|
||||||
verifiedConfig.update({className: classCFG})
|
verifiedConfig.update({className: classCFG})
|
||||||
|
|
||||||
# Turn list into only strings by expanding tuples
|
# Turn list into only strings by expanding tuples
|
||||||
for i, clss in enumerate(classList):
|
for i, clss in enumerate(classList):
|
||||||
if isinstance(clss, tuple):
|
if isinstance(clss, tuple):
|
||||||
classList.insert(i+1, clss[0])
|
|
||||||
classList.insert(i+1, clss[1])
|
classList.insert(i+1, clss[1])
|
||||||
|
classList.insert(i+1, clss[0])
|
||||||
classList.pop(i)
|
classList.pop(i)
|
||||||
|
|
||||||
|
globalErrors = []
|
||||||
for remainingClass in cfg:
|
for remainingClass in cfg:
|
||||||
if remainingClass not in classList:
|
if remainingClass not in classList:
|
||||||
errors.append(f'Error in {remainingClass}: "{remainingClass}" is not a valid class')
|
globalErrors.append(f'"{remainingClass}" is not a valid class')
|
||||||
else:
|
else:
|
||||||
otherName = findTwin(remainingClass)
|
otherName = findTwin(remainingClass)
|
||||||
if otherName is not None:
|
globalErrors.append(f'Conflicting names for section: "{remainingClass}" and "{otherName}"')
|
||||||
errors.append(f'Error in {remainingClass}: conflicting names for section: "{remainingClass}" and "{otherName}"')
|
|
||||||
|
if len(globalErrors) > 0:
|
||||||
|
errors.update( {"file": globalErrors} )
|
||||||
|
|
||||||
if len(errors) > 0:
|
if len(errors) > 0:
|
||||||
verifiedConfig.update({"errors": errors})
|
verifiedConfig.update({"errors": errors})
|
||||||
|
@ -95,8 +98,8 @@ def validBind(key, data, alias = False) -> list:
|
||||||
|
|
||||||
extras = dataCopy.keys()
|
extras = dataCopy.keys()
|
||||||
if len(extras) > 0:
|
if len(extras) > 0:
|
||||||
extrasString = "\n\t".join(extras)
|
extrasString = "\n ".join(extras)
|
||||||
ret.append(f'Unused fields in "{key}":\n\t{extrasString}')
|
ret.append(f'Unused fields in "{key}":\n {extrasString}')
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
@ -108,7 +111,10 @@ validKeyList = [
|
||||||
'u', 'v', 'w', 'x', 'y', 'z',
|
'u', 'v', 'w', 'x', 'y', 'z',
|
||||||
'mouse1', 'mouse2', 'mouse3', 'mouse4', 'mouse5',
|
'mouse1', 'mouse2', 'mouse3', 'mouse4', 'mouse5',
|
||||||
'shift', 'capslock', 'ctrl', 'semicolon', 'space', 'enter',
|
'shift', 'capslock', 'ctrl', 'semicolon', 'space', 'enter',
|
||||||
'backspace'
|
'backspace',
|
||||||
|
'scrolllock', 'numlock',
|
||||||
|
'ins', 'home', 'pgup',
|
||||||
|
'del', 'end', 'pgdn'
|
||||||
]
|
]
|
||||||
|
|
||||||
def validKey(key):
|
def validKey(key):
|
||||||
|
@ -144,6 +150,7 @@ def validBindType(key, data: dict):
|
||||||
|
|
||||||
def removeRelaventFields(data, bindType):
|
def removeRelaventFields(data, bindType):
|
||||||
errMsgs = []
|
errMsgs = []
|
||||||
|
if "alias" in data: data.pop("alias")
|
||||||
# These types are simple, just the bind type and argument
|
# These types are simple, just the bind type and argument
|
||||||
if bindType in ["impulse", "toggle"]:
|
if bindType in ["impulse", "toggle"]:
|
||||||
data.pop(bindType)
|
data.pop(bindType)
|
||||||
|
|
Loading…
Reference in New Issue