Определение макроса режима org с разрывами строк
Можно определить макрос в файле org
следующим образом:
#+MACRO: macroname <here comes the body of the macro>
Можно ли определить макрос, содержащий разрывы строк? I.e, что-то вроде:
#+MACRO: macroname line 1 of macro
line 2 of macro
В частности, этот макрос будет расширен до
line 1 of macro
line 2 of macro
Моей мотивацией является наличие макроса, который расширяется до блока текста, который содержит, например, два абзаца.
Ответы
Ответ 1
Это не только возможно, но и довольно легко. Вам просто нужно быть
о том, как вы вставляете новую строку. Я использую Org Babel для взлома макросов. Для меня работает следующее:
#+MACRO: newline src_emacs-lisp[:results raw]{"\n"}
#+MACRO: macroname line 1 of macro {{{newline}}}line 2 of macro
Итак, учитывая этот документ:
#+MACRO: newline src_emacs-lisp[:results raw]{"\n"}
#+MACRO: macroname line 1 of macro {{{newline}}}line 2 of macro
{{{macroname}}}
Экспорт в режим Org дает следующие
# Created 2015-11-03 Tue 15:27
#+TITLE:
#+AUTHOR:
#+MACRO: newline src_emacs-lisp[:results raw]{"\n"}
#+MACRO: macroname line 1 of macro {{{newline}}}line 2 of macro
line 1 of macro
line 2 of macro
Вам просто нужно знать, что некоторые форматы экспорта
newline для одной строки, когда она обертывает текст. Итак, вы, вероятно, хотите, чтобы что-то вроде этого получилось двумя абзацами:
#+MACRO: newline src_emacs-lisp[:results raw]{"\n"}
#+MACRO: macroname line 1 of macro {{{newline}}} {{{newline}}}line 2 of macro
Ответ 2
Есть еще одно решение, которое работает корректно. Из исходного кода org-macro.el:
;; VALUE starts with "(eval": it is a s-exp, `eval' it.
(when (string-match "\\`(eval\\>" value)
(setq value (eval (read value))))
Таким образом, вы можете определить макрос следующим образом:
#+MACRO: newline (eval "\n")
Также поддерживаются подстановки. Макрос
#+MACRO: img (eval "#+CAPTION: $1\nfile:$2")
который называется
{{{img(hello world!, ./img1.jpg)}}}
будет заменено на:
#+CAPTION: hello world!
file:./img1.jpg
Ответ 3
Невозможно со стандартными инструментами на данный момент, так как
org-macro--collect-macros
рассматривает только определения одной строки.
Здесь обход:
* Setup :noexport:
#+begin_src elisp :exports results :results silent
(setq my-macros
(mapcar
(lambda (x)
(string-match "\\*\\* \\([^\n]+\\)\n\\(.*\\)" x)
(cons (match-string 1 x)
(substring x (match-beginning 2))))
(org-element-map (org-element-parse-buffer) 'headline
(lambda (x)
(and (= (org-element-property :level x) 2)
(string=
(org-element-property
:raw-value
(org-element-property :parent x)) "Macros")
(buffer-substring-no-properties
(org-element-property :begin x)
(org-element-property :end x)))))
headings))
(defadvice org-macro--collect-macros (around add-macros activate)
(let ((r ad-do-it))
(setq ad-return-value
(append my-macros r))))
#+end_src
* Macros
** foobar
line 1 of macro
line 2 of macro
** bar
line 1 of macro
line 2 of macro
line 3 of macro
* Test
{{{foobar}}}
{{{bar}}}
Этот подход поддерживает соглашение по настройке, поэтому каждый макрос должен быть
уровень 2-го уровня заголовка уровня 1 с именем "Макросы".
Никакой дополнительной конфигурации не требуется: должен работать обычный экспорт.
Заголовок установки должен быть скопирован в файлы, в которых вы хотите, чтобы это работало.
Или вы можете добавить defadvice
в свою конфигурацию, чтобы иметь такое поведение повсюду.
Ответ 4
Лучший совет, который я могу вам дать, - следовать тому, что предложил Николя Гоазиу (т.е. не использовать макросы для вашего использования) и найти другое решение, для которого вы уверены, что он будет работать сейчас и навсегда.
В этом случае я либо использовал YASnippets (если бы только помощник при наборе текста), либо Org Babel (если его нужно настроить после написания документа).