如何动态设置org-download-image-dir,其中包含buffer文件名?

org

#1

比如我的org文件路径是 ~/.../bar/foo.org,我想存储图片到 bar/source/image/foo

求教一个org-download的问题 - Org-mode - Emacs China

这里是一个相关问题,但是解决方法是在每一个 org 文件头部放置 # -*- eval: (setq org-download-image-dir (file-name-sans-extension (buffer-name))); -*-

这个方法有点麻烦,如何一次性设置呢?

(setq-default
 org-download-image-dir (concat "./source/img/" (file-name-nondirectory (buffer-file-name)))
)

如果能设置变量为一个表达式,实时进行 eval 解释 (file-name-nondirectory (buffer-file-name)) 就好了,但似乎无法实现。。

下面是我的配置,问题是所有的 buffer org-download-image-dir 值都是一样的,在初始化的时候就变成固定值了。

  (setq-default org-download-heading-lvl nil
                org-download-image-dir (concat "./source/img/" (file-name-nondirectory (buffer-file-name)))
                org-download-screenshot-method "pngpaste %s"
                org-download-screenshot-file (expand-file-name "screenshot.jpg" temporary-file-directory))

#2

想到一个比较Hack的方法,给 org-download--dir 方法写advice。


#3

感谢帮助。看来没有办法给变量赋一个表达式了:joy:。

贴上最终我的解决方案,可以实现需求。

  (defun my-org-download--dir-1 ()
    (or org-download-image-dir (concat "./source/img/" (file-name-nondirectory (file-name-sans-extension (buffer-file-name))) )))

  (advice-add #'org-download--dir-1 :override #'my-org-download--dir-1)

但有一点烦人:图片上会有一个 header:

#+DOWNLOADED: /var/folders/mh/mphsxstx16v6wcfdlv7fymf40000gn/T/screenshot.png @ 2019-09-22 14:53:54


#4

每次进入org buffer时更新这个变量

(add-hook 'org-mode-hook
          (lambda ()
            (setq-local (concat "./source/img/" (file-name-nondirectory
                                           (buffer-file-name))))))

显然,变量只是个存放值的地方,并不能每次给你重新算出值来


#5

谢谢,又学到一招:smile:


#6

理论上还是建议你用file local variable。这样比较portable。另外file local variable除了elisp的lexical-binding其实是可以用下面的格式写在结尾的

Local Variables:
mode: emacs-lisp
eval: (message "Hello!")
End:

另外还有对目录和子目录生效的directory local variable https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html