使用泛型函数简化导出 org-mode 链接的扩展方法
我超级喜欢 org-mode 链接。最近,我需要修改一些链接的导出方式,比如为不同的后端定义新的导出,或者对特定后端进行微调。根据链接的设置方式,这项工作可能会很困难。下面是我习惯使用的一个典型设置,其中后端不同的选项在单个函数的条件语句中处理。
我将使用一个链接来说明这里的问题。这些链接只是标记的语法糖,它们本身不做做任何其他的事情。我们从一个例子开始,在这个例子中,该链接为不同的后端(如 html 或 latex)将文本转换为斜体文本。
(defun italic-link-export (path desc backend)
(cond
((eq 'html backend)
(format "<em>%s</em>" path))
((eq 'latex backend)
(format "\textit{%s}" path))
;; fall-through case for everything else
(t
path)))
(org-link-set-parameters "italic" :export 'italic-link-export)
:export
italic-link-export
(org-export-string-as "italic:text" 'html t)
<p>
<em>text</em></p>
(org-export-string-as "italic:text" 'latex t)
textit{text}
下面是默认情况。
(require 'ox-md)
(org-export-string-as "italic:text" 'md t)
# Table of Contents
text
我在这里想指出,作为一个用户,扩展这个函数并不容易。你要么直接修改 italic-link-export 函数,要么给它提供 advise,要么给它打上猴子补丁。这些都不是太好。
我还可以以另一种方式来定义 italic-link-export,其方式是使用后端参数来从列表或散列表中检索要使用的函数,但是在这之后你必须通过两个步骤来修改其行为:定义一个后端特定的函数 /并且/ 在查找变量中注册它。当然,也可以通过派生符号来查找一个函数,例如使用 fboundp,然后使用 funcall 来执行它。像这样的:
;; a user definable function for exporting to latex
(defun italic-link-export-latex (path desc backend)
(format "\textit{%s}" path))
;; generic export function that looks up functions or defaults to
(defun italic-link-exporter (path desc backend)
"Run `italic-link-export-BACKEND' if it exists, or return path."
(let ((func (intern-soft (format "italic-link-export-%s" backend))))
(if (fboundp func)
(funcall func path desc backend)
path)))
这不太直接,但您只需要定义新函数来添加新的导出后端,或替换单个后端导出。这个方案还不错,但还有改进的空间。
I will switch to bold markup for this.
在该 评论 中,我发现了一个新的解决问题的方法,使用 elisp 中的泛型函数!
其思想是定义一个处理一般导出情况的通用函数,然后根据导出函数的签名为每个特定后端定义额外的函数。
我这里将其改为粗体标记。
(cl-defgeneric bold-link-export (path desc backend)
"Generic function to export a bold link."
path)
;; this one runs when the backend is equal to html
(cl-defmethod bold-link-export ((path t) (desc t) (backend (eql html)))
(format "<b>%s</b>" path))
;; this one runs when the backend is equal to latex
(cl-defmethod bold-link-export ((path t) (desc t) (backend (eql latex)))
(format "\textit{%s}" path))
(org-link-set-parameters "bold" :export 'bold-link-export)
:export
bold-link-export
它是这样用的:
(org-export-string-as "some bold:text" 'html t)
<p>some <b>text</b></p>
(org-export-string-as "some bold:text" 'latex t)
这里使用了通用函数。
(require 'ox-md)
(org-export-string-as "some bold:text" 'md t)
# Table of Contents
some text
定义泛型函数的语法与常规函数非常相似。但具体的方法略有不同,因为它们必须提供触发每个方法的特定 签名。这里我们只区分后台参数的类型。这些后端处理函数都是单独的真是太好了。在我看来,添加新功能很简单,替换起来也不太麻烦。
泛型函数有许多其他潜在的应用,可以替换使用大量条件来控制流的函数,并在最后提供一个跳转选项。您可以在这里了解更多关于它们的信息: https://www.gnu.org/software/emacs/manual/html_node/elisp/Generic-Functions.html 。它们能提供的信息比我在这里所描述的要多得多
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论