在我之前的文章《通过这个温度转换脚本学习 Perl》中,我带领读者学习了一个 Perl 脚本。当我第一次开始使用 Scribus——一个用于创建 PDF 以进行印刷或在线出版的桌面出版 (DTP) 应用程序时,Perl 是我最熟悉的脚本语言,我甚至尝试将其与 Scribus 一起使用。我曾经制作过一个 Perl 脚本,可以从头开始生成 Scribus 格式 (SLA) 的文件。虽然这当然是可行的,但实际上并没有太大的实用价值。
Scribus 包含一个名为 Scripter 的插件,它允许使用许多内部 Python 命令在 Scribus 中执行各种分析、创意和编辑操作,以及使用 Python 提供的所有其他功能。正如我在关于 Perl 入门的文章中倡导的那样,我首先查看了 Python 附带的各种脚本,来回参考各种资料,并制作了各种用于 Scribus 之外的脚本。如果你无法在 Scribus 之外以某种方式使基本算法工作,那么它肯定无法在 Scribus 内部工作。
让我们从一个基本的实用程序开始,我们可能会设想稍后在 DTP 环境中使用它。这是一个名为 date.py 的简单脚本
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from datetime import date
today = date.today()
d = today.strftime("%A, %d %B %Y")
print d
在顶部,我们有 she-bang 行(与 Perl 一样,#),但这里有点不同的风格,使用 /usr/bin/env
来查找当前的系统 Python 解释器。接下来不是绝对必要的,因为 UTF-8 是大多数 Linux 系统上的默认字符编码,但它确实突出了我第一次修改从 Windows 机器复制的这个脚本时遇到的问题。当我尝试运行它时,我一直收到错误,说它找不到 /usr/bin/env python^M
。最终我弄清楚文件的编码(就像在 Windows 中一样)是行尾带有回车符,尽管脚本中包含了这一行。我只需要在文件上运行 dos2unix
即可。
当我们进入可执行行时,请注意在 Python 中,这些行不以分号结尾——它们只是结束。此外,变量名不以特殊字符开头。from
和 import
是 Python 命令;datetime
和 date
是变量名。在这种特定情况下,datetime
指的是该名称的 Python 模块,而 date
指的是该模块中的特定函数。如果没有这个语句,基本的 Python 解释器将不知道该命令。稍后我们将看到这如何应用于 Scribus。
我们的下一个语句设置一个新的变量 today
,其中包含 date.today()
的收集信息。Python 在语法方面也很讲究。today
是对 date
执行的操作,其结果现在保存在变量 today
中。在某种程度上,这是我起的不幸的变量名,但同时它表明 Python 将这些视为两个独立的实体,语法结构澄清了这一点。
接下来,就像我们在 Python 中使用 sprintf
命令一样,我们为今天的日期设置了特定的输出格式:A
是星期几,d
是月份中的日期,B
是月份,Y
是年份。毫不奇怪,当我运行这个脚本时,输出是
Thursday, 13 October 2016
看到格式化中的逗号是如何传递到输出的吗?你可以查找 datetime
模块,看看你有哪些格式化选项。
作为一个独立的脚本,考虑到我可以随时从命令行运行 date
,这算是一个相当弱的脚本。现在让我们考虑一下 DTP 和 Scribus——例如,想象一下我们正在制作一份时事通讯或其他定期文档,我们希望在其中包含出版日期,可能在页眉中。从概念上讲,你只需运行这个小脚本,就完成了。只是我们在 DTP 中需要关注许多设计问题。
桌面出版和页面设计
在像 Scribus 这样的 DTP 程序中,默认情况下你没有任何东西可以使用。在你创建文档或打开已保存的文档之前,你没有文档。当你打开一个新文档时,默认情况下它只有一个页面,并且在你告诉它之前不会自动创建更多页面。此外,页面只是一个工作空间。你不会直接在页面上键入内容或插入图片;相反,你必须在框架环境中使用。框架是你可以输入文本、图像或其他图形(例如表格或图表)的空间,但这些是唯一的——你不能在图像框架中输入文本,反之亦然。
使用脚本,或更具体地说是在 Scribus 中的 Scripter,你也必须在这种环境中工作。我在 Scribus 中使用脚本时尝试推广的一般规则是,当图形环境是最有效的工作方式时,你应该使用图形环境,但是当你正在执行重复性、繁琐或可能很困难的任务时,你期望定期执行这些任务时,你应该使用脚本。
重复性任务示例
让我们发明一个重复性任务,以便我们可以利用我们关于 datetime
的 Python 逻辑。想象一下,我们有一份时事通讯的模板,并且在页眉中有这样的内容
从结构上看,这是一个具有特定尺寸的文本框架,以及页面上特定的 X,Y 位置,并装饰有两条宽的黑色边框。文本居中,第一行是 20 磅 Fontin Bold,第二行是 14 磅 Fontin Regular,具有自动行距,并在顶部(在 Scribus 中称为“距离”)添加了 9 磅的间距。对于我们的脚本任务,我们只想更新日期,因此我们将使用一个预先存在的文档,其中包含此框架。
我们创建脚本,打开文档,运行脚本,我们就完成了——但是等一下。Scripter 如何知道要操作哪个页面元素?与 Scripter 之外的 Scribus 一样,你必须选择当前页面上的一个项目才能开始工作(如果你不是在创建新元素)。
让我们列出一个操作列表
- 识别选定的框架。(是否选择了一个?它是文本框架吗?)
- 要么清除所有文本,要么仅清除日期。
- 创建我们要输入的新日期,并将其输入到框架中的正确位置。
- 确保使用正确的字体、字体大小和对齐方式。
这是我们最终得到的(不要让它的大小吓到你)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# gazette_date.py
try:
import scribus
except ImportError:
print "Unable to import the 'scribus' module. This script will only run within"
print "the Python interpreter embedded in Scribus. Try Script->Execute Script."
sys.exit(1)
from datetime import date
if not scribus.haveDoc():
scribus.messageBox('Scribus - Script Error', "No document open", scribus.ICON_WARNING, scribus.BUTTON_OK)
sys.exit(1)
if scribus.selectionCount() == 0:
scribus.messageBox('Scribus - Script Error',
"There is no object selected.\nPlease select a text frame and try again.",
scribus.ICON_WARNING, scribus.BUTTON_OK)
sys.exit(2)
if scribus.selectionCount() > 1:
scribus.messageBox('Scribus - Script Error',
"You have more than one object selected.\nPlease select one text frame and try again.",
scribus.ICON_WARNING, scribus.BUTTON_OK)
sys.exit(2)
textbox = scribus.getSelectedObject()
ftype = scribus.getObjectType(textbox)
if (ftype != "TextFrame"):
scribus.messageBox('Scribus - Script Error', "This is not a textframe. Try again.", scribus.ICON_WARNING, scribus.BUTTON_OK)
sys.exit(2)
today = date.today()
d = today.strftime("%A, %B %d, %Y")
length = scribus.getTextLength()
scribus.selectText(19, length-19, textbox)
scribus.deleteText(textbox)
scribus.insertText(d, -1, textbox)
length = scribus.getTextLength()
scribus.selectText(19, length-19, textbox)
scribus.setFontSize(14.0, textbox)
脚本解释
从 try:
到最后一个 sys.exit(2)
的所有内容或多或少都是错误检查样板代码,你可以轻松地从你的一个脚本复制到另一个脚本(或从别人的脚本复制)。如果你不介意你的脚本崩溃(直到你发现你没有选择对象,或者它不是文本框架等等),你可以不必放入所有这些错误检查。至少,你确实需要有 import scribus
和 from datetime import date
用于此脚本。你使用这些检查所做的事情是提供有关脚本失败原因的反馈,这始终是一件好事,即使是对你自己而言。
从 today = date.today()
开始应该看起来很熟悉。因为我们已经检查过这是一个选定的文本框架,所以我们可以对其执行 getTextLength()
。我们必须预先添加 scribus
,以便 Python 知道这是一个 Scripter 命令。我们将使用该文本长度来有选择地从框架中删除日期。我们不知道日期中将有多少个字符,但我们知道它是总数减去第一行中的数字。在 Scribus 中,selectText()
命令的字符计数从 0 开始,并且你必须计算第一行末尾隐式存在的 \n
——这就是我得出 19
作为第二行第一个字符的原因。
我以为在 insertText()
命令之后我会很幸运地完成,因为旧文本消失了,新文本都在那里,具有正确的字体并且居中——但是字体大小是 16pt。我对这个没有很好的解释,因为我在原始文件中多次尝试重新输入;不知何故,在带有换行符过渡到下一个的过程中,磅值大小发生了变化。最简单的答案是在重新检查 textLength()
并 setFontSize()
以进行修复后重新选择日期。真的不算太糟。
保存脚本后,在 Scribus 菜单中选择脚本 | 执行脚本 以查找并运行你的脚本。如果你最近运行过该脚本,它将出现在脚本 | 最近的脚本 列表中。
故障排除
这个脚本确实没有做太多事情,但应该让你了解在 Scribus 内部使用 Python 的过渡。通常,我会慢慢构建一个脚本,逐步朝着我的目标努力,直到我得到我想要的最终结果。
有时,当你完成一系列操作后,你无法弄清楚发生了什么。例如,如果耐心地计数字符不起作用怎么办?我经常使用 messageBox()
命令作为故障排除工具。在以 length
开头的任何一行之后,我们可以插入以下内容(全部在一行中)
scribus.messageBox('Length Value',
"Text length is " + str(length), scribus.ICON_NONE, scribus.BUTTON_OK)
当脚本到达这一点时,它会暂停以显示此消息,然后在你单击确定按钮后恢复。请注意,与 Perl 相比,你必须将整数 length
转换为字符串才能将其与前面的文本组合。如果你在 valueDialog()
命令中请求用户输入,则会发生相反的情况。这始终被视为字符串,因此如果你想将其用作数字,则必须使用 int()
或 float()
进行转换。
有关 Scripter 命令的文档包含在 Scribus 中,你还可以在 wiki 上找到许多 脚本 以供查看和借鉴。
评论已关闭。