Added config command, removed requirement for CLI version to have tk installed
This commit is contained in:
parent
5018edb246
commit
61843399b0
2 changed files with 57 additions and 35 deletions
|
@ -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
|
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
|
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
|
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
|
Loading a mod profile will instantly change the enabled mods to the ones that
|
||||||
were enabled when the profile was last saved.
|
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:
|
The available commands are:
|
||||||
|
|
||||||
- `list`: show a listing of all installed mods. Disabled mods appear in red.
|
- `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.
|
- `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
|
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,
|
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
|
that should be given is the name of the profile to save. If the profile already
|
||||||
exists, then it will be overwritten.
|
exists, then it will be overwritten.
|
||||||
- `load`: sets the enabled mods to those defined by the given profile.
|
- `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,
|
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
|
then bash autocompletion works for mod names - hence why it uses the ugly
|
||||||
|
|
|
@ -22,12 +22,11 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
from tkinter import *
|
|
||||||
from tkinter import ttk
|
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
PROFILE_DB = "profile_db.json"
|
PROFILE_DB = "profile_db.json"
|
||||||
HOME = os.getenv("HOME", os.getcwd()) # Use relative path in attmpt to salvage things
|
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")
|
SEVEN_DIR = os.path.join(HOME, "/.steam/steam/steamapps/common/7 Days To Die")
|
||||||
CONFIG_FILE = "seven-mods.cfg"
|
CONFIG_FILE = "seven-mods.cfg"
|
||||||
|
|
||||||
|
HELP_TEXT="""Usage: seven-mods.py <command> <args ...>
|
||||||
|
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:
|
class Config:
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
|
@ -70,21 +90,14 @@ class ModProfiles:
|
||||||
except:
|
except:
|
||||||
print("Could not save profiles.")
|
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)
|
VAL_RE = re.compile(r'\s*"([^"]*)"', re.MULTILINE)
|
||||||
DICT_START_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)
|
DICT_END_RE = re.compile(r'\s*}', re.MULTILINE)
|
||||||
|
|
||||||
class VDF_Error(RuntimeError):
|
class SevenModsError(RuntimeError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class VDF_Error(SevenModsError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def parse_vdf_val(text: str) -> tuple:
|
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")
|
ret = os.path.join(cfg.seven_dir, "Mods")
|
||||||
if not os.path.exists(ret):
|
if not os.path.exists(ret):
|
||||||
try:
|
try:
|
||||||
os.makedirs(ret)
|
os.mkdir(ret)
|
||||||
except:
|
except:
|
||||||
print(f"Could not create directory at {ret}.")
|
raise SevenModsError(f"Could not create directory at {ret}.")
|
||||||
raise
|
|
||||||
elif not os.path.isdir(ret):
|
elif not os.path.isdir(ret):
|
||||||
os.remove(ret)
|
os.remove(ret)
|
||||||
os.makedirs(ret)
|
os.makedirs(ret)
|
||||||
|
@ -184,7 +196,7 @@ def prompt_configuration_cli():
|
||||||
seven_dir = SEVEN_DIR
|
seven_dir = SEVEN_DIR
|
||||||
cfg = Config(mods_dir=mods_dir, seven_dir=seven_dir)
|
cfg = Config(mods_dir=mods_dir, seven_dir=seven_dir)
|
||||||
if not save_config(cfg):
|
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
|
return cfg
|
||||||
|
|
||||||
def save_config(cfg: Config) -> bool:
|
def save_config(cfg: Config) -> bool:
|
||||||
|
@ -192,8 +204,7 @@ def save_config(cfg: Config) -> bool:
|
||||||
with open(CONFIG_FILE, 'w') as config_file:
|
with open(CONFIG_FILE, 'w') as config_file:
|
||||||
config_file.write(f"mods_dir={cfg.mods_dir}\nseven_dir={cfg.seven_dir}\n")
|
config_file.write(f"mods_dir={cfg.mods_dir}\nseven_dir={cfg.seven_dir}\n")
|
||||||
return True
|
return True
|
||||||
except RuntimeError as e:
|
except RuntimeError:
|
||||||
print(e)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def load_config():
|
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_source = os.path.join(cfg.mods_dir, mod_name)
|
||||||
link_dest = os.path.join(get_internal_mods_path(cfg), mod_name)
|
link_dest = os.path.join(get_internal_mods_path(cfg), mod_name)
|
||||||
if not os.path.exists(link_source):
|
if not os.path.exists(link_source):
|
||||||
print(f"Could not enable {mod_name}: mod not available.")
|
raise SevenModsError(f"Could not enable {mod_name}: mod not available.")
|
||||||
return
|
|
||||||
if os.path.exists(link_dest):
|
if os.path.exists(link_dest):
|
||||||
print(f"Could not enable {mod_name}: already enabled.")
|
raise SevenModsError(f"Could not enable {mod_name}: already enabled.")
|
||||||
return
|
|
||||||
os.symlink(link_source, link_dest)
|
os.symlink(link_source, link_dest)
|
||||||
|
|
||||||
def disable_mod(cfg: Config, mod_name: str):
|
def disable_mod(cfg: Config, mod_name: str):
|
||||||
link_dest = os.path.join(get_internal_mods_path(cfg), mod_name)
|
link_dest = os.path.join(get_internal_mods_path(cfg), mod_name)
|
||||||
if not os.path.exists(link_dest):
|
if not os.path.exists(link_dest):
|
||||||
print(f"Could not disable {mod_name}: already disabled.")
|
raise SevenModsError(f"Could not disable {mod_name}: already disabled.")
|
||||||
return
|
|
||||||
os.remove(link_dest)
|
os.remove(link_dest)
|
||||||
|
|
||||||
def toggle_mod(cfg: Config, mod_name: str):
|
def toggle_mod(cfg: Config, mod_name: str):
|
||||||
|
@ -255,8 +263,7 @@ def toggle_mod(cfg: Config, mod_name: str):
|
||||||
else:
|
else:
|
||||||
link_source = os.path.join(cfg.mods_dir, mod_name)
|
link_source = os.path.join(cfg.mods_dir, mod_name)
|
||||||
if not os.path.exists(link_source):
|
if not os.path.exists(link_source):
|
||||||
print(f"Could not enable {mod_name}: mod not available.")
|
raise SevenModsError(f"Could not enable {mod_name}: mod not available.")
|
||||||
return
|
|
||||||
os.symlink(link_source, link_dest)
|
os.symlink(link_source, link_dest)
|
||||||
|
|
||||||
def command_list(args: list, cfg: Config, profiles: ModProfiles):
|
def command_list(args: list, cfg: Config, profiles: ModProfiles):
|
||||||
|
@ -274,7 +281,7 @@ def command_list(args: list, cfg: Config, profiles: ModProfiles):
|
||||||
print(profile)
|
print(profile)
|
||||||
|
|
||||||
else:
|
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):
|
def command_enable(args: list, cfg: Config, profiles: ModProfiles):
|
||||||
for mod in args[2:]:
|
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.profiles[prof] = get_loaded_mods(cfg)
|
||||||
profiles.save_mod_profiles()
|
profiles.save_mod_profiles()
|
||||||
else:
|
else:
|
||||||
print(f"Usage: python {args[0]} {args[1]} <profile-name>")
|
print(f"Usage: {args[0]} {args[1]} <profile-name>")
|
||||||
|
|
||||||
def command_load(args: list, cfg: Config, profiles: ModProfiles):
|
def command_load(args: list, cfg: Config, profiles: ModProfiles):
|
||||||
if len(args) == 3 and args[2] in profiles.profiles:
|
if len(args) == 3 and args[2] in profiles.profiles:
|
||||||
command_disable(args[:2] + ["*"], cfg, profiles)
|
command_disable(args[:2] + ["*"], cfg, profiles)
|
||||||
command_enable(args[:2] + profiles.profiles[args[2]], cfg, profiles)
|
command_enable(args[:2] + profiles.profiles[args[2]], cfg, profiles)
|
||||||
else:
|
else:
|
||||||
print(f"Usage: python {args[0]} {args[1]} <profile-name>")
|
print(f"Usage: {args[0]} {args[1]} <profile-name>")
|
||||||
|
|
||||||
|
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):
|
def parse_input(args: list, cfg: Config, profiles: ModProfiles):
|
||||||
if len(args) > 1:
|
if len(args) > 1:
|
||||||
|
@ -325,7 +338,10 @@ def parse_input(args: list, cfg: Config, profiles: ModProfiles):
|
||||||
"disable" : command_disable,
|
"disable" : command_disable,
|
||||||
"toggle" : command_toggle,
|
"toggle" : command_toggle,
|
||||||
"save" : command_save,
|
"save" : command_save,
|
||||||
"load" : command_load}
|
"load" : command_load,
|
||||||
|
"config" : command_configure,
|
||||||
|
"help" : command_help,
|
||||||
|
"--help" : command_help}
|
||||||
if args[1] in commands:
|
if args[1] in commands:
|
||||||
commands[args[1]](args, cfg, profiles)
|
commands[args[1]](args, cfg, profiles)
|
||||||
else:
|
else:
|
||||||
|
@ -337,9 +353,12 @@ def main(args):
|
||||||
cfg = load_config()
|
cfg = load_config()
|
||||||
profiles = ModProfiles()
|
profiles = ModProfiles()
|
||||||
profiles.load_mod_profiles()
|
profiles.load_mod_profiles()
|
||||||
|
try:
|
||||||
parse_input(args, cfg, profiles)
|
parse_input(args, cfg, profiles)
|
||||||
|
except SevenModsError as err:
|
||||||
|
print(err, file = sys.stderr)
|
||||||
|
return 1
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import sys
|
|
||||||
sys.exit(main(sys.argv))
|
sys.exit(main(sys.argv))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue