Определение макроса режима 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 (если его нужно настроить после написания документа).