为 Glyphs 编写脚本(一)

教程
作者:Rafał Buchner & Rainer Scheichelbauer
en zh

 

这是一系列 Python 教程的第一篇。无需预备知识。在这第一部分里,我们会在 “宏” 窗口中迈出最初几步。

本系列教程会带你开始学习 Python。无需预备知识。你可以花一上午读完全部内容,吃个午饭,然后下午写出你的第一个脚本,全在一天之内完成。祝你玩得开心!

宏面板

前往 “窗口” 菜单并选择 “宏面板”(Opt-Cmd-M)。你会看到这样的窗口:

上半部分供你写下 Python 代码。下半部分中,Glyphs 会对你的代码作出响应并给出结果。你可以将水平分界线拖动到你觉得舒服的位置。好,我们来给 Glyphs 一些它能够响应的东西。开始吧,在窗口的上半部分中输入这一行:

print( "Hello World!" )

大小写非常重要,所以请输入 print 而非 Print。引号为直引号 "(从字体角度而言,实际上是英寸符号),而非蝌蚪引号。 print 和直引号之间的空格可有可无,但结尾的引号必须要有。你可以使用单引号 '...' 也可以使用双引号 "..."

点击 “运行” 按钮(Cmd-回车,fn-回车,或数字小键盘上的 Enter 键),你会看到这样的内容:

字符串、整数、浮点数和对象

现在,print 命令让 Python 在结果区域输出一些内容。跟在 print 命令之后的内容会被输出。文本需要用引号括起来。程序员将其称为 “字符串”(string),与 “数值” 相对。

说到数值,你可以让 Python 输出任意运算结果。Python 会区分整数(integers)和小数(浮点数,floats),结果是整数还是浮点数会和你所输入的内容保持一致。5 除以 2 会得到 2,而 5.0 除以 2.0 会得到 2.5:

如果你多次点击 “运行”(Cmd-Return),你会看到结果区域越积越多。点击 “清除”(Cmd-K) 来清空记录。

对象

现在,我们让 Python 输出点别的东西。试试这个:

print( Glyphs )

结果不算很意外。不过 Glyphs 并非字符串,也非运算数值,而是所谓的 “对象”(object)。现在,Glyphs 是一个包含其他对象的对象。为了指代这些子对象,我们在 Glyphs 后加上句点,后接子对象名称。试试这个:

print( Glyphs.fonts )
print( Glyphs.font )

Python 会输出当前打开的多个字体,列在圆括号中(print Glyphs.fonts 的结果);再加上最前端窗口中的字体(print Glyphs.font 的结果)。如果你没有打开任何字体,你的结果会是一个空白列表(空的圆括号)以及 None

列表

打开几个字体,回到宏面板中,点击 “清除”(Cmd-K)并再次 “运行”(Cmd-Return)。将不同字体窗口放在最前面,重复运行代码,看看会发生什么。

所以,“Glyphs.fonts” 返回一个字体的列表(list)。你可以通过添加方括号数字(从 0 开始)来调用列表中的单个字体,像这样:

print( Glyphs.fonts[0] ) #打开的第一个字体,和 Glyphs.font 相同
print( Glyphs.fonts[1] ) #打开的第二个字体

哦,对了:井号 # 代表一段注释,其后面所跟的内容会被无视掉。在你的代码中插入描述性的注释是个很好的办法。如果你在几年后再来修改或调整你的脚本,你会对当初留下注释的自己深表感激,真的。

可能你已经猜到了,你可以用 Glyphs.font 作为 Glyphs.fonts[0] 的捷径。

正如你所料,字体也拥有子对象。同样,我们可以通过添加句点和对象名称来定位它们。试试这个:

print( Glyphs.font.glyphs )

要调用单个字符形,你可以在方括号中添加它的序数,或者名称。试试这个:

print( Glyphs.font.glyphs[7] )
print( Glyphs.font.glyphs["a"] )

同样,我们可以再加一个句点,后接一个字符形所包含的任何信息。试试这些:

print( Glyphs.font.glyphs["a"].name )
print( Glyphs.font.glyphs["a"].category )
print( Glyphs.font.glyphs["a"].subCategory )
print( Glyphs.font.glyphs["a"].unicode )

别忘了,你可以复制粘贴。不需要反复输入每一行。

变量

显然,用这种方式获得字符形信息效率很低。如果我们想获得 b 的同样的信息,我们必须把这 4 行里 a 都改成 b。所以我们来引入一个变量(variable):

glyphname = "b"
print( Glyphs.font.glyphs[glyphname].name )
print( Glyphs.font.glyphs[glyphname].category )
print( Glyphs.font.glyphs[glyphname].subCategory )
print( Glyphs.font.glyphs[glyphname].unicode )

如果你不想让字符形信息分行,就在每个输出行末尾添加逗号,后接 end=" "

glyphname = "b"
print( Glyphs.font.glyphs[glyphname].name, end=" " )
print( Glyphs.font.glyphs[glyphname].category, end=" " )
print( Glyphs.font.glyphs[glyphname].subCategory, end=" " )
print( Glyphs.font.glyphs[glyphname].unicode end=" " )

好了,所谓编程,就是避免反复输入所有内容。我们要让 Python 来做那些重复工作。你看到那些每行中都一样的内容了吗?我们给它们添加另一个变量,或许再加一个空行,让它看起来更清晰:

glyphname = "b"
myGlyph = Glyphs.font.glyphs[glyphname]

print( myGlyph.name, end=" " )
print( myGlyph.category, end=" " )
print( myGlyph.subCategory, end=" " )
print( myGlyph.unicode )

这样,我们每次只要改动第一行的字符形名称就行了。

循环

不过,如果说我们想要获得字体中每一个字符形的信息,该怎么办?当然了,我们可以复制粘贴整段代码一百遍,改变每个字符形名称。不过这对于非机器人而言太过枯燥,所以我们让 Python 帮我们做这个工作:

for myGlyph in Glyphs.font.glyphs:
    print( myGlyph.name, end=" " )
    print( myGlyph.category, end=" " )
    print( myGlyph.subCategory, end=" " )
    print( myGlyph.unicode )

注意所有 print 行需要缩进。你可以使用固定数目的空格或是制表符(Tab),只要这些行缩进一致即可。Python 对于你如何缩进非常挑剔,所以决定一种风格并保持。我喜欢制表符,所以在下面的例子中我会沿用这种方式。

Python 会遍历所有字符形,每次输出一行信息。嘿!这差不多就是这篇教程里的第一个有点实际用处的结果了。比如说,我们可以把这个结果复制粘贴进一封 email 中,作为一篇状态报告。我们再来灵活处理一下,只保留一个 print,其他都删掉,把我们的代码精简到两行:

for myGlyph in Glyphs.font.glyphs:
    print( myGlyph.name, myGlyph.category, myGlyph.subCategory, myGlyph.unicode )

现在,我们想要获得所有打开字体的字符形信息报告。幸运的是,我们可以叠加缩进。这个怎么样:

for myFont in Glyphs.fonts:
    print()
    print( "Report for:", myFont.familyName )
    for myGlyph in myFont.glyphs:
        print( myGlyph.name, myGlyph.category, myGlyph.subCategory, myGlyph.unicode )

想要你的报告里包含其他信息?前往 Glyphs Python 文档 看看字符形对象(‘GSGlyph’)和字体对象(‘GSFont’)还能为你做些什么。

下一部分中,我们会稍微深入了解一下 GSGlyph 对象,并一路钻下去直到节点。


2014-10-04 更新:添加 Glyphs.font 捷径,以及前往第二部分的链接。
2015-07-30 更新:更新 Glyphs 2 截图。
2016-12-08 更新:更新截图、修正格式,将 Glyphs.currentDocument 改为 Glyphs.font。
2016-12-09 更新:添加第一段。
2020-12-02 更新:升级到 Python 3。

Chinese translation by Willie Liu (刘育黎) from 3type (三言).