hsingko


如何在 Org-mode 中愉快地嵌入图片

对于经常用 emacs 的 Org-mode 写文章的朋友,常常会遇到的一个困扰就是如何在 Org-mode 中嵌入图片。俗话说一图胜千言,一篇令人印象深刻的文章总是少不了精致的图片,但是 Org-mode 自带的引入图片功能实在是有够简陋,往往只能通过 [[file:<path>]] 这种非常麻烦的方式,而一旦涉及到截图就更难受了。那么有没有什么办法能让 emacer 愉快地嵌入图片呢?当然有了,万能的开源社区往往早就解决了这类常见的痛点,那就是: org-download

使用 org-download 能实现什么样的功能?

首先,当我们想要在文章中引入一张图片,我们会怎么做呢? org-download 明确地将图片的来源作出了归类:

  • 剪贴板
  • 截屏
  • 网络地址
  • 直接从文件系统拖拽到 emacs 中

而无论你要用到的图片是从哪里来的, org-download 都可以轻松做到。

那么如何才能使用 org-download ?

安装

首先自然是安装,对于 doom-emacs 用户来说,只要在 package.el 文件中加入下面一行:

(package! org-download)

或者在原生 emacs 中使用 use-package:

(use-package org-download)

配置

首先先贴上我现在在用的配置:

;;; org-download
(require 'org-download)
(setq org-download-screenshot-method "flameshot gui --raw >%s")
; (setq org-download-method 'directory)
(setq-default org-download-heading-lvl nil)
(setq-default org-download-image-dir "./images")
(defun dummy-org-download-annotate-function (link)
  "")
(setq org-download-annotate-function
      #'dummy-org-download-annotate-function)

或者用 use-package 配置:

(use-package org-download
  :config
  (setq-default org-download-heading-lvl nil)
  (setq-default org-download-image-dir "./images")
  (setq org-download-backend "wget")
  (setq org-download-abbreviate-filename-function (lambda (fn) fn)) ; use original filename
  (defun dummy-org-download-annotate-function (link)
    "")
  (setq org-download-annotate-function
      #'dummy-org-download-annotate-function)
  )

上述代码配置生效之后,你就可以愉快地使用了:先从复制图片开始,你可以从网络上随便点开一个页面,右键复制,然后在 Org 文档中执行 Alt-x org-download-clipboard ,很快,你想要的图片就被插入到文档中了。

至此,不关心配置细节的用户已经可以放心关闭这个网页去享受了,而如果你非常在意上面的配置起了什么作用,那就请继续往下滑。

  1. (setq org-download-screenshot-method "flameshot gui --raw >%s") 这一行指定了 org-download 在执行截图时会调用的系统命令,我使用的是 flameshot ,但其实无关紧要,因为你几乎不会通过 org-download 去截屏,那样也太麻烦了,更快捷的方式是直接用你喜欢的截屏工具截图,然后将图片复制,然后和上面的流程那样插入图片。所以这一行其实并非必须。如果有和我一样是使用 flameshot 的用户,那么写一下也没什么关系。

  2. 接下来是被注释掉的 ;(setq org-download-method 'directory) 。上面的文章其实隐藏了 org-download 的一个细节,那就是如何保存图片。它默认有两种方式,一种是作为附件,另一种是基于普通的文件夹。基于附件的并不常用,而且使用起来也非常别扭,因此 org-download 默认将存储为普通文件。

  3. 下面两行则设定了图片具体的保存位置。 org-download 默认有个非常别扭的行为,就是将图片保存到所在 headline 为文件夹名称的目录下,通过 (setq-default org-download-heading-lvl nil) 可以屏蔽这个行为;而后面一行则非常直观地设定了要保存的文件夹名称。另外你可能会疑惑为什么之前用的都是 setq 怎么到这里就变成 setq-default 了呢?那是因为这两个变量有 buffer 作用域和全局作用域之分,这样的好处是可以针对每不同的文件设定图片的保存路径。但是我并不需要这种功能,因此我将其全局设定。

  4. 配置的最后我自定了一个 dummy-org-download-annotate-fuction 函数,以及将对应的变量指向到这个函数中。这个函数的作用是返回一个空的字符串。为什么我要这么做你可以试试将这几行注释掉,就会发现你粘贴的图片上方多了一行莫名其妙的注释, #+DOWNLOAD... ,不知道别人怎么想,我是不需要这个功能的,因此我用自定义函数覆盖了这个特性。具体的讨论可以见这里

针对文件夹设定不同的存储路径

有时候你可能想将图片存在不同的地方。比如对于我来说, org 文件分为两类,一种是只给自己看的笔记,其中的图片统一存放在 ~/Documents/org/images/ 目录下,这样方便管理;另一种则是 hugo 博客文章,这个时候就应该将图片存放在相对目录下的 ./images/ 文件夹中。

这种情景可以利用 .dir-local 来实现。

在想要定制的目录下创建 .dir-locals.el 文件,比如 hugo 的 content/ 目录,写入如下内容:

(dir-locals-set-class-variables 'org-download-hugo-directory
	'((org-mode . ((org-download-image-dir . "./images")))))
(dir-locals-set-directory-class
 "~/Documents/Blog/content/" 'org-download-hugo-directory)

第一次使用时会出现安全提醒,按 ! 忽略之后就可以使用了,或者使用:

(setq enable-local-variables :safe)

忽略所有安全提醒。