Skip to content

Instantly share code, notes, and snippets.

@RafalBuchner
Last active August 11, 2023 19:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RafalBuchner/3d890381f5abb2bc2a0b347077a47f72 to your computer and use it in GitHub Desktop.
Save RafalBuchner/3d890381f5abb2bc2a0b347077a47f72 to your computer and use it in GitHub Desktop.
script that creates the build.py file based on roboFontExt stored in /build directory

Readme

  1. Use build_the_build.py
  2. Put resetRoboFiont.py in the same directory as build.py
  3. use this in command line robofont -p -a path/to/your/build.py | python3 resetRoboFiont.py

resetRoboFiont.py requires installed pyobjc on your python environment. Have fun

import os
import plistlib
def createBuildTxt(path):
infoPath = os.path.join(
path,
"info.plist"
)
assert os.path.exists(infoPath), f"{os.path.basename(path)} doesn't have info.plist file!"
extResourcesPath = os.path.join(path, "resources")
extResourcesPath_doesExists = os.path.exists(extResourcesPath)
hasPngIcon = os.path.exists(
os.path.join(extResourcesPath, "icon.png")
)
infoPlistFile = open(infoPath, "rb")
infoData = plistlib.loads(infoPlistFile.read())
info_name = infoData.get("name")
info_version = infoData.get("version")
info_html = infoData.get("html")
info_launchAtStartUp = infoData.get("launchAtStartUp")
info_developer = infoData.get("developer")
info_developerURL = infoData.get("developerURL", None)
info_mainScript = infoData.get("mainScript")
info_requiresVersionMajor = infoData.get("requiresVersionMajor")
info_requiresVersionMinor = infoData.get("requiresVersionMinor")
info_expireDate = infoData.get("expireDate")
info_addToMenu = pprint.pformat(infoData.get("addToMenu"), indent=4) if infoData.get("addToMenu") is not None else None
txt = """from mojo.extensions import ExtensionBundle
import os
import AppKit
from Foundation import NSURL
import shutil
from lib.scripting.extensionBundle import applicationPluginRootPath
def forceInstall(bundle, installAfterBuild=True):
# installs extensions – no questions asked
if installAfterBuild:
print(f"Installing extension {bundle.name}...", end=" ")
installDirectory = applicationPluginRootPath
installPath = os.path.join(installDirectory, extensionFile)
if os.path.exists(installPath):
shutil.rmtree(installPath)
shutil.copytree(bundle.bundlePath(), installPath)
print(". . .")
print("done!")
"""
txt += f"__version__ = '{info_version}'" + "\n"
txt += f"__name__ = '{info_name}'" + "\n\n"
txt += "# get current folder\n"
txt += "basePath = os.path.dirname(__file__)\n\n"
txt += "# source folder for all extension files\n"
txt += "sourcePath = os.path.join(basePath, 'source')" + "\n\n"
txt += "# folder with python files\n"
txt += "libPath = os.path.join(sourcePath, 'code')" + "\n\n"
txt += "# folder with html files\n"
if info_html:
txt += "htmlPath = os.path.join(sourcePath, 'documentation')" + "\n\n"
else:
txt += "# htmlPath = os.path.join(sourcePath, 'documentation')" + "\n"
txt += "htmlPath = None" + "\n\n"
txt += "# folder with resources (icons etc)\n"
if extResourcesPath_doesExists:
txt += "resourcesPath = os.path.join(sourcePath, 'resources')" + "\n\n"
else:
txt += "# resourcesPath = os.path.join(sourcePath, 'resources')" + "\n"
txt += "resourcesPath = None" + "\n\n"
txt += "# load license text from file\n"
txt += "# see choosealicense.com for more open-source licenses\n"
txt += "licensePath = os.path.join(basePath, 'LICENSE')" + "\n\n"
txt += "# boolean indicating if only .pyc should be included\n"
txt += "pycOnly = False" + "\n\n"
txt += "# name of the compiled extension file\n"
txt += "extensionFile = f'{__name__}.roboFontExt'" + "\n\n"
txt += "# path of the compiled extension\n"
txt += "buildPath = os.path.join(basePath, 'build')\n"
txt += "extensionPath = os.path.join(buildPath, extensionFile)" + "\n\n"
##################
txt += "# initiate the extension builder\n"
txt += "B = ExtensionBundle()\n"
txt += "# name of the extension\n"
txt += "B.name = __name__\n\n"
txt += "# name of the developer\n"
txt += f"B.developer = '{info_developer}'\n\n"
txt += "# URL of the developer\n"
txt += f"B.developerURL = '{info_developerURL}'\n\n"
txt += "# extension icon (file path or NSImage)\n"
if hasPngIcon:
txt += "imagePath = os.path.join(resourcesPath, 'icon.png')\n"
txt += "B.icon = imagePath\n\n"
else:
txt += "# imagePath = os.path.join(resourcesPath, 'icon.png')\n"
txt += "# B.icon = imagePath\n\n"
txt += "# version of the extension\n"
txt += "B.version = __version__\n\n"
txt += "# should the extension be launched at start-up?\n"
txt += f"B.launchAtStartUp = {info_launchAtStartUp}\n\n"
txt += "# script to be executed when RF starts\n"
txt += f"B.mainScript = '{info_mainScript}'\n\n"
txt += "# does the extension contain html help files?\n"
txt += f"B.html = {info_html}\n\n"
txt += "# minimum RoboFont version required for this extension\n"
txt += f"B.requiresVersionMajor = '{info_requiresVersionMajor}'\n"
txt += f"B.requiresVersionMinor = '{info_requiresVersionMinor}'\n\n"
txt += "# scripts which should appear in Extensions menu\n"
txt += f"B.addToMenu = {info_addToMenu}\n\n"
txt += "# license for the extension\n"
txt += "with open(licensePath, encoding='utf-8') as license:\n"
txt += " B.license = license.read()\n\n"
txt += "# expiration date for trial extensions\n"
if info_expireDate is not None:
txt += "B.expireDate = '2019-12-31'\n\n"
else:
txt += "# B.expireDate = '2100-12-01'\n\n"
txt += "# compile and save the extension bundle\n"
txt += "print(f'building {__name__} extension...', end=' ')\n"
txt += "B.save(extensionPath, libPath=libPath, htmlPath=htmlPath, resourcesPath=resourcesPath, pycOnly=pycOnly, pycExclude=[])\n"
txt += "print('done!')\n\n"
txt += "# check for problems in the compiled extension\n"
txt += "print()\n"
txt += "print(B.validationErrors())\n"
txt += "if '' == str(B.validationErrors()):\n"
txt += " forceInstall(B)"
return txt, info_name
def main():
path = os.path.abspath("build")
assert os.path.exists(path), "no /build folder"
roboFontExtPaths = []
for f in os.listdir(path):
if os.path.splitext(f)[-1]:
roboFontExtPaths.append(
os.path.join(path, f)
)
if len(roboFontExtPaths) != 1:
raise "couldn't find one .roboFontExt file in /build folder"
build_path = os.path.abspath("build.py")
buildTxt, info_name = createBuildTxt(roboFontExtPaths[0])
txt = f"'''build <{info_name}> extension with this shell command:\n"
txt += f"robofont -p -a {build_path}\n"
txt += "\n"
txt += "'''"
txt += "\n\n\n\n"
txt += buildTxt
if os.path.exists(build_path):
os.remove(build_path)
with open('build.py', 'w') as f:
f.write(txt)
if __name__ == "__main__":
main()
import AppKit
import time
from Foundation import NSURL
def restartRoboFont():
print("closing RoboFiont")
time.sleep(1)
# restarts robofiont if opened. otherwise opens it
running_robofiont = AppKit.NSRunningApplication.runningApplicationsWithBundleIdentifier_('com.typemytype.robofont4')
if len(running_robofiont):
running_robofiont[0].forceTerminate()
time.sleep(1)
print("opening RoboFiont")
robofiont_url = NSURL.fileURLWithPath_isDirectory_('/Applications/RoboFont.app', True)
workspace = AppKit.NSWorkspace.sharedWorkspace()
workspace.launchApplicationAtURL_options_configuration_error_(robofiont_url, AppKit.NSWorkspaceLaunchDefault, {}, None)
print("done")
restartRoboFont()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment