CustomParameter scripting

How does the actual custom parameter need to be attached to the setCustomParameters_? I tried putting the CP as an argument in parenthesis and other funky stuff, but I cannot figure out how to use this particular one properly.

Let’s say I got the snippet:

thisFont = Glyphs.font

for instance in thisFont.instances:
....print instance.customParameters

and i want to add this CP:

........"Rename Glyphs" = "(\n    \"zero.lf=zero nine.lf=nine\"\n)";

BTW: is there a reason it outputs the 2 "\n", even if in the manually made CP is no linebreak at all?

You add a parameter like this:

cp = GSCustomProperty.alloc().init()

This is a setter method for the whole parameter list. You would need to supply a list of parameters to get this to work. The content of the parameter is a array and this is displayed in one line (using the \n instead of the actual line break). This has to do with the nesting of the lists

super nice, thanks! works super smoothly.

I added it to the wrapper. With the update, you then can do this:

cp = GSCustomProperty(“Test”, “Test2”)

I just hat the look at the wrapper and found that it is much easier.

Font.instances[0].customParameters[“Test”] = “Test2”

There is one catch. If there already is a “Test” property, it will be overwritten. If you need more than one parameter with the same name, you need to use .append()

Georg, that is so cool! Thanks again. Actually I was even trying to check if it’s already there. In my particular case I need it exactly as you describe: overwriting (or doing nothing).

If zhe value is not there yet, it will add a new parameter.

And how to remove a whole Custom Parameter? I am able to reset the values, but can’t find out to pop or remove the whole thing.

instance = Font.instances[0]

Nice, thanks!

  1. can I call it by its actual name? The index won’t be of any use for the thing I am working on, it gotta be dynamic and explicit.

kinda like this:

thisFont = Glyphs.font
cpName = "Rename Glyphs"
for instance in thisFont.instances:
....cp = instance.customParameters[cpName]
  1. How could I’ve found out that it is del()? dir/help() couldn’t point me to that.

3) This crashes G2 every time:

thisFont = Glyphs.font
cpName = "Rename Glyphs"
for instance in thisFont.instances:

and as opposed to your snippet, this one seems to not pass the cp (3rd line) into the arguments of del(...):

thisFont = Glyphs.font
for instance in thisFont.instances:
....cp = instance.customParameters[1]
No. As there could be more than one entry with the same name. So 'customParameters' acts as a 'list' object. del() is a standard method for list objects.


As I said, you can only access the entries by index. And you should be careful if you interacting a list and change it at the same time. Iterating backwards prevents problems.

thisFont = Glyphs.font
cpName = “Rename Glyphs”
for instance in thisFont.instances:
…for i in reversed(range(len(instance.customParameters))):
…if ((instance.customParameters[i].name == cpName:

My bad, sorry. I wasn't aware of it being treated like that. Good to know that one can work with multiple keys of the same name. Thanks, this works perfectly. We just need to add the 2 closing parenthesis like so:
if ((instance.customParameters[i].name == cpName)):

Thanks again for all your effort. Really glad to get this working.

or remove them. A habit from writing c code all the time.

yes, better without :slight_smile:

Hopefully one last thing on that. Now I encountered an interesting behavior. The script I am working on uses a delay in order to wait some seconds for the otf export and go on after this. For that i use

import time



While this works perfectly run from the macro window, when running it from a .py file file out of the scripts menu, the delay is not working. It seems to employ it immediately, displaying the beachball for 15 seconds and then run the script all at once. What’s the difference here with the macro window and the run of .py file?

here is the script in development:
GitHub dev

In G1 in works run from the script menu. In G2 it doesn’t, but it works when run from the macro window there.