added new way to format files
parent
8cd203bcb8
commit
0d64ad9b54
|
@ -4,7 +4,6 @@
|
||||||
condDict = {}
|
condDict = {}
|
||||||
defaultDict = {}
|
defaultDict = {}
|
||||||
bindOrAlias = "bind"
|
bindOrAlias = "bind"
|
||||||
from json import dumps
|
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
|
||||||
def makeCFG(cfg, default=False):
|
def makeCFG(cfg, default=False):
|
||||||
|
@ -32,12 +31,15 @@ def makeCFG(cfg, default=False):
|
||||||
|
|
||||||
# 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():
|
if condDict != defaultDict:
|
||||||
plusToggleStr = ';'.join(toggles["plus_toggles"])
|
# ==, and by extension !=, does in fact check
|
||||||
minusToggleStr = ';'.join(toggles["minus_toggles"])
|
# for dictionary equality in keys and values
|
||||||
ret += f'alias +{key}_toggles "{plusToggleStr}"\n' +\
|
for key, toggles in condDict.items():
|
||||||
f'alias -{key}_toggles "{minusToggleStr}"\n' +\
|
onCondPress = ';'.join(toggles["change_keys"])
|
||||||
f'{bindOrAlias} {key} "+{key}_toggles"\n'
|
onCondRelease = ';'.join(toggles["restore_keys"])
|
||||||
|
ret += f'alias +{key}_toggles "{onCondPress}"\n' +\
|
||||||
|
f'alias -{key}_toggles "{onCondRelease}"\n' +\
|
||||||
|
f'{bindOrAlias} {key} "+{key}_toggles"\n'
|
||||||
|
|
||||||
del condDict # free deep copy
|
del condDict # free deep copy
|
||||||
|
|
||||||
|
@ -57,6 +59,22 @@ def typeOf(dictIn):
|
||||||
return t
|
return t
|
||||||
|
|
||||||
def branch(keyName, bindContent):
|
def branch(keyName, bindContent):
|
||||||
|
""" Using the provided keyName and content, call the correct function """
|
||||||
|
|
||||||
|
"""
|
||||||
|
Terser syntax, ex.
|
||||||
|
impulse e:
|
||||||
|
<content>
|
||||||
|
instead of
|
||||||
|
e:
|
||||||
|
impulse:
|
||||||
|
<content>
|
||||||
|
"""
|
||||||
|
splitKey = keyName.split(' ', 1)
|
||||||
|
if len(splitKey) > 1:
|
||||||
|
keyName = splitKey[1]
|
||||||
|
bindContent = {splitKey[0]: bindContent}
|
||||||
|
|
||||||
bindType = typeOf(bindContent)
|
bindType = typeOf(bindContent)
|
||||||
bindContent = bindContent.pop(bindType)
|
bindContent = bindContent.pop(bindType)
|
||||||
|
|
||||||
|
@ -80,41 +98,46 @@ def branch(keyName, bindContent):
|
||||||
|
|
||||||
def impulse(key, instruction):
|
def impulse(key, instruction):
|
||||||
global bindOrAlias
|
global bindOrAlias
|
||||||
if isinstance(instruction, list):
|
if isinstance(instruction, dict):
|
||||||
instruction = ';'.join(instruction)
|
instruction = instruction["command"]
|
||||||
|
|
||||||
allInstructions = []
|
|
||||||
|
|
||||||
for indivCmd in instruction.split(';'):
|
if not isinstance(instruction, list):
|
||||||
allInstructions.append(impulseShortcuts(indivCmd))
|
instruction = instruction.split(';')
|
||||||
|
|
||||||
instruction = ';'.join(allInstructions)
|
instuction = impulseShortcuts(instruction)
|
||||||
|
instruction = ';'.join(instruction)
|
||||||
|
|
||||||
return f'{bindOrAlias} {key} "{instruction}"\n'
|
return f'{bindOrAlias} {key} "{instruction}"\n'
|
||||||
|
|
||||||
def impulseShortcuts(instruction):
|
def impulseShortcuts(instList):
|
||||||
splitCommand = instruction.split(' ')
|
for i, instruction in enumerate(instList):
|
||||||
cmd = splitCommand[0]
|
splitCmd = instruction.split(' ')
|
||||||
shortcuts = {
|
cmd = splitCmd[0]
|
||||||
"primary": "slot1",
|
restOfCmd = ' '.join(splitCmd[1:])
|
||||||
"secondary": "slot2",
|
shortcuts = {
|
||||||
"melee": "slot3"
|
"primary": "slot1",
|
||||||
}
|
"secondary": "slot2",
|
||||||
if cmd in shortcuts:
|
"melee": "slot3"
|
||||||
for sc, expansion in shortcuts.items():
|
}
|
||||||
if cmd == sc:
|
if cmd in shortcuts:
|
||||||
splitCommand[0] = expansion
|
cmd = shortcuts[cmd]
|
||||||
break
|
|
||||||
instruction = ' '.join(splitCommand)
|
|
||||||
|
|
||||||
restOfCmd = ' '.join(splitCommand[1:])
|
if cmd == "voice":
|
||||||
if cmd == "voice":
|
cmd = "voicemenu"
|
||||||
instruction = voice(restOfCmd)
|
restOfCmd = voice(restOfCmd)
|
||||||
|
|
||||||
elif cmd == "build" or cmd == "destroy":
|
elif cmd == "build" or cmd == "destroy":
|
||||||
instruction = f"{cmd} " + expandBuildings(restOfCmd)
|
restOfCmd = expandBuildings(restOfCmd)
|
||||||
|
|
||||||
return instruction
|
elif cmd == "load_itempreset" and restOfCmd.isalpha():
|
||||||
|
restOfCmd = restOfCmd.lower()
|
||||||
|
restOfCmd = ['a','b','c','d'].index(restOfCmd)
|
||||||
|
|
||||||
|
if restOfCmd != "":
|
||||||
|
cmd += ' ' + restOfCmd
|
||||||
|
instList[i] = cmd
|
||||||
|
|
||||||
|
return instList
|
||||||
|
|
||||||
def voice(keyword):
|
def voice(keyword):
|
||||||
keyword = keyword.lower()
|
keyword = keyword.lower()
|
||||||
|
@ -128,7 +151,7 @@ def voice(keyword):
|
||||||
for menu, voiceList in enumerate(allLists):
|
for menu, voiceList in enumerate(allLists):
|
||||||
for selection, shortcut in enumerate(voiceList):
|
for selection, shortcut in enumerate(voiceList):
|
||||||
if keyword == shortcut:
|
if keyword == shortcut:
|
||||||
return f'voicemenu {menu} {selection}'
|
return f'{menu} {selection}'
|
||||||
|
|
||||||
def expandBuildings(building):
|
def expandBuildings(building):
|
||||||
buildingNums = {
|
buildingNums = {
|
||||||
|
@ -151,17 +174,15 @@ def simpleHold(key, instruction):
|
||||||
|
|
||||||
def listHold(key, options):
|
def listHold(key, options):
|
||||||
global bindOrAlias
|
global bindOrAlias
|
||||||
pressStr = options["press"]
|
|
||||||
if isinstance(pressStr, list):
|
|
||||||
pressStr = ';'.join(pressStr)
|
|
||||||
|
|
||||||
releaseStr = options["release"]
|
|
||||||
if isinstance(releaseStr, list):
|
|
||||||
releaseStr = ';'.join(releaseStr)
|
|
||||||
|
|
||||||
ret = f'alias +{key}_bind "{pressStr}"\n' +\
|
oldBindOrAlias = bindOrAlias
|
||||||
f'alias -{key}_bind "{releaseStr}"\n' +\
|
bindOrAlias = 'alias'
|
||||||
f'{bindOrAlias} {key} "+{key}_bind"\n'
|
ret = impulse(f'+{key}_press', options["press"]) +\
|
||||||
|
impulse(f'-{key}_release', options["release"])
|
||||||
|
|
||||||
|
bindOrAlias = oldBindOrAlias
|
||||||
|
|
||||||
|
ret += f'{bindOrAlias} {key} "+{key}_press"\n'
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
@ -170,6 +191,8 @@ def toggle(key, instruction):
|
||||||
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}'
|
||||||
|
if instruction[0] == '+':
|
||||||
|
instruction = instruction[1:]
|
||||||
|
|
||||||
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' +\
|
||||||
|
@ -184,8 +207,8 @@ def double(key, options):
|
||||||
|
|
||||||
mainStr = f'{key}_main'
|
mainStr = f'{key}_main'
|
||||||
altStr = f'{key}_alt'
|
altStr = f'{key}_alt'
|
||||||
pTogStr = f'+toggle_{key}'
|
pShiftStr = f'+shift_{key}'
|
||||||
mTogStr = f'-toggle_{key}'
|
mShiftStr = f'-shift_{key}'
|
||||||
|
|
||||||
global bindOrAlias
|
global bindOrAlias
|
||||||
oldBindOrAlias = bindOrAlias
|
oldBindOrAlias = bindOrAlias
|
||||||
|
@ -195,28 +218,51 @@ def double(key, options):
|
||||||
bindOrAlias = oldBindOrAlias
|
bindOrAlias = oldBindOrAlias
|
||||||
|
|
||||||
ret = recursiveCode +\
|
ret = recursiveCode +\
|
||||||
f'alias {pTogStr} "{bindOrAlias} {key} {altStr}"\n' +\
|
f'alias {pShiftStr} "{bindOrAlias} {key} {altStr}"\n' +\
|
||||||
f'alias {mTogStr} "{bindOrAlias} {key} {mainStr}"\n'+\
|
f'alias {mShiftStr} "{bindOrAlias} {key} {mainStr}"\n'+\
|
||||||
f'{bindOrAlias} {key} "{mainStr}"\n'
|
f'{bindOrAlias} {key} "{mainStr}"\n'
|
||||||
|
|
||||||
|
isToggle = ("toggle" in options and options.pop("toggle") == True)
|
||||||
|
if isToggle:
|
||||||
|
toggleStr = toggle(key, pShiftStr)
|
||||||
|
|
||||||
condName = options["condition"]
|
condName = options["condition"]
|
||||||
global condDict
|
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
|
# just append another toggle string
|
||||||
plusToggles = condDict[condName]["plus_toggles"]
|
changes = condDict[condName]["change_keys"]
|
||||||
minusToggles = condDict[condName]["minus_toggles"]
|
restores = condDict[condName]["restore_keys"]
|
||||||
if pTogStr not in plusToggles:
|
|
||||||
plusToggles.append(pTogStr)
|
if isToggle:
|
||||||
minusToggles.append(mTogStr)
|
# "toggle: true" specified, add the toggle string
|
||||||
|
if toggleStr not in changes:
|
||||||
|
changes.append(toggleStr)
|
||||||
|
if pShiftStr in changes:
|
||||||
|
# If key already has normal shift, remove it
|
||||||
|
changes.remove(pShiftStr)
|
||||||
|
changes.remove(mShiftStr)
|
||||||
|
|
||||||
|
elif pShiftStr not in changes:
|
||||||
|
# not toggle, not already in changes
|
||||||
|
changes.append(pShiftStr)
|
||||||
|
restores.append(mShiftStr)
|
||||||
else:
|
else:
|
||||||
# If the condition key doesn't already exist, make it
|
# If the condition key doesn't already exist, make it
|
||||||
condDict.update( {
|
if isToggle:
|
||||||
condName: {
|
condDict.update( {
|
||||||
"plus_toggles": [ pTogStr ],
|
condName: {
|
||||||
"minus_toggles": [ mTogStr ]
|
"change_keys": [ toggleStr ],
|
||||||
}
|
"restore_keys": [ ]
|
||||||
} )
|
}
|
||||||
|
} )
|
||||||
|
else:
|
||||||
|
condDict.update( {
|
||||||
|
condName: {
|
||||||
|
"change_keys": [ pShiftStr ],
|
||||||
|
"restore_keys": [ mShiftStr ]
|
||||||
|
}
|
||||||
|
} )
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ __copyright__ = "Copyright © 2022 Nicholas Hope. See LICENSE for details."
|
||||||
|
|
||||||
# Standard libraries
|
# Standard libraries
|
||||||
from sys import stderr
|
from sys import stderr
|
||||||
from os import mkdir
|
from os import mkdir, sep as dirsep
|
||||||
from os.path import isdir, expanduser, normpath
|
from os.path import isdir, expanduser, normpath
|
||||||
import argparse
|
import argparse
|
||||||
from warnings import warn
|
from warnings import warn
|
||||||
|
@ -134,20 +134,12 @@ def main() -> int:
|
||||||
|
|
||||||
systemName = GetOSName()
|
systemName = GetOSName()
|
||||||
if args.directory is not None:
|
if args.directory is not None:
|
||||||
targetDir = normpath(args.directory)
|
targetDir = normpath(args.directory) + dirsep
|
||||||
if systemName == "Windows":
|
|
||||||
targetDir += '\\'
|
|
||||||
else:
|
|
||||||
targetDir += '/'
|
|
||||||
else:
|
else:
|
||||||
targetDir = getTargetDir(systemName)
|
targetDir = getTargetDir(systemName)
|
||||||
if targetDir is not None:
|
if targetDir is not None:
|
||||||
# Supported OS: add steamapps path
|
# Supported OS: add steamapps path
|
||||||
targetDir += normpath("/steamapps/common/Team Fortress 2/tf/cfg")
|
targetDir += normpath("/steamapps/common/Team Fortress 2/tf/cfg") + dirsep
|
||||||
if systemName == "Windows":
|
|
||||||
targetDir += '\\'
|
|
||||||
else:
|
|
||||||
targetDir += '/'
|
|
||||||
elif args.force:
|
elif args.force:
|
||||||
# Unsupported OS but -f specified
|
# Unsupported OS but -f specified
|
||||||
if args.debug:
|
if args.debug:
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
"""Verify all the things that could go wrong."""
|
"""Verify all the things that could go wrong."""
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
def verifyConfig(cfg: dict) -> (dict, dict):
|
def verifyConfig(cfg: dict) -> (dict, dict):
|
||||||
verifiedConfig = {}
|
verifiedConfig = {}
|
||||||
|
|
||||||
|
@ -76,7 +78,7 @@ def verifyConfig(cfg: dict) -> (dict, dict):
|
||||||
globalErrors.append(f'Conflicting names for section: "{remainingClass}" and "{otherName}"')
|
globalErrors.append(f'Conflicting names for section: "{remainingClass}" and "{otherName}"')
|
||||||
|
|
||||||
if len(globalErrors) > 0:
|
if len(globalErrors) > 0:
|
||||||
errors.update( {"file": globalErrors} )
|
errors.update({"file": globalErrors})
|
||||||
|
|
||||||
if len(errors) > 0:
|
if len(errors) > 0:
|
||||||
verifiedConfig.update({"errors": errors})
|
verifiedConfig.update({"errors": errors})
|
||||||
|
@ -86,15 +88,17 @@ def verifyConfig(cfg: dict) -> (dict, dict):
|
||||||
def validBind(key, data, alias = False) -> list:
|
def validBind(key, data, alias = False) -> list:
|
||||||
"""Check for valid key and valid binding"""
|
"""Check for valid key and valid binding"""
|
||||||
ret = []
|
ret = []
|
||||||
|
splitKey = key.split(' ')
|
||||||
|
if len(splitKey) > 1:
|
||||||
|
key = splitKey[1]
|
||||||
|
data = {splitKey[0]: data}
|
||||||
|
|
||||||
if (not alias and not validKey(key)):
|
if (not alias and not validKey(key)):
|
||||||
ret.append(f'Invalid key "{key}"')
|
ret.append(f'Invalid key "{key}"')
|
||||||
|
|
||||||
# The values passed to validBindType get mutilated, so a copy must be made
|
# The values passed to validBindType get mutilated, so a copy must be made
|
||||||
dataCopy = data.copy()
|
dataCopy, errMsgs = validBindType(key, data)
|
||||||
dataCopy, errMsgs = validBindType(key, dataCopy)
|
ret.extend(errMsgs)
|
||||||
if len(errMsgs) > 0:
|
|
||||||
for msg in errMsgs:
|
|
||||||
ret.append(msg)
|
|
||||||
|
|
||||||
extras = dataCopy.keys()
|
extras = dataCopy.keys()
|
||||||
if len(extras) > 0:
|
if len(extras) > 0:
|
||||||
|
@ -140,33 +144,65 @@ def validBindType(key, data: dict):
|
||||||
for potentialType in data.keys():
|
for potentialType in data.keys():
|
||||||
if potentialType in types:
|
if potentialType in types:
|
||||||
validType = True
|
validType = True
|
||||||
data, errMsgs = removeRelaventFields(data, potentialType)
|
|
||||||
break
|
break
|
||||||
|
|
||||||
if not validType:
|
if validType:
|
||||||
|
expandSpaceFields(data)
|
||||||
|
dataCopy = deepcopy(data)
|
||||||
|
dataCopy, errMsgs = removeRelaventFields(key, dataCopy, potentialType)
|
||||||
|
else:
|
||||||
errMsgs.append(f'Key "{key}" has no known bind type')
|
errMsgs.append(f'Key "{key}" has no known bind type')
|
||||||
|
|
||||||
return data, errMsgs
|
return dataCopy, errMsgs
|
||||||
|
|
||||||
def removeRelaventFields(data, bindType):
|
def expandSpaceFields(data):
|
||||||
|
keys = list(data.keys())
|
||||||
|
for field in keys:
|
||||||
|
# if you change a key of a dict, while looping
|
||||||
|
# over the dict, it causes a RuntimeError.
|
||||||
|
# Looping as list avoids this
|
||||||
|
splitField = field.split(' ', 1)
|
||||||
|
if len(splitField) > 1:
|
||||||
|
newContent = {splitField[0]: data.pop(field)}
|
||||||
|
data.update({splitField[1]: newContent})
|
||||||
|
field = splitField[1]
|
||||||
|
content = data[field]
|
||||||
|
if isinstance(content, dict):
|
||||||
|
expandSpaceFields(content)
|
||||||
|
|
||||||
|
def removeRelaventFields(key, data, bindType):
|
||||||
errMsgs = []
|
errMsgs = []
|
||||||
if "alias" in data: data.pop("alias")
|
content = data.pop(bindType)
|
||||||
# These types are simple, just the bind type and argument
|
if "alias" in data:
|
||||||
if bindType in ["impulse", "toggle"]:
|
# alias is universal
|
||||||
data.pop(bindType)
|
data.pop("alias")
|
||||||
|
|
||||||
|
if bindType == "impulse":
|
||||||
|
if isinstance(content, dict):
|
||||||
|
if "command" not in content:
|
||||||
|
errMsgs.append('impulse requires `command` argument')
|
||||||
|
else:
|
||||||
|
content.pop("command")
|
||||||
|
|
||||||
|
elif bindType == "toggle":
|
||||||
|
if isinstance(content, dict):
|
||||||
|
if "begin" not in content:
|
||||||
|
errMsgs.append("toggle requires `begin` argument")
|
||||||
|
if "end" not in content:
|
||||||
|
errMsgs.append("toggle requires `end` argument")
|
||||||
|
elif not isinstance(content, str):
|
||||||
|
errMsgs.append(f"toggle must be either single action or begin and end")
|
||||||
|
|
||||||
elif bindType == "hold":
|
elif bindType == "hold":
|
||||||
content = data.pop("hold")
|
|
||||||
if isinstance(content, dict):
|
if isinstance(content, dict):
|
||||||
if "press" not in content:
|
if "press" not in content:
|
||||||
errMsgs.append("If hold is not a single argument, it requires a `press` argument")
|
errMsgs.append("hold requires `press` argument")
|
||||||
elif "release" not in content:
|
if "release" not in content:
|
||||||
errMsgs.append("If hold is not a single argument, it requires a `release` argument")
|
errMsgs.append("hold requires `release` argument")
|
||||||
elif not isinstance(content, str):
|
elif not isinstance(content, str):
|
||||||
errMsgs.append(f"Hold must be either single action or press and release")
|
errMsgs.append(f"Hold must be either single action or press and release")
|
||||||
|
|
||||||
elif bindType == "double":
|
elif bindType == "double":
|
||||||
content = data.pop("double")
|
|
||||||
if "primary" not in content:
|
if "primary" not in content:
|
||||||
errMsgs.append("Double requires primary action")
|
errMsgs.append("Double requires primary action")
|
||||||
else:
|
else:
|
||||||
|
@ -174,28 +210,29 @@ def removeRelaventFields(data, bindType):
|
||||||
# It takes advantage of `alias = True` not verifying the key,
|
# It takes advantage of `alias = True` not verifying the key,
|
||||||
# but it isn't an alias, I'm just lazy.
|
# but it isn't an alias, I'm just lazy.
|
||||||
errMessages = validBind("primary", content["primary"], alias = True)
|
errMessages = validBind("primary", content["primary"], alias = True)
|
||||||
if len(errMessages) > 0:
|
errMsgs.extend(errMessages)
|
||||||
errMsgs += errMessages
|
|
||||||
|
|
||||||
if "secondary" not in content:
|
if "secondary" not in content:
|
||||||
errMsgs.append("Double requires secondary action")
|
errMsgs.append("Double requires secondary action")
|
||||||
else:
|
else:
|
||||||
# Same logic as above
|
# Same logic as above
|
||||||
errMessages = validBind("secondary", content["secondary"], alias = True)
|
errMessages = validBind("secondary", content["secondary"], alias = True)
|
||||||
if len(errMessages) > 0:
|
errMsgs.extend(errMessages)
|
||||||
errMsgs += errMessages
|
|
||||||
|
|
||||||
if "condition" not in content:
|
if "condition" not in content:
|
||||||
errMsgs.append("Double requires condition to toggle")
|
errMsgs.append("Double requires condition to toggle")
|
||||||
else:
|
else:
|
||||||
# Validate the toggler
|
# Validate the toggler
|
||||||
key = content["condition"]
|
condition = content["condition"]
|
||||||
if not validKey(key):
|
if not validKey(condition):
|
||||||
errMsgs.append(f'Invalid condition to toggle "{key}"')
|
errMsgs.append(f'Invalid condition to toggle "{condition}"')
|
||||||
|
|
||||||
|
if "cancel both" in content:
|
||||||
|
cancelBoth = content["cancel both"]
|
||||||
|
if not isinstance(cancelBoth, bool):
|
||||||
|
errMsgs.append(f'"cancel both" field in "{key}" makes no sense: "{cancelBoth}"')
|
||||||
|
|
||||||
elif bindType == "repeat":
|
elif bindType == "repeat":
|
||||||
content = data.pop("repeat")
|
|
||||||
|
|
||||||
unit = "s"
|
unit = "s"
|
||||||
if "unit" in content:
|
if "unit" in content:
|
||||||
# Set unit if provided
|
# Set unit if provided
|
||||||
|
|
Loading…
Reference in New Issue