emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* Templating with Org
@ 2015-09-03  8:49 Eric Abrahamsen
  0 siblings, 0 replies; only message in thread
From: Eric Abrahamsen @ 2015-09-03  8:49 UTC (permalink / raw)
  To: emacs-orgmode

A while ago I asked about creating a system that repeats body text for
many Org headings -- essentially writing an export template that is
re-used for many headings. Search through Gmane is tedious and strangely
inaccurate, so I'm not bothering to find the original thread.

I've come up with a solution that others might find useful -- I'm also
hoping for some tips on improving it. I suppose I can add it to Worg
later.

I'll paste the function at the bottom, but what I'm talking about is
this:

#+BEGIN_SOURCE org
Templating Test
:PROPERTIES:
:EXPORT_BODY_TEMPLATE: template-heading
:END:
** Bob Jones
:PROPERTIES:
:SALUTATION: Dear Mr Jones
:MARMOTS:  390
:END:
** Janet Smith
:PROPERTIES:
:SALUTATION: Dear Prof. Smith
:MARMOTS:  9
:END:
** Unknown
:PROPERTIES:
:SALUTATION: Dear Sir/Madame
:MARMOTS:  42
:END:
Also, would you at your earliest convenience please remind us of your
name?
* Template body                                                    :noexport:
:PROPERTIES:
:ID:       template-heading
:END:
{{{property(SALUTATION)}}},

This is an automatically-generated form letter, informing you that you
have {{{property(MARMOTS)}}} marmots remaining in your account at the
United Bank of Marmots.

@@body@@

Yours truly,\\
Director of the United Bank of Marmots
#+END_SOURCE

When this is exported, the body of the "Template body" heading is
switched in for the bodies of each of the children of "Templating test".
That lets you use property macros to fill in the template context. As a
special case, the string "@@body@@" will be replaced with the original
body of the exported heading, if there is one.

The function below works fine, though I'd sure like to know if anyone
has any suggestions for cleaning it up, particular the bits about
finding and extracting heading bodies.

More unfortunately, it doesn't work if you restrict the export scope to
the "Templating Test" subtree, because the "EXPORT_BODY_TEMPLATE"
property isn't seen. I'd sure like to find a way to fix that.

I suppose one solution would be to explicitly add EXPORT_BODY_TEMPLATE
to the list of inherited properties, and then remove the inner
`org-map-entries'. But one of the things I like about the current
arrangement is that it is limited to direct children of the heading with
that property set.

Anyway, comments and improvements welcome!

Eric


#+BEGIN_SOURCE emacs-lisp
(defun org-template-replace (backend)
  "Do template body replacement in the exported region.

For any heading that has the EXPORT_BODY_TEMPLATE property set,
treat the value of that property as an org heading id, find that
heading, get its body text, and replace the body text of each of
this heading's children with that text.

This can be used to write a single export template which is then
used for many headings."
  (let ((org-use-property-inheritance nil))
    (org-map-entries
     (lambda ()
       (let ((targ (org-entry-get (point) "EXPORT_BODY_TEMPLATE"))
	     (level (org-current-level))
	     original-body template-body)
	 (when targ
	   (setq template-body
		 (save-excursion
		   (org-id-goto targ)
		   (org-end-of-meta-data t)
		   (when (or (looking-at org-heading-regexp)
			     (= (point) (point-max)))
		     (user-error "Template heading has no body text."))
		   (buffer-substring-no-properties
		    (point)
		    (progn (org-next-visible-heading 1)
			   (point)))))
	   (save-restriction
	     (org-narrow-to-subtree)
	     (org-map-entries
	      (lambda ()
		(org-end-of-meta-data t)
		(cond
		 ((looking-at org-heading-regexp)
		  (open-line 1))
		 ((= (point) (point-max))
		  (newline))
		 (t (setq original-body
			  (delete-and-extract-region
			   (point)
			   (progn
			     (save-excursion
			       (org-next-visible-heading 1)
			       (point)))))))
		
		(insert
		 (replace-regexp-in-string
		  (if original-body
		      "@@body@@"
		    "@@body@@\n\n") (or original-body "") template-body))
		(setq org-map-continue-from (1- (point))))
	      (format "LEVEL=%d" (1+ level)))))))
     "EXPORT_BODY_TEMPLATE<>\"\"")))

(add-hook 'org-export-before-processing-hook #'org-template-replace)

#+END_SOURCE

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2015-09-03  8:50 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-03  8:49 Templating with Org Eric Abrahamsen

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).