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