M4 宏处理器(2020)

2021-07-29 22:03:11

m4 是一个宏处理器,从某种意义上说,它将其输入复制到输出,并在执行过程中扩展宏 m4 是一个核心 gnu 实用程序,默认情况下安装在大多数 *nix 系统上。事实上,我遇到的每一个人。包括 macOS。我认为自己是一个非常严肃的命令行书呆子,熟悉 sed、awk、grep、cut、sort、tr 等。但我从未听说过这个宏处理器。当我第一次遇到它时,它似乎非常神秘和晦涩。我不是 100% 第一次遇到 m4 的时间和地点。它很可能出现在 technomancy.us 的版权页中,作者吹嘘整个站点“通过 GNU M4、rsync 和 12 行 Makefile 发布”,这对我这种极简主义者来说非常有吸引力。然后我记得在去某个地方度假的途中在机场休息室用手机阅读了关于 M4 宏语言的注释,试图了解更多关于这个一直在我眼皮底下的神秘小程序的信息。后来我在 github 上找到了 apostl,一个 m4 的小包装器,目的是在你的 HTML 中轻松包含部分。这是一个让我产生共鸣的应用程序:一种零开销、无框架的 HTML 模块化方式,适合像我这样只想编写静态内容而不需要额外工具或膨胀的人。最后,我可以抽象出我的页眉、页脚和导航组件,并将它们包含在我想要的任何地方。

我想要从 m4 中删除一个 include(nav.md) 和一个 include(footer.md) 在我的降价中,并在我的工作流程中引入一点模块化。我做了一分钟,这很棒。我在 Markdown 中嵌入了可扩展的宏。我可以通过 m4 管道每个降价文件来扩展它,然后通过 pandoc 管道组装降价以创建一个 HTML 页面。除了,我忍不住觉得它可以更好。我仍然手工做很多事情,比如更新我博客的“所有帖子”页面。我偷偷地怀疑,如果我只能完全掌握这些宏的潜力,事情就会变得更加程序化。全面采用的催化剂,深入挖掘 m4 的潜力,来自我从未想过会看到的东西。我开始尝试在我的新松树上写博客。这个 arm64 系统不仅没有安装 pandoc,而且 pandoc 甚至不在软件存储库中。我考虑过自己编译它,但是它所用的语言 Haskel 甚至不能在 arm64 上编译。我以为我永远不会看到的是一台没有 pandoc 的计算机。所以我开始了从我的博客中删除所有 markdown 的道路,让自己辞去编写 HTML 的工作。我最终推翻了这个决定,因为我非常讨厌编写 HTML,然后又回到编写 Markdown 并简单地使用一个不是 pandoc 的 Markdown 到 HTML 转换器。

Pandoc 只是将 Markdown 转换为 HTML 实在是太过分了。我不需要瑞士军刀。我需要一把黄油刀。但是在删除 Markdown 和将其放回之间,我花了一个下午的时间查看 Technomancy 的 makefile 和 m4 文档,并且真正开始理解。关于丢失 pandoc,我真正错过的第一件事是在 YAML frontmatter 中设置元数据。然后内容被夹在我第一次爱上的包含之间: 如此有效的原因是——我从没想过我会听到自己这么说——因为全局状态的美丽!如果您从文档 A 中包含文档 B,则您在文档 A 中定义的任何宏都可用于文档 B。因此,在这种情况下,标题、副标题等可用于 header.html。我可以在头部设置 <title> 并在正文中放置 <h1> ,就像 pandoc 那样。

最后,我学会了更改默认的引号字符串。因为在编写充满代码块的 markdown 时,让 m4 每次遇到反引号时都试图转义字符串是行不通的。 define(__timestamp, 2020-06-17)dnldefine(__title, `m4')dnldefine(__subtitle, `一种真正的模板语言')dnldefine(__id, 9)dnlinclude(src/header.html)changequote(<!,! >)dnl 否则`代码块`混淆 m4markdown markdown markdown markdown changequote`'dnl 更改引号`返回默认值'include(src/footer.html) 现在我直接从 Technomancy 中提取了两件事:填充“所有帖子”列表,并自动填充 RSS 提要。以下是如何在 m4 中实现“倒计时”for 循环,直接来自 M4 宏语言的注释,稍作修改:粗略,对吧? m4 非常适合宏和包含。对于一般编程来说不是超级有趣。但是,就像移民一样,它可以完成工作。所以现在“所有帖子”和 rss.xml 都可以,通过在 Makefile 中定义一个“LATEST”变量(它告诉宏总共有多少文件),遍历所有文件并加载它们,转移它们的输出到一次性寄存器,但保留它们的宏定义。因此,例如,可以从每个帖子中提取标题和时间戳,并将它们吐出到所有帖子的列表中。像这样。我从 Technomancy 借来的最后一点聪明是使用 header.html 和 footer.html,根据 Makefile 传入的“__feed”宏的前置,将帖子包装在博客的 HTML 文档中,或者提要的 XML 文档。像这样。

但是当你需要实现一个 for 循环或者做很多程序化的事情时,它很快就会变得非常笨拙。很难调试。我很快发现,遇到意外情况时,我的默认行为就是增加一些东西周围的转义引号。这经常修复它。也就是说,它是一种有趣的语言,我发现学习和使用它是有益的,如果有机会,我可能会再次使用它。我对这个博客的当前写作状态非常满意。我觉得我 90% 的方式达到了我最初的“带有包含的简单降价”的愿景,而额外的 m4 并没有真正打扰我。它仍然非常干净,几乎所有的复杂性和丑陋的东西都从我写入辅助文件的地方移开了。