tfscript/src/tfscript/cli.py

154 lines
4.7 KiB
Python

"""
Command line module for making Team Fortress 2 macro scripts from
YAML source code.
"""
__all__ = ['parseFile']
__author__ = "Nicholas Hope <tfscript@nickhope.world"
__date__ = "26 August 2022"
__version__ = "1.0"
__copyright__ = "Copyright © 2022 Nicholas Hope. See LICENSE for details."
# Standard libraries
import sys
import os
import argparse
from tempfile import NamedTemporaryFile
import yaml
from platform import system as GetOSName, release as GetOSRelease
try:
import winreg
except ModuleNotFoundError:
# Not running on windows
pass
# Local libraries
import tfscript
from tfscript import verify
from tfscript import writing
args = {}
targetDir = ""
def parseFile(inputFile) -> (dict, dict):
"""Parse, verify, and do the conversion."""
config = yaml.safe_load(inputFile)
# See verify.py
config, aliases = verify.verifyConfig(config)
if "errors" in config:
for e in config["errors"]:
print(e, file=sys.stderr)
return None, None
else:
return config, aliases
def parseConfig(config, defaults):
"""With validated data structure, write out all the files."""
global args
global targetDir
if os.path.isdir(targetDir) == False:
os.mkdir(targetDir)
if args.debug:
print( f"DEBUG: Created directory {targetDir}", file=sys.stderr)
tempsAndReals = {}
if defaults is not None:
stringToWrite = tfscript.makeCFG(defaults)
replaceDict = writing.writeOutput(stringToWrite, "default", args)
tempsAndReals.update(replaceDict)
for currentClass in config:
classDict = config[currentClass]
stringToWrite = tfscript.makeCFG(classDict)
replaceDict = writing.writeOutput(stringToWrite, currentClass, args)
tempsAndReals.update(replaceDict)
return tempsAndReals
def parseCLI():
# Handle command line
parser = argparse.ArgumentParser(
description="Parse YAML file and produce TF2 config script."
)
parser.add_argument( '-d', '--debug', action='store_true',
help="Enable debugging messages.")
parser.add_argument( '-n', '--dry-run', action='store_true',
help="Parse input file, but don't write anything.")
parser.add_argument( '-f', '--force', action='store_true',
help="Force tfscript to continue until catastrophic failure")
parser.add_argument( '-D', '--directory', action='store', type=str,
help="Change output directory")
# positional argument: first non-hyphenated argument is input file
parser.add_argument( 'infile', type=argparse.FileType('r'),
help='File containing YAML to convert.')
return parser
def getTargetDir(systemName):
if systemName == "Darwin":
if float( '.'.join( GetOSRelease().split('.')[0:2] ) ) >= 10.15:
if not args.force:
print(
"As of macOS Catalina (v10.15), 32-bit applications "
"such as tf2 do not work, so tfscript does not function",
file=sys.stderr
)
else:
return os.path.expanduser("~/Library/Application Support/Steam/")
elif systemName == "Windows":
# oh god why do we have to use the registry
accessReg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
accessKey = winreg.OpenKey(accessReg, "SOFTWARE\\WOW6432Node\\Valve\\Steam\\")
return winreg.QueryValue(accessKey, "InstallPath")
elif systemName == "Linux":
return os.path.expanduser("~/.local/Steam")
elif systemName == "Java":
print("Java-based OSes are not supported yet by tfscript.", file=sys.stderr)
return None
def main() -> int:
""" Command line interface. """
global args
global targetDir
parser = parseCLI()
args = parser.parse_args()
if args.directory is not None:
targetDir = args.directory
else:
systemName = GetOSName()
targetDir = getTargetDir(systemName)
if targetDir is not None:
# Supported OS: add steamapps path
if targetDir[-1] != '/':
targetDir += '/'
targetDir += "steamapps/common/Team Fortress 2/tf/cfg"
elif args.force:
# Unsupported OS but -f specified
if args.debug:
print("DEBUG: forced to continue, output set to current directory", file=sys.stderr)
targetDir = '.'
else:
# Unsupported OS and not forced to continue
return 2
config, defaults = parseFile(args.infile)
if config is None:
return 2
fileNames = parseConfig(config, defaults)
fileList = writing.replaceFiles(targetDir, fileNames, args)
# writing.appendToActuals(targetDir, fileList)
return 0
if __name__ == "__main__":
exit(main())