Arara 规则使用通配符删除文件

Arara 规则使用通配符删除文件

如何定义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.0CTAN 版本)。然后我们需要创造一些奇迹。

免责声明:为了使这个答案有效,我们不能单独使用 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 代码注入表达式语言上下文中,它的作用是:

  1. 列出当前目录中与特定模式匹配的所有文件(由parameters.pattern您在指令中设置)
  2. 将文件名列表以 分隔的大字符串形式连接起来" "
  3. 应用正则表达式删除前导点和分隔符(操作系统的内容)。
  4. 以 形式返回与提供的模式匹配的文件列表"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.texhello.pdfhello.log!为什么?让我们看看arara在这种情况下会发生什么:

  1. 该工具在源文件中找到两个指令。
  2. 它扩展了pdftex规则,使其变为pdftex hello.tex
  3. 它扩展了cleanpattern规则,rm -rf因为目前还没有hello.log!毕竟,这条规则依赖于前者。

恐怕我对此无能为力。抱歉。:(至少在当前版本中是3.0这样。我正在努力改变这一点。请注意,最初的决定本身并不是一个坏主意,但正如我所说,它arara发展成为一个庞大的用户群,其中包含该工具最初没有准备涵盖的案例。

概括:可以通过(有点像黑客的)代码注入来获得通配符扩展,但由于事件发生在规则扩展而不是执行时,因此它不会处理以前的规则执行生成的最终文件依赖关系。

相关内容