lexipython/lexipython.py

192 lines
5.7 KiB
Python
Raw Permalink Normal View History

#!/usr/bin/env python3
import sys
if sys.version_info[0] < 3:
raise Exception("Lexipython requires Python 3")
import argparse
import os
2018-05-29 20:04:35 +00:00
import re
2018-05-29 21:31:12 +00:00
import json
2018-07-01 20:12:57 +00:00
from src.article import LexiconArticle
2018-07-07 04:59:09 +00:00
from src import build
from src import utils
def is_lexicon(name):
"""
2018-05-29 18:23:13 +00:00
Checks whether the given folder is a Lexicon game.
Inputs:
2018-05-29 18:23:13 +00:00
name The Lexicon name to check. Assumed to be an existing folder.
Output:
2018-05-29 21:31:12 +00:00
Returns a tuple (result, msg, status), where result is True if the
given name is a Lexicon game and False otherwise, msg is the Lexicon's
status or an error message, and status is the status dictionary of the
Lexicon or None.
"""
2018-05-29 21:31:12 +00:00
if not os.path.isfile(os.path.join("lexicon", name, "lexicon.cfg")):
return (False, "'{}' is not a Lexicon game, or its config file may be missing.".format(name), None)
if not os.path.isfile(os.path.join("lexicon", name, "status")):
return (True, "status missing", None)
with open(os.path.join("lexicon", name, "status")) as statusfile:
raw = statusfile.read()
if len(raw) == 0:
return (True, "unbuilt", {})
try:
status = json.loads(raw)
except:
return (True, "status corrupted", None)
return (True, "ye", status) # TODO
return (False, "Error checking Lexicon status", None)
def overview_all():
"""
Prints the names and statuses of all extant Lexicons,
or a short help message if none have been created yet.
"""
# Scan the directory
lexicon_names = []
with os.scandir("lexicon") as lexicons:
for entry in lexicons:
2018-05-29 18:23:13 +00:00
if entry.is_dir():
2018-05-29 21:31:12 +00:00
result, msg, status = is_lexicon(entry.name)
if result:
lexicon_names.append((entry.name, msg))
# Print the results
if len(lexicon_names) > 0:
2018-05-29 21:31:12 +00:00
l = max([len(name) for name, msg in lexicon_names]) + 4
print("Lexicons:")
2018-05-29 21:31:12 +00:00
for name, msg in sorted(lexicon_names):
print(" {}{}{}".format(name, " " * (l - len(name)), msg))
else:
print("There are no Lexicons yet. Create one with:\n\n"\
2018-07-07 19:58:55 +00:00
" lexipython.py [name] init\n")
def overview_one(name):
"""
Prints the status and summary information for the Lexicon with the
given name.
"""
# Verify the name
2018-05-29 18:23:13 +00:00
if not os.path.isdir(os.path.join("lexicon", name)):
print("Error: There is no Lexicon named '{}'.".format(name))
return
2018-05-29 21:31:12 +00:00
result, msg, status = is_lexicon(name)
if not result:
print("Error: " + msg)
2018-05-29 18:23:13 +00:00
return
# Print status and summary
2018-05-29 21:31:12 +00:00
print(msg)
print(status)
2018-05-29 18:23:13 +00:00
# TODO
def run_command(name, command):
"""
2018-05-29 18:23:13 +00:00
Runs a command on a Lexicon.
"""
if command == "init":
2018-05-29 18:23:13 +00:00
# Check that the folder isn't already there
if os.path.exists(os.path.join("lexicon", name)):
print("Error: Can't create '{}', it already exists.".format(name))
return
# Create the Lexicon
command_init(name)
return
elif command == "build":
2018-05-29 18:23:13 +00:00
if not os.path.exists(os.path.join("lexicon", name)):
print("Error: There is no Lexicon named '{}'.".format(name))
return
2018-05-29 21:31:12 +00:00
result, msg, status = is_lexicon(name)
if not result:
print("Error: " + msg)
2018-05-29 18:23:13 +00:00
return
# Build the Lexicon
command_build(name)
return
elif command == "run":
2018-05-29 18:23:13 +00:00
if not os.path.exists(os.path.join("lexicon", name)):
print("Error: There is no Lexicon named '{}'.".format(name))
return
2018-05-29 21:31:12 +00:00
result, msg, status = is_lexicon(name)
if not result:
print("Error: " + msg)
2018-05-29 18:23:13 +00:00
return
# Run a server managing the Lexicon
command_run(name)
return
else:
print("Error: '{}' is not a valid command.".format(command))
return
2018-05-29 18:23:13 +00:00
def command_init(name):
"""
Sets up a Lexicon game with the given name.
"""
2018-05-29 20:04:35 +00:00
# Create the folder structure
lex_path = os.path.join("lexicon", name)
os.mkdir(lex_path)
os.mkdir(os.path.join(lex_path, "src"))
os.mkdir(os.path.join(lex_path, "article"))
os.mkdir(os.path.join(lex_path, "contents"))
os.mkdir(os.path.join(lex_path, "formatting"))
os.mkdir(os.path.join(lex_path, "rules"))
os.mkdir(os.path.join(lex_path, "session"))
os.mkdir(os.path.join(lex_path, "statistics"))
# Open the default config file
2018-05-29 21:31:12 +00:00
config = utils.load_resource("lexicon.cfg")
2018-05-29 20:04:35 +00:00
# Edit the name field
config = re.sub("Lexicon Title", "Lexicon {}".format(name), config)
# Create the Lexicon's config file
with open(os.path.join(lex_path, "lexicon.cfg"), "w") as config_file:
config_file.write(config)
2018-10-30 17:17:54 +00:00
# Copy the CSS file
with open(os.path.join(lex_path, "lexicon.css"), "w") as css_file:
css_file.write(utils.load_resource("lexicon.css"))
2018-05-29 20:04:35 +00:00
# Create an example page
2018-05-29 21:31:12 +00:00
with open(os.path.join(lex_path, "src", "example-page.txt"), "w") as destfile:
destfile.write(utils.load_resource("example-page.txt"))
# Create an empty status file
open(os.path.join(lex_path, "status"), "w").close()
2018-05-29 20:04:35 +00:00
print("Created Lexicon {}".format(name))
2018-07-01 20:12:57 +00:00
# Done initializing
return
2018-05-29 18:23:13 +00:00
def command_build(name):
"""
Rebuilds the browsable pages of a Lexicon.
"""
2018-07-07 19:58:55 +00:00
build.build_all("lexicon", name)
2018-05-29 18:23:13 +00:00
def command_run(name):
"""
Runs as a server managing a Lexicon.
"""
2018-07-07 19:58:55 +00:00
print("Not implemented")
2018-05-29 18:23:13 +00:00
def main():
parser = argparse.ArgumentParser(
description="Lexipython is a Python application for playing the Lexicon RPG.",
epilog="Run lexipython.py without arguments to list the extant Lexicons.\n\n"\
"Available commands:\n\n"\
" init Create a Lexicon with the provided name\n"\
" build Build the Lexicon, then exit\n"\
" run Launch a persistent server managing the Lexicon\n",
formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument("name", help="The name of the Lexicon to operate on",
nargs="?", default=None)
parser.add_argument("command", help="The operation to perform on the Lexicon",
nargs="?", default=None)
args = parser.parse_args()
# If no Lexicon as specified
if args.name is None:
overview_all()
# If no command was specified
elif args.command is None:
overview_one(args.name)
# A command was specified
else:
run_command(args.name, args.command)
if __name__ == "__main__":
2018-07-07 04:59:09 +00:00
main()