Script outside GlyphApp

Hey,

What is the best way to do script to .glyphs file ?
I would like to run some script without needing my glyphs file to be open in Glyphs 3.

For example :

font = Glyphs.font
for glyph in font.glyphs:
    if glyph.export == True:
        print(glyph.name)

What is the best method to run this script outside Glyphs 3 app ?

You can’t use the Glyphs 3 Python API outside Glyphs, but you can access it other ways, see this repo GlyphsSDK/Glyphs remote scripts at Glyphs3 · schriftgestalt/GlyphsSDK · GitHub

1 Like

Thanks, I checked this repo but I wondered if there wasn’t an easier way… :slight_smile:
I tried a small script using the method in the repo.

#!/usr/bin/env python
# encoding: utf-8
"""
instanceGenerate.py
Created by Georg Seifert on 2016-10-13.
Copyright (c) 2016 schriftgestaltung.de. All rights reserved.
"""

import sys, os
from Glyphs import *
from Foundation import NSURL, NSString

def TEST():

	path = "../../file.glyphs"
	doc = Glyphs.openDocumentWithContentsOfFile_display_(path, False)
	font = doc.font()
	for glyph in font.glyphs():
		print(glyph.name)

TEST()

It’ work but only if Glyphs 3 is open, do you know if it’s possible to run it without Glyphs 3 App open ?

Some of Glyphs 3 Python API are present in glyphsLib module.

from glyphsLib import GSFont, GSLayer

font = GSFont(path=".../.../file.glyphs")

exportedGlyphs = []
for glyph in font.glyphs:
    if glyph.export == True:
        exportedGlyphs.append(glyph)
print(exportedGlyphs)

You can use glyphLib but also use the remote scripting. The later requires that you open the font in Glyphs but that can be done from the script and doesn’t neet to open the UI. In the remote scripting environment, the scripting wrapper doesn’t work so you need to use the native objectiveC API. That mostly means that you have parents at properties (font.glyphs() vs font.glyphs) and some longer accessor methods (e.g. glyph.layerForId_(layerID) vs glyph.layers[layerID]).

Sorry, this is just my compulsion to always pack everything into list comprehensions, but you can write the second part of your code like this:

print([glyph for glyph in font.glyphs if glyph.export])
1 Like

I think it’s possible to remotely run a Glyphs script based on the name in the menu too, but I lost the thread that explained it

To me that would be a good compromise; you could inject a regular script into the Scripts folder, use the regular Glyphs API, run the script remotely, then remove it

That is an interesting approach. There is one downside. All output from the script shows up in the macro window and not in the context of where you run the script.
Here is a sample code if someone what’s to try:

macroViewController = Glyphs.objectWithClassName_("GSMacroViewController")
macroViewController.runMacroString_("print('hallo world')")

This has to be run as the “testExternal.py” explains.

1 Like

Nice, that works. OK, very interesting :slight_smile:

You’re right, it’s too bad we can’t get the output directly. (It looks like macroViewController.macroText is not available, but that may not mean what I guess it means). But if we can run scripts the way you just described… I wonder if variables and state persist the way they do while in the macro editor. E.g, can I run part of a script with runMacroString_ then print something to the console, then run more of the script with another call to runMacroString_, etc :thinking:

It does persist :slight_smile: Although it’s still limited (e.g., can’t print from inside a for loop)

So yes I think the challenge with this approach is logging. Regardless,runMacroString_ is a very interesting way of running the Glyphs API remotely :clap:

I played a bit with this an found a way. Soon you will be able to do:

RunScript("print(Layer)")

and you will get:

<GSLayer "Regular" (A)>
2 Likes

Exciting! Thank you!