如何在 Emacs 的组织模式下在源块的“#+RESULTS”预览输出周围添加“#+ATTR_HTML”?

How can I add "#+ATTR_HTML" around "#+RESULTS" preview output of Source Block in Org-mode of Emacs?

我在 org 中使用 plantuml,它运行良好。但是,我试图通过在 #+RESULTS 输出标签之前自动添加一些 HTML 标签来进行一些更改,这样可以获得漂亮的 HTML输出效果。

我的示例代码如下:

#+BEGIN_SRC plantuml :file test.png
@startuml

  package "Some Group" {
          HTTP - [First Component]
          [Another Component]
  }

  node "Other Groups" {
          FTP - [Second Component]
          [First Component] --> FTP
  } 

  cloud {
          [Example 1]
  }


  database "MySql" {
          folder "This is my folder" {
                  [Folder 3]
          }
          frame "Foo" {
                  [Frame 4]
          }
  }


  [Another Component] --> [Example 1]
  [Example 1] --> [Folder 3]
  [Folder 3] --> [Frame 4]

  @enduml
#+END_SRC

在 "C-c C-c" plantuml 之后,您将在 plantuml 代码块下方获得以下输出:

#+RESULTS:
[[file:test.png]]

但是,我希望它自动附加上面的#+RESULT标签如下,这将显示在plantuml源下面-在 Emacs 中阻止:

#+ATTR_HTML: :width 80% 
#+ATTR_ORG: :width 80% 
#+ATTR_HTML: :style background-color: white; border-radius: 8px; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
#+RESULTS:
[[file:test.png]]

然后,我可以通过"C-c C-e h o"将org文件输出到HTML,得到一个漂亮的HTML。

我怎样才能做到?

谢谢!

标准技术是为源块命名:

#+NAME: foo
#+BEGIN_SRC plantuml :file test.png
@startuml
...
#+END_SRC

当你评估代码块时,它会产生一个 #+RESULTS: header 像这样:

#+RESULTS: foo
[[file:test.png]]

现在您可以在结果前添加 #+ATTR_* 声明:

#+ATTR_HTML: :width 80% 
#+ATTR_ORG: :width 
#+ATTR_HTML: :style background-color: white; border-radius: 8px; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
#+RESULTS: foo
[[file:test.png]]

重新运行代码块会将文件 link 放在同一个地方,而不会留下 #+ATTR-* 的东西。然后您可以导出并获得 "beautiful HTML"!

编辑:上面的主旨是避免如果块命名则需要手动工作:你将不得不继续将属性声明移动到新生成的 #+RESULTS: 源块的每个 re-evaluation 之后的部分(并清理旧结果)。从我的 POV 来看,这是令人讨厌的部分,块的命名很好地处理了它。

属性声明的添加然后变成了一个 one-time 任务,我不是特别希望自动化,主要是因为属性对于不同的块来说必然是不同的,所以我为一个块做的任何事情块必须完全更改为另一个:我宁愿手动执行 one-time 任务。

就是说,您可以部分自动执行属性插入,例如通过创建一个函数来执行插入并将其绑定到一个键:

(defun insert-attr-decls ()
  (interactive)
  (insert "#+ATTR_HTML: :width 80%\n")
  (insert "#+ATTR_ORG: :width 80%\n") 
  (insert "#+ATTR_HTML: :style background-color: white; border-radius: 8px; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n"))

(define-key org-mode-map [f10] 'insert-attr-decls)

然后在第一次评估后,将点放在生成的 #+RESULTS: foo 行之前,然后按 F10。从我的视角来看,这是我要停下来的地方(如果我走到这一步)。

下一步是搜索插入的地方,然后调用上面的函数——类似这样,虽然我确信它可以改进:

(defun insert-attr-decls ()
  (insert "#+ATTR_HTML: :width 80%\n")
  (insert "#+ATTR_ORG: :width 80%\n") 
  (insert "#+ATTR_HTML: :style background-color: white; border-radius: 8px; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n"))

(defun insert-attr-decls-at (s)
  (let ((case-fold-search t))
   (if (search-forward s nil t)
    (progn 
       (search-backward s nil t)
       (insert-attr-decls)))))

(defun insert-attr-decls-at-results ()
  (interactive)
  (save-excursion
   (insert-attr-decls-at "#+RESULTS:")))

(define-key org-mode-map [f10] 'insert-attr-decls-at-results)

这已经是复杂性的巨大飞跃,它可能包含错误:会发生什么,例如如果缓冲区中没有 #+RESULTS: 字符串?我没有测试过。因此,如果其他人愿意花时间制作 "perfect" 函数,那么是的,也许我会接受并使用它。但除非这将是我的 bread-and-butter 工作,否则我宁愿把时间花在其他地方:如果它确实被证明是一个时间沉没,你可以随时将它自动化。

下一步(我不会这样做)是 C-c C-c 评估块 添加属性声明。您可以通过将 insert-attr-decls-at-results 添加到 org-babel-after-execute-hook 变量来实现:

(add-hook 'org-babel-after-execute-hook 'insert-attr-decls-at-results)

这里的问题是,在 评估时,您都会添加一个属性声明块:您真的必须重写插入函数以检查是否存在 is 已经是一个属性声明块,如果是,什么也不做。这留作练习。

故事 AFAIAC 的寓意是:您可以将一切自动化,但并非一切都值得自动化。