From 61843399b0c68c0d93d47987171366a560f2e433 Mon Sep 17 00:00:00 2001 From: Patrick Marsee Date: Sun, 22 Jan 2023 14:35:02 -0500 Subject: [PATCH] Added config command, removed requirement for CLI version to have tk installed --- README.md | 7 +++-- seven-mods.py | 85 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 57 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index a5d429e..c8ea832 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Upon first use, you will be prompted for the locations of your mods folder and seven-days also allows the user to create separate mod profiles. If, for instance, you frequent a multiplayer server with a certain set of mods, but have a different prefered set of mods for single player, then you could create -two mod profiles, called `multiplayer` and `singleplayer`, for instance. +two mod profiles, called `multiplayer` and `singleplayer`. Loading a mod profile will instantly change the enabled mods to the ones that were enabled when the profile was last saved. @@ -36,7 +36,9 @@ The main source file for the CLI version is `seven-mods.py`. General usage is: The available commands are: - `list`: show a listing of all installed mods. Disabled mods appear in red. -Enabled ones appear in green, and are followed by an asterisk (`*`). +Enabled ones appear in green, and are followed by an asterisk (`*`). `list` +also accepts an optional argument, `profiles`, which tells it to list all saved +profiles instead of mods. - `enable`: enable mods. A list of mod names can be given, separated by spaces. The mod names are the names of their respective folders, *not* the names listed in their respective `ModInfo.xml` files. Alternatively, to enable all mods, @@ -48,6 +50,7 @@ simply type `-a` rather than listing them all out. that should be given is the name of the profile to save. If the profile already exists, then it will be overwritten. - `load`: sets the enabled mods to those defined by the given profile. +- `config`: reconfigure paths to your mod and 7 Days to Die directories. Tip: If you run the script from the directory in which you store your mods, then bash autocompletion works for mod names - hence why it uses the ugly diff --git a/seven-mods.py b/seven-mods.py index 39cccba..5000aee 100755 --- a/seven-mods.py +++ b/seven-mods.py @@ -22,12 +22,11 @@ # # -from tkinter import * -from tkinter import ttk import os import os.path import json import re +import sys PROFILE_DB = "profile_db.json" HOME = os.getenv("HOME", os.getcwd()) # Use relative path in attmpt to salvage things @@ -36,6 +35,27 @@ STEAM_LIBRARIES_DIR = os.path.join(HOME, ".local/share/Steam/config/libraryfolde SEVEN_DIR = os.path.join(HOME, "/.steam/steam/steamapps/common/7 Days To Die") CONFIG_FILE = "seven-mods.cfg" +HELP_TEXT="""Usage: seven-mods.py +Valid commands are: +- help : usage guide. +- list : show a listing of all installed mods. Disabled mods appear in red. + Enabled ones appear in green, and are followed by an asterisk (`*`). + `list` also accepts an optional argument, `profiles`, which tells it + to list all saved profiles instead of mods. +- enable : enable mods. A list of mod names can be given, separated by spaces. + The mod names are the names of their respective folders, *not* the + names listed in their respective `ModInfo.xml` files. Alternatively, + to enable all mods, simply type `-a` rather than listing them all + out. +- disable : disable mods. Arguments are the same as for `enable`, including `-a` + to disable all mods. +- toggle : toggles mods on or off. Does *not* support `-a`. +- save : saves the currently enabled mods to a profile. The only argument + that should be given is the name of the profile to save. If the + profile already exists, then it will be overwritten. +- load : sets the enabled mods to those defined by the given profile. +- config : reconfigure paths to your mod and 7 Days to Die directories.""" + class Config: def __init__(self, **kwargs): @@ -70,21 +90,14 @@ class ModProfiles: except: print("Could not save profiles.") -class AppFrame(ttk.Frame): - - def __init__(self, root): - self.super(SevenDaysToMod, self).__init__(root) - self.grid(column = 0, row = 0) - self.initialize_widgets() - - def initialize_widgets(self): - pass - VAL_RE = re.compile(r'\s*"([^"]*)"', re.MULTILINE) DICT_START_RE = re.compile(r'\s*{', re.MULTILINE) DICT_END_RE = re.compile(r'\s*}', re.MULTILINE) -class VDF_Error(RuntimeError): +class SevenModsError(RuntimeError): + pass + +class VDF_Error(SevenModsError): pass def parse_vdf_val(text: str) -> tuple: @@ -165,10 +178,9 @@ def get_internal_mods_path(cfg: Config) -> str: ret = os.path.join(cfg.seven_dir, "Mods") if not os.path.exists(ret): try: - os.makedirs(ret) + os.mkdir(ret) except: - print(f"Could not create directory at {ret}.") - raise + raise SevenModsError(f"Could not create directory at {ret}.") elif not os.path.isdir(ret): os.remove(ret) os.makedirs(ret) @@ -184,7 +196,7 @@ def prompt_configuration_cli(): seven_dir = SEVEN_DIR cfg = Config(mods_dir=mods_dir, seven_dir=seven_dir) if not save_config(cfg): - print("There was a problem writing the configuration file.") + raise SevenModsError("There was a problem writing the configuration file.") return cfg def save_config(cfg: Config) -> bool: @@ -192,8 +204,7 @@ def save_config(cfg: Config) -> bool: with open(CONFIG_FILE, 'w') as config_file: config_file.write(f"mods_dir={cfg.mods_dir}\nseven_dir={cfg.seven_dir}\n") return True - except RuntimeError as e: - print(e) + except RuntimeError: return False def load_config(): @@ -234,18 +245,15 @@ def enable_mod(cfg: Config, mod_name: str): link_source = os.path.join(cfg.mods_dir, mod_name) link_dest = os.path.join(get_internal_mods_path(cfg), mod_name) if not os.path.exists(link_source): - print(f"Could not enable {mod_name}: mod not available.") - return + raise SevenModsError(f"Could not enable {mod_name}: mod not available.") if os.path.exists(link_dest): - print(f"Could not enable {mod_name}: already enabled.") - return + raise SevenModsError(f"Could not enable {mod_name}: already enabled.") os.symlink(link_source, link_dest) def disable_mod(cfg: Config, mod_name: str): link_dest = os.path.join(get_internal_mods_path(cfg), mod_name) if not os.path.exists(link_dest): - print(f"Could not disable {mod_name}: already disabled.") - return + raise SevenModsError(f"Could not disable {mod_name}: already disabled.") os.remove(link_dest) def toggle_mod(cfg: Config, mod_name: str): @@ -255,8 +263,7 @@ def toggle_mod(cfg: Config, mod_name: str): else: link_source = os.path.join(cfg.mods_dir, mod_name) if not os.path.exists(link_source): - print(f"Could not enable {mod_name}: mod not available.") - return + raise SevenModsError(f"Could not enable {mod_name}: mod not available.") os.symlink(link_source, link_dest) def command_list(args: list, cfg: Config, profiles: ModProfiles): @@ -274,7 +281,7 @@ def command_list(args: list, cfg: Config, profiles: ModProfiles): print(profile) else: - print(f"Usage: python {args[0]} {args[1]} [profiles]") + print(f"Usage: {args[0]} {args[1]} [profiles]") def command_enable(args: list, cfg: Config, profiles: ModProfiles): for mod in args[2:]: @@ -308,14 +315,20 @@ def command_save(args: list, cfg: Config, profiles: ModProfiles): profiles.profiles[prof] = get_loaded_mods(cfg) profiles.save_mod_profiles() else: - print(f"Usage: python {args[0]} {args[1]} ") + print(f"Usage: {args[0]} {args[1]} ") def command_load(args: list, cfg: Config, profiles: ModProfiles): if len(args) == 3 and args[2] in profiles.profiles: command_disable(args[:2] + ["*"], cfg, profiles) command_enable(args[:2] + profiles.profiles[args[2]], cfg, profiles) else: - print(f"Usage: python {args[0]} {args[1]} ") + print(f"Usage: {args[0]} {args[1]} ") + +def command_configure(args: list, cfg: Config, profiles: ModProfiles): + prompt_configuration_cli() + +def command_help(args: list, cfg: Config, profiles: ModProfiles): + print(HELP_TEXT) def parse_input(args: list, cfg: Config, profiles: ModProfiles): if len(args) > 1: @@ -325,7 +338,10 @@ def parse_input(args: list, cfg: Config, profiles: ModProfiles): "disable" : command_disable, "toggle" : command_toggle, "save" : command_save, - "load" : command_load} + "load" : command_load, + "config" : command_configure, + "help" : command_help, + "--help" : command_help} if args[1] in commands: commands[args[1]](args, cfg, profiles) else: @@ -337,9 +353,12 @@ def main(args): cfg = load_config() profiles = ModProfiles() profiles.load_mod_profiles() - parse_input(args, cfg, profiles) + try: + parse_input(args, cfg, profiles) + except SevenModsError as err: + print(err, file = sys.stderr) + return 1 return 0 if __name__ == '__main__': - import sys sys.exit(main(sys.argv))