如何定义Arara
使用通配符删除的规则?以下应删除 LaTeX 文件夹内的所有日志文件。
%!TEX TS-program = Arara
% arara: pdflatex: { synctex: yes }
% arara: cleanwildcard: { files: [*.log]}
\documentclass{minimal}
\begin{document}
Hello World!
\end{document}
答案1
吸血鬼的希望,你吸进我的血液。
(《神曲》,但丁·阿利吉耶里)
是时候给出我有史以来最疯狂的答案了。:)
你说得对,它arara
不允许使用通配符,而这样做的原因是底层执行库的限制。通配符的使用可能被理解为某种子 shell 扩展,并且没有办法(直接)询问arara
它的内部机制来使命令工作rm *.log
。就我个人而言,我倾向于更宽容的执行层,但到目前为止,当前的执行库(即Apache Commons Exec) 在一般情况下有效。当尝试解析带有空格的命令参数时,库中实际上存在一个错误(Nicola 和我追踪了错误并发现这是一个已经众所周知的错误 - 我正在密切关注他们的错误跟踪器),但库本身在大多数情况下运行良好。将来,我可能会编写自己的执行层,但现在时间有问题。:)
用户arara
群的增长速度超出了我的预期,人们正在使用该工具执行我从未想象过的任务。例如,我从未想过我会需要某种FileSystem
辅助方法,但显然这对规则制定者来说是一个很好的补充。
现在回到你的问题。:)
简短回答:不,不可能arara
在任务执行上下文中要求执行通配符扩展。
长答案:正如序言中提到的,底层执行库不允许这样做,因为它是一种子 shell 扩展,而子 shell(粗略地说,调用中的调用)是绝对禁止的。
疯狂的答案:我可以让它发挥作用。这是人类有史以来最狡猾的方法。方法如下。请注意,以下几行可能会变得非常复杂。
在规则上下文中,我们有 orb 标签,允许解释底层表达式语言。我可以利用此功能来运行 Java API 中的任意方法,以执行我想要的任务。问题是,表达式语言有很多限制,我无法以我想要的方式注入代码。
解决这些限制的一种方法是提供一个方法链,在评估上下文中返回一组有效元素。更准确地说,arara
利用一些有趣的库,如果我知道它们的完整命名空间,我就可以使用它们的方法。
遗憾的是,有一个大问题:arara
没有 IO 库(至少是3.0
CTAN 版本)。然后我们需要创造一些奇迹。
免责声明:为了使这个答案有效,我们不能单独使用 CTAN(或安装程序)版本,因此需要某种新的批处理命令来包装整行(至少为了方便)。我将在这里本地执行操作。
我将使用Apache Commons IO库用于此技巧。链接将解析为名为的文件commons-io-2.4-bin.zip
。我们只需要整个包中的一个文件:commons-io-2.4.jar
arara
不同于通常的跑步方式
$ java -jar arara
是
$ java -cp arara.jar com.github.arara.Arara
其中我们根据类路径查找提供应用程序的主类。现在,我将通过执行以下操作将 Commons IO 设为应用程序类路径的一部分:
$ java -cp commons-io-2.4.jar:arara.jar com.github.arara.Arara
如果我没记错的话,Linux 中的路径分隔符是:
,但在 Windows 中是;
,因此您的情况可能会有所不同。请注意,我考虑将两个.jar
文件放在同一个目录中;写出完整路径可能是一个好主意,或者,如果您愿意,您可以将两者添加到CLASSPATH
用户/系统环境变量中的变量中,这样查找就会变得更容易。无论如何。
现在我注入了一个 IO 库,让我们编写一条规则:
!config
identifier: cleanpattern
name: CleanPattern
command: <arara> @{remove} @{pattern}
arguments:
- identifier: remove
default: <arara> @{isWindows("cmd /c del", "rm -f")}
- identifier: pattern
flag: "@{'\"'.concat(org.apache.commons.lang3.StringUtils.join(org.apache.commons.io.FileUtils.listFiles(new java.io.File(\".\"), new org.apache.commons.io.filefilter.WildcardFileFilter(parameters.pattern), org.apache.commons.io.filefilter.FalseFileFilter.INSTANCE), \"\\\" \\\"\")).concat('\"').replaceAll(\"\\\"\\\\.\".concat(java.io.File.separator), \"\\\"\")}"
很漂亮,不是吗?:)
而且它还没有经过测试,哇哦!我没有在 Windows 上尝试过,所以让我们看看情况是否很快就会变得很糟糕。:P
此规则将 Java 代码注入表达式语言上下文中,它的作用是:
- 列出当前目录中与特定模式匹配的所有文件(由
parameters.pattern
您在指令中设置) - 将文件名列表以 分隔的大字符串形式连接起来
" "
。 - 应用正则表达式删除前导点和分隔符(操作系统的内容)。
- 以 形式返回与提供的模式匹配的文件列表
"a" "b" "c"
。
长话短说:我做了通配符扩展,而不是要求arara
这样做(反正它也不会这样做)。这很可怕,而且容易出错,但嘿,这很有趣!:)
是时候测试一下了!:)
paulo@alexandria sandbox$ touch aaa.xml bbb.xml ccc.xml
paulo@alexandria sandbox$ cat test.tex
% arara: cleanpattern: { pattern: '*.xml' }
paulo@alexandria sandbox$ java -cp commons-io-2.4.jar:arara.jar com.github.arara.Arara test.tex
__ _ _ __ __ _ _ __ __ _
/ _` | '__/ _` | '__/ _` |
| (_| | | | (_| | | | (_| |
\__,_|_| \__,_|_| \__,_|
Running CleanPattern... SUCCESS
paulo@alexandria sandbox$ ls
arara.jar commons-io-2.4.jar test.tex
它甚至适用于模式:
paulo@alexandria sandbox$ touch aaa.xml bbb.xml ccc.xml
paulo@alexandria sandbox$ cat test.tex
% arara: cleanpattern: { pattern: 'a*.xml' }
paulo@alexandria sandbox$ java -cp commons-io-2.4.jar:arara.jar com.github.arara.Arara test.tex
__ _ _ __ __ _ _ __ __ _
/ _` | '__/ _` | '__/ _` |
| (_| | | | (_| | | | (_| |
\__,_|_| \__,_|_| \__,_|
Running CleanPattern... SUCCESS
paulo@alexandria sandbox$ ls
arara.jar bbb.xml ccc.xml commons-io-2.4.jar test.tex
然而,有一个问题。这是设计问题。
对于版本3.0
,规则扩展发生在所有规则执行之前(值得注意的是,我想在以后的版本中改变这种行为)。所以,如果你有
% arara: pdftex
% arara: cleanpattern: { pattern: '*.log' }
Hello world.
\bye
运行后arara hello.tex
,您将得到hello.tex
,hello.pdf
和hello.log
!为什么?让我们看看arara
在这种情况下会发生什么:
- 该工具在源文件中找到两个指令。
- 它扩展了
pdftex
规则,使其变为pdftex hello.tex
。 - 它扩展了
cleanpattern
规则,rm -rf
因为目前还没有hello.log
!毕竟,这条规则依赖于前者。
恐怕我对此无能为力。抱歉。:(
至少在当前版本中是3.0
这样。我正在努力改变这一点。请注意,最初的决定本身并不是一个坏主意,但正如我所说,它arara
发展成为一个庞大的用户群,其中包含该工具最初没有准备涵盖的案例。
概括:可以通过(有点像黑客的)代码注入来获得通配符扩展,但由于事件发生在规则扩展而不是执行时,因此它不会处理以前的规则执行生成的最终文件依赖关系。