Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
github-actions committed Apr 26, 2024
2 parents 9b6cb5c + 85b414a commit 4285d76
Show file tree
Hide file tree
Showing 107 changed files with 753 additions and 3,480 deletions.
134 changes: 123 additions & 11 deletions Manual/GenerateKeyboardShortcutTableFromJson.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,34 @@
###
### Provide the full directory path to the .json files as the command line argument.
### The output HTML file will also be placed there.
### For example: CMD > python GenerateKeyboardShortcutTableFromJson.py "C:/Users/Dev/Documents/Manual/" -name_as_desc
### For example: CMD > python GenerateKeyboardShortcutTableFromJson.py "C:/Users/Dev/Documents/GitHub/ameMaker-Manual/Manual/" -name_as_desc -env beta -update_rh_vars
###
### You can provide an optional argument:
### You can provide a few optional arguments:
###
### -name_as_desc: Add this to write the hotkey's name as the description.
### -env: Provide this, followed by the environment in which you want to look for the JSON files
### (one of: "dev", "lts", "beta", "prod")
### Note: only works on Windows!
### -update_rh_vars: Add this to update the RoboHelp variables
### A RH variable is written (or updated if exists) for every Win/Mac shortcut
### For example: Hotkey_Create_Asset_Win, Hotkey_Create_Asset_Mac
###
### Important: Technically, the JSON cannot contain trailing commas, this isn't supported
### using the built-in json module. Though it is supported through the yy_load function.
###

import sys
import os
import json
import re
from collections import OrderedDict

# Write to RoboHelp variables
import xml.etree.ElementTree as ET

# Unique modifier keys
mods = set()

def yy_load(file):
""" Load json from a file that possibly contains trailing commas """
# Do some tricky regex substitution
Expand All @@ -29,35 +42,75 @@ def yy_load(file):

# Utility functions
def get_combo_string(combo):
global mods
if not combo:
combo_string = ""
else:
modifier = [key for key in combo['Modifier'].split(", ") if key != "None"]
combo_string = " + ".join([*modifier, combo['Keys']])
mods.update(modifier)
if type(combo['Keys']) is list:
# This is a hotkey chord
mods = " + ".join([*modifier])
combo_string = " => ".join([mods + " + " + key for key in combo['Keys']])
else:
# This is a regular hotkey
combo_string = " + ".join([*modifier, combo['Keys']])
return combo_string

# Default names
fname_win_hotkeys = "default_hotkeys.json"
fname_mac_hotkeys = "mac_hotkeys.json"

# Whether to use the shortcut's name as the description
name_as_desc = False
install_dirs = {
"dev": "GameMaker-Dev",
"lts": "GameMaker-LTS",
"beta": "GameMaker-Beta",
"prod": "GameMaker"
}

# Handle parameters received from command line
if len(sys.argv) == 1:
print("ERROR - The input/output directory should be provided. Exiting...")
exit()
else:
fdir = sys.argv[1]
name_as_desc = (len(sys.argv) == 3 and sys.argv[2] == "-name_as_desc")
out_dir = sys.argv[1]
in_dir = out_dir

# Whether to use the shortcut's name as the description
name_as_desc = "-name_as_desc" in sys.argv

# Whether to create new and/or update existing RH hotkey variables
write_update_rh_vars = "-update_rh_vars" in sys.argv

# Use an existing GM installation to get the JSON files, if provided
env = "out_dir"
if "-env" in sys.argv:
ind = sys.argv.index("-env")
env = sys.argv[ind+1]
in_dir = os.environ['ProgramFiles'] + os.sep + install_dirs[env]
if not os.path.isdir(in_dir):
# Revert to out_dir if there's no such directory
in_dir = out_dir

# Check if directories exist
if not os.path.isdir(in_dir) or not os.path.isdir(out_dir):
print("ERROR - One or more directories don't exist. Exiting...")
exit()

# Check if files exist
fpath_win = in_dir + os.sep + fname_win_hotkeys
fpath_mac = in_dir + os.sep + fname_mac_hotkeys
if not os.path.isfile(fpath_win) or not os.path.isfile(fpath_mac):
print("ERROR - One or more files doesn't exist. Exiting...")
exit()

# Data structures
input = [] # input from file
shortcuts = dict() # maps shortcut name => shortcut data
shortcuts_per_location = OrderedDict() # stores shortcuts under locations

# First read the Windows defaults file
with open(fdir + "/" + fname_win_hotkeys, 'r', encoding="utf-8") as f:
with open(fpath_win, 'r', encoding="utf-8") as f:
# Load all the data
# input = json.load(f) # risk of errors if trailing commas are present
input = yy_load(f) # regex-replace variety that fixes things
Expand All @@ -68,7 +121,8 @@ def get_combo_string(combo):
name = shortcut['Name']

# Nothing to do for unlisted shortcuts?
if 'IsUnlisted' in shortcut:
#if 'IsUnlisted' in shortcut:
if 'IsListed' in shortcut and shortcut['IsListed'] == False:
continue

# Get this shortcut's combo(s)
Expand Down Expand Up @@ -98,7 +152,7 @@ def get_combo_string(combo):
shortcuts_per_location[location][name] = name

# Then add the combos in the macOS defaults file
with open(fdir + "/" + fname_mac_hotkeys, 'r') as f:
with open(fpath_mac, 'r') as f:
# Load all the data
input = yy_load(f)

Expand Down Expand Up @@ -139,5 +193,63 @@ def get_combo_string(combo):
html += "</table>"

# Write to file
with open(fdir + "/" + "shortcuts.htm", 'w') as f:
fpath_out = out_dir + "/" + "shortcuts.htm"
with open(fpath_out, 'w') as f:
f.write(html)

# Output unique keys
print("Shortcuts of environment " + str(env) + " written to file:")
print(fpath_out)

if not write_update_rh_vars:
print("Not writing RH variables. Exiting...")
exit()

# Optional: write to RH variables
fdir = os.getcwd() + os.sep + "variable"
fpath = fdir + os.sep + "Default.var"
tree = ET.parse(fpath)
root = tree.getroot()
vars = {}
for child in root:
# Skip title tag to avoid parsing issues
if child.tag == "title":
continue

# Reconstruct RH vars mapping
key = child.attrib["keys"]
val = child[0][0][0].text
vars[key] = val

# Update or append shortcuts
for sc in shortcuts:
readable_name = sc.replace("-", "")
readable_name = readable_name.replace("+", "And")

for platform in ["win", "mac"]:
suffix = "_" + platform.capitalize()
key_name = "Hotkey_" + readable_name.replace(" ", "_") + suffix
v = [tag for tag in root.findall('.//keydef[@keys]') if tag.attrib['keys'] == key_name]
sc_key_name = platform + '_combo'
text = ", ".join(shortcuts[sc][sc_key_name])

if v:
# The shortcut already exists!
# Update
e = v[0]
e[0][0][0].text = text
else:
# The shortcut is a new one for the RH variables.
# Create
e = ET.SubElement(root, "keydef", attrib = {"keys": key_name})
ec = ET.SubElement(e, "topicmeta")
ec2 = ET.SubElement(ec, "keywords")
ec3 = ET.SubElement(ec2, "keyword")
ec3.text = text

# Prettify XML to maintain line-by-line diffs
ET.indent(tree, space="\t")

tree.write(fpath, encoding='utf-8', xml_declaration=True)

print("RoboHelp variables updated.")
77 changes: 0 additions & 77 deletions Manual/GenerateKeyboardShortcutTableFromList.py

This file was deleted.

Loading

0 comments on commit 4285d76

Please sign in to comment.