arara
自从我上次更新我的 LaTeX 副本以来,编写规则的语法似乎已经发生了变化。
在我的旧电脑上,以下规则按预期工作:
!config
# open rule for arara
# author: A.Ellett
# requires arara 3.0+
identifier: open
name: PREVIEW
commands:
- <arara> @{isTrue ( isFile ("./.design/open.pdf.true"),
"open -a /Applications/Skim.app ".concat(getBasename(file)).concat('".pdf"')
""
)}
arguments: []
但在新电脑上我收到以下错误消息:
I have spotted an error in rule "open" located at
"/Users/..../arara/rules/open.yaml". I could
not parse the rule, something bad happened. This part is quite
tricky, since it involves aspects of the underlying data
serialization format. I will do my best to help you in any way I
can. There are more details available on this exception:
DETAILS ---------------------------------------------------------
com.charleskorn.kaml.IncorrectTypeException at commands[0] on
line 8, column 5: Expected an object, but got a scalar value
我不懂这啥意思。
我尝试过查看arara
手册,但没找到任何有用的东西。我唯一能找到的是 <arara>
不再支持提及。但这让我不知道如何重写它。
有什么建议么?
答案1
遗憾的是,我无法提供关于如何编写正确规则的速成课程,因为在非常有限的空间内需要涵盖很多内容。话虽如此,我会尝试根据您最初的规则评论各个版本中发生更改的内容,然后提供一些更新。:)
(我擅自删除了注释,以便我们可以专注于代码本身)
!config
正确,第一行必须包含对象映射元数据。
identifier: ...
name: ...
这里没有任何变化,所以我们可以开始了。
commands:
到目前为止一切顺利,这里我们有潜在的命令列表。
- <arara> @{ ...
这不再起作用,原因有二:
我们从简单条目转向实际结构(系列 4)。每个命令(或文档中称为子任务)都包含在适当的块中。此块中唯一必需的条目是实际命令,由键表示
command
。因此,而不是:- ...
它应该是:
- command: ...
<arara>
不再使用简写形式(系列 5 中已弃用,系列 6 中已删除)。相反,我们鼓励使用 YAML 的折叠样式(文档附录涵盖了此主题)。因此,不要使用:- command: <arara> @{ ...
它应该是:
command: > @{ ...
继续...
isFile(...)
这种方法不再存在(可能是 4.0 系列,记不清了)。原因是我们已经用特定的硬编码方法替换了它,这些方法为toFile(...)
我们提供了文件的实际表示。
"open -a /Applications/Skim.app ..."
该工具不再允许使用纯字符串来执行命令。原因之一是命令的字符串操作比较棘手、不稳定且容易出错。从第 4 系列开始,我们引入了 的概念Command
,它允许您以安全的方式构建命令。因此,不要使用:
"open -a /Applications/Skim.app ..."
它应该是:
getCommand("open", "-a", "/Applications/Skim.app", ... )
继续。
arguments: []
正确,无可争论。
现在我将提出更新规则的建议。我试图遵循原始规则的思路,但做了一些修改。:)
!config
identifier: open
name: Preview
没什么新鲜事。:)
authors: []
此键是可选的,但为了完整性,我喜欢添加它,即使它是空的。它可以帮助我记住规则格式。
commands:
这里也什么也没有。
- name: Open Skim
虽然这是可选的,但我发现给每个任务添加一个名称很有用。否则,如果您在工作流程中遇到问题,该工具将使用未命名的引用,这不太容易理解。:)
command: >
@{
太棒了,折叠样式。现在我们可以添加规则逻辑了。
if (exists(toFile("./.design/open.pdf.true"))) {
这里发生了三件事:
.design/open.pdf.true
从纯字符串转换为实际文件引用(使用toFile(...)
方法)。无论文件是否存在,都可以创建文件引用。我们使用一个名为的方法
exists(...)
,顾名思义,该方法返回一个逻辑值,表示该文件引用是否确实存在。请注意,可以通过exists()
从File
类中调用方法来替换此方法,因此toFile(...).exists()
在语义上是等效的。我们将逻辑测试包装在条件中,这样当测试成立时我们可以做某些事情,否则我们可以做其他事情。
继续...
base = getBasename(reference.getName()) + ".pdf";
为了便于阅读,我们创建了一个名为的局部变量,用于base
保存当前文件的基本名称(即不带扩展名的文件名)。请注意,file
不再有这个名称(我想是版本 6)。我们用一种更强大的表示法替换了它,即对当前文件的规范、绝对引用(因此得名reference
)。对于这个特定目的,只需获取文件名就足够了,因此我们调用getName()
它来获取它。
return getCommand("open", "-a", "/Applications/Skim.app", base);
}
我们使用了一种名为 的方法getCommand(...)
,正如操作名称所暗示的那样,获取Command
要执行的内容的表示。必须明确解析要提供的每个元素(命令 + 参数)(与纯字符串方法相反,纯字符串方法是猜测)。然后我们return
刚刚创建的命令。
else {
return [];
}
}
现在我们在else
分支中。如果该文件不存在,则不应执行任何操作。但是什么也不做,嗯,什么也不做,我们需要告诉工具我们想要运行...什么也不做。:)
如果您不返回任何内容,arara
则会发出抱怨。返回任何内容的一种可能方法是提供一个空列表[]
,这样工具就会明白这是一个要执行的命令的空列表。
arguments: []
这里没什么可做的,我们已经完成了。:)
完整open.yaml
规则,供参考:
!config
identifier: open
name: Preview
authors: []
commands:
- name: Open Skim
command: >
@{
if (exists(toFile("./.design/open.pdf.true"))) {
base = getBasename(reference.getName()) + ".pdf";
return getCommand("open", "-a", "/Applications/Skim.app", base);
}
else {
return [];
}
}
arguments: []
希望能帮助到你。:)