1 ;;; ox-koma-letter.el --- KOMA Scrlttr2 Back-End for Org Export Engine
3 ;; Copyright (C) 2007-2015 Free Software Foundation, Inc.
5 ;; Author: Nicolas Goaziou <n.goaziou AT gmail DOT com>
6 ;; Alan Schmitt <alan.schmitt AT polytechnique DOT org>
7 ;; Viktor Rosenfeld <listuser36 AT gmail DOT com>
8 ;; Rasmus Pank Roulund <emacs AT pank DOT eu>
9 ;; Keywords: org, wp, tex
11 ;; This program is free software: you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation, either version 3 of the License, or
14 ;; (at your option) any later version.
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
26 ;; This library implements a KOMA Scrlttr2 back-end, derived from the
29 ;; Depending on the desired output format, three commands are provided
30 ;; for export: `org-koma-letter-export-as-latex' (temporary buffer),
31 ;; `org-koma-letter-export-to-latex' ("tex" file) and
32 ;; `org-koma-letter-export-to-pdf' ("pdf" file).
34 ;; On top of buffer keywords supported by `latex' back-end (see
35 ;; `org-latex-options-alist'), this back-end introduces the following
37 ;; - CLOSING: see `org-koma-letter-closing',
38 ;; - FROM_ADDRESS: see `org-koma-letter-from-address',
39 ;; - LCO: see `org-koma-letter-class-option-file',
40 ;; - OPENING: see `org-koma-letter-opening',
41 ;; - PHONE_NUMBER: see `org-koma-letter-phone-number',
42 ;; - SIGNATURE: see `org-koma-letter-signature',
43 ;; - PLACE: see `org-koma-letter-place',
44 ;; - TO_ADDRESS: If unspecified this is set to "\mbox{}".
46 ;; TO_ADDRESS and FROM_ADDRESS can also be specified using heading
47 ;; with the special tags specified in
48 ;; `org-koma-letter-special-tags-in-letter', namely "to" and "from".
49 ;; LaTeX line breaks are not necessary if using these headings. If
50 ;; both a headline and a keyword specify a to or from address the
51 ;; value is determined in accordance with
52 ;; `org-koma-letter-prefer-special-headings'.
54 ;; A number of OPTIONS settings can be set to change which contents is
56 ;; - backaddress (see `org-koma-letter-use-backaddress')
57 ;; - foldmarks (see `org-koma-letter-use-foldmarks')
58 ;; - phone (see `org-koma-letter-use-phone')
59 ;; - email (see `org-koma-letter-use-email')
60 ;; - place (see `org-koma-letter-use-place')
61 ;; - subject, a list of format options
62 ;; (see `org-koma-letter-subject-format')
63 ;; - after-closing-order, a list of the ordering of headings with
64 ;; special tags after closing (see
65 ;; `org-koma-letter-special-tags-after-closing')
66 ;; - after-letter-order, as above, but after the end of the letter
67 ;; (see `org-koma-letter-special-tags-after-letter').
69 ;; The following variables works differently from the main LaTeX class
70 ;; - AUTHOR: Default to user-full-name but may be disabled.
71 ;; (See also `org-koma-letter-author'),
72 ;; - EMAIL: Same as AUTHOR. (see also `org-koma-letter-email'),
74 ;; Headlines are in general ignored. However, headlines with special
75 ;; tags can be used for specified contents like postscript (ps),
76 ;; carbon copy (cc), enclosures (encl) and code to be inserted after
77 ;; \end{letter} (after_letter). Specials tags are defined in
78 ;; `org-koma-letter-special-tags-after-closing' and
79 ;; `org-koma-letter-special-tags-after-letter'. Currently members of
80 ;; `org-koma-letter-special-tags-after-closing' used as macros and the
81 ;; content of the headline is the argument.
83 ;; Headlines with two and from may also be used rather than the
84 ;; keyword approach described above. If both a keyword and a headline
85 ;; with information is present precedence is determined by
86 ;; `org-koma-letter-prefer-special-headings'.
88 ;; You need an appropriate association in `org-latex-classes' in order
89 ;; to use the KOMA Scrlttr2 class. By default, a sparse scrlttr2
90 ;; class is provided: "default-koma-letter". You can also add you own
91 ;; letter class. For instance:
93 ;; (add-to-list 'org-latex-classes
95 ;; "\\documentclass\[%
100 ;; backaddress=false,
103 ;; fromphone=true\]\{scrlttr2\}
104 ;; \[DEFAULT-PACKAGES]
108 ;; Then, in your Org document, be sure to require the proper class
111 ;; #+LATEX_CLASS: my-letter
113 ;; Or by setting `org-koma-letter-default-class'.
115 ;; You may have to load (LaTeX) Babel as well, e.g., by adding
116 ;; it to `org-latex-packages-alist',
118 ;; (add-to-list 'org-latex-packages-alist '("AUTO" "babel" nil))
124 ;; Install a default letter class.
125 (unless (assoc "default-koma-letter" org-latex-classes
)
126 (add-to-list 'org-latex-classes
127 '("default-koma-letter" "\\documentclass[11pt]{scrlttr2}")))
130 ;;; User-Configurable Variables
132 (defgroup org-export-koma-letter nil
133 "Options for exporting to KOMA scrlttr2 class in LaTeX export."
134 :tag
"Org Koma-Letter"
137 (defcustom org-koma-letter-class-option-file
"NF"
138 "Letter Class Option File.
139 This option can also be set with the LCO keyword."
140 :group
'org-export-koma-letter
143 (defcustom org-koma-letter-author
'user-full-name
146 This variable defaults to calling the function `user-full-name'
147 which just returns the current function `user-full-name'.
148 Alternatively a string, nil or a function may be given.
149 Functions must return a string.
151 This option can also be set with the AUTHOR keyword."
152 :group
'org-export-koma-letter
153 :type
'(radio (function-item user-full-name
)
156 (const :tag
"Do not export author" nil
)))
158 (defcustom org-koma-letter-email
'org-koma-letter-email
159 "Sender's email address.
161 This variable defaults to the value `org-koma-letter-email' which
162 returns `user-mail-address'. Alternatively a string, nil or
163 a function may be given. Functions must return a string.
165 This option can also be set with the EMAIL keyword."
166 :group
'org-export-koma-letter
167 :type
'(radio (function-item org-koma-letter-email
)
170 (const :tag
"Do not export email" nil
)))
172 (defcustom org-koma-letter-from-address
""
173 "Sender's address, as a string.
174 This option can also be set with one or more FROM_ADDRESS
176 :group
'org-export-koma-letter
179 (defcustom org-koma-letter-phone-number
""
180 "Sender's phone number, as a string.
181 This option can also be set with the PHONE_NUMBER keyword."
182 :group
'org-export-koma-letter
185 (defcustom org-koma-letter-place
""
186 "Place from which the letter is sent, as a string.
187 This option can also be set with the PLACE keyword."
188 :group
'org-export-koma-letter
191 (defcustom org-koma-letter-opening
""
192 "Letter's opening, as a string.
194 This option can also be set with the OPENING keyword. Moreover,
196 (1) Either `org-koma-letter-prefer-special-headings' is non-nil
197 or the CLOSING keyword is empty
198 (2) `org-koma-letter-headline-is-opening-maybe' is non-nil;
199 (3) the letter contains a headline without a special
200 tag (e.g. \"to\" or \"ps\");
201 then the opening will be implicitly set as the untagged headline title."
202 :group
'org-export-koma-letter
205 (defcustom org-koma-letter-closing
""
206 "Letter's closing, as a string.
207 This option can also be set with the CLOSING keyword. Moreover,
209 (1) Either `org-koma-letter-prefer-special-headings' is non-nil
210 or the CLOSING keyword is empty;
211 (2) `org-koma-letter-headline-is-opening-maybe' is non-nil;
212 (3) the letter contains a headline with the special
214 then the opening will be set as the title of the closing special
216 :group
'org-export-koma-letter
219 (defcustom org-koma-letter-signature
""
220 "Signature, as a string.
221 This option can also be set with the SIGNATURE keyword.
223 (1) Either `org-koma-letter-prefer-special-headings' is non-nil
224 or there is no CLOSING keyword or the CLOSING keyword is empty;
225 (2) `org-koma-letter-headline-is-opening-maybe' is non-nil;
226 (3) the letter contains a headline with the special
228 then the signature will be set as the content of the
229 closing special heading.
231 Note if the content is empty the signature will not be set."
232 :group
'org-export-koma-letter
235 (defcustom org-koma-letter-prefer-special-headings nil
236 "Non-nil means prefer headlines over keywords for TO and FROM.
237 This option can also be set with the OPTIONS keyword, e.g.:
238 \"special-headings:t\"."
239 :group
'org-export-koma-letter
242 (defcustom org-koma-letter-subject-format t
243 "Non-nil means include the subject.
245 Support formatting options.
247 When t, insert a subject using default options. When nil, do not
248 insert a subject at all. It can also be a list of symbols among
251 `afteropening' Subject after opening
252 `beforeopening' Subject before opening
253 `centered' Subject centered
254 `left' Subject left-justified
255 `right' Subject right-justified
256 `titled' Add title/description to subject
257 `underlined' Set subject underlined
258 `untitled' Do not add title/description to subject
260 Please refer to the KOMA-script manual (Table 4.16. in the
261 English manual of 2012-07-22).
263 This option can also be set with the OPTIONS keyword, e.g.:
264 \"subject:(underlined centered)\"."
267 (const :tag
"No export" nil
)
268 (const :tag
"Default options" t
)
269 (set :tag
"Configure options"
270 (const :tag
"Subject after opening" afteropening
)
271 (const :tag
"Subject before opening" beforeopening
)
272 (const :tag
"Subject centered" centered
)
273 (const :tag
"Subject left-justified" left
)
274 (const :tag
"Subject right-justified" right
)
275 (const :tag
"Add title or description to subject" underlined
)
276 (const :tag
"Set subject underlined" titled
)
277 (const :tag
"Do not add title or description to subject" untitled
)))
278 :group
'org-export-koma-letter
)
280 (defcustom org-koma-letter-use-backaddress nil
281 "Non-nil prints return address in line above to address.
282 This option can also be set with the OPTIONS keyword, e.g.:
284 :group
'org-export-koma-letter
287 (defcustom org-koma-letter-use-foldmarks t
288 "Configure appearance of folding marks.
290 When t, activate default folding marks. When nil, do not insert
291 folding marks at all. It can also be a list of symbols among the
294 `B' Activate upper horizontal mark on left paper edge
295 `b' Deactivate upper horizontal mark on left paper edge
297 `H' Activate all horizontal marks on left paper edge
298 `h' Deactivate all horizontal marks on left paper edge
300 `L' Activate left vertical mark on upper paper edge
301 `l' Deactivate left vertical mark on upper paper edge
303 `M' Activate middle horizontal mark on left paper edge
304 `m' Deactivate middle horizontal mark on left paper edge
306 `P' Activate punch or center mark on left paper edge
307 `p' Deactivate punch or center mark on left paper edge
309 `T' Activate lower horizontal mark on left paper edge
310 `t' Deactivate lower horizontal mark on left paper edge
312 `V' Activate all vertical marks on upper paper edge
313 `v' Deactivate all vertical marks on upper paper edge
315 This option can also be set with the OPTIONS keyword, e.g.:
316 \"foldmarks:(b l m t)\"."
317 :group
'org-export-koma-letter
319 (const :tag
"Activate default folding marks" t
)
320 (const :tag
"Deactivate folding marks" nil
)
322 :tag
"Configure folding marks"
323 (const :tag
"Activate upper horizontal mark on left paper edge" B
)
324 (const :tag
"Deactivate upper horizontal mark on left paper edge" b
)
325 (const :tag
"Activate all horizontal marks on left paper edge" H
)
326 (const :tag
"Deactivate all horizontal marks on left paper edge" h
)
327 (const :tag
"Activate left vertical mark on upper paper edge" L
)
328 (const :tag
"Deactivate left vertical mark on upper paper edge" l
)
329 (const :tag
"Activate middle horizontal mark on left paper edge" M
)
330 (const :tag
"Deactivate middle horizontal mark on left paper edge" m
)
331 (const :tag
"Activate punch or center mark on left paper edge" P
)
332 (const :tag
"Deactivate punch or center mark on left paper edge" p
)
333 (const :tag
"Activate lower horizontal mark on left paper edge" T
)
334 (const :tag
"Deactivate lower horizontal mark on left paper edge" t
)
335 (const :tag
"Activate all vertical marks on upper paper edge" V
)
336 (const :tag
"Deactivate all vertical marks on upper paper edge" v
))))
338 (defcustom org-koma-letter-use-phone nil
339 "Non-nil prints sender's phone number.
340 This option can also be set with the OPTIONS keyword, e.g.:
342 :group
'org-export-koma-letter
345 (defcustom org-koma-letter-use-email nil
346 "Non-nil prints sender's email address.
347 This option can also be set with the OPTIONS keyword, e.g.:
349 :group
'org-export-koma-letter
352 (defcustom org-koma-letter-use-place t
353 "Non-nil prints the letter's place next to the date.
354 This option can also be set with the OPTIONS keyword, e.g.:
356 :group
'org-export-koma-letter
359 (defcustom org-koma-letter-default-class
"default-koma-letter"
360 "Default class for `org-koma-letter'.
361 The value must be a member of `org-latex-classes'."
362 :group
'org-export-koma-letter
365 (defcustom org-koma-letter-headline-is-opening-maybe t
366 "Non-nil means a headline may be used as an opening and closing.
367 See also `org-koma-letter-opening' and
368 `org-koma-letter-closing'."
369 :group
'org-export-koma-letter
372 (defcustom org-koma-letter-prefer-subject nil
373 "Non-nil means title should be interpreted as subject if subject is missing.
374 This option can also be set with the OPTIONS keyword,
375 e.g. \"title-subject:t\"."
376 :group
'org-export-koma-letter
379 (defconst org-koma-letter-special-tags-in-letter
'(to from closing
)
380 "Header tags related to the letter itself.")
382 (defconst org-koma-letter-special-tags-after-closing
'(ps encl cc
)
383 "Header tags to be inserted after closing.")
385 (defconst org-koma-letter-special-tags-after-letter
'(after_letter)
386 "Header tags to be inserted after closing.")
388 (defvar org-koma-letter-special-contents nil
389 "Holds special content temporarily.")
391 (make-obsolete-variable 'org-koma-letter-use-title
392 'org-export-with-title
398 (org-export-define-derived-backend 'koma-letter
'latex
400 '((:latex-class
"LATEX_CLASS" nil org-koma-letter-default-class t
)
401 (:lco
"LCO" nil org-koma-letter-class-option-file
)
402 (:author
"AUTHOR" nil
(org-koma-letter--get-value org-koma-letter-author
) parse
)
403 (:author-changed-in-buffer-p
"AUTHOR" nil nil t
)
404 (:from-address
"FROM_ADDRESS" nil org-koma-letter-from-address newline
)
405 (:phone-number
"PHONE_NUMBER" nil org-koma-letter-phone-number
)
406 (:email
"EMAIL" nil
(org-koma-letter--get-value org-koma-letter-email
) t
)
407 (:to-address
"TO_ADDRESS" nil nil newline
)
408 (:place
"PLACE" nil org-koma-letter-place
)
409 (:subject
"SUBJECT" nil nil parse
)
410 (:opening
"OPENING" nil org-koma-letter-opening parse
)
411 (:closing
"CLOSING" nil org-koma-letter-closing parse
)
412 (:signature
"SIGNATURE" nil org-koma-letter-signature newline
)
413 (:special-headings nil
"special-headings"
414 org-koma-letter-prefer-special-headings
)
415 (:special-tags nil nil
(append
416 org-koma-letter-special-tags-in-letter
417 org-koma-letter-special-tags-after-closing
418 org-koma-letter-special-tags-after-letter
))
419 (:with-after-closing nil
"after-closing-order"
420 org-koma-letter-special-tags-after-closing
)
421 (:with-after-letter nil
"after-letter-order"
422 org-koma-letter-special-tags-after-letter
)
423 (:with-backaddress nil
"backaddress" org-koma-letter-use-backaddress
)
424 (:with-email nil
"email" org-koma-letter-use-email
)
425 (:with-foldmarks nil
"foldmarks" org-koma-letter-use-foldmarks
)
426 (:with-phone nil
"phone" org-koma-letter-use-phone
)
427 (:with-place nil
"place" org-koma-letter-use-place
)
428 (:with-subject nil
"subject" org-koma-letter-subject-format
)
429 (:with-title-as-subject nil
"title-subject" org-koma-letter-prefer-subject
)
430 (:with-headline-opening nil nil org-koma-letter-headline-is-opening-maybe
)
431 ;; Special properties non-nil when a setting happened in buffer.
432 ;; They are used to prioritize in-buffer settings over "lco"
433 ;; files. See `org-koma-letter-template'.
434 (:inbuffer-author
"AUTHOR" nil
'koma-letter
:empty
)
435 (:inbuffer-email
"EMAIL" nil
'koma-letter
:empty
)
436 (:inbuffer-phone-number
"PHONE_NUMBER" nil
'koma-letter
:empty
)
437 (:inbuffer-place
"PLACE" nil
'koma-letter
:empty
)
438 (:inbuffer-signature
"SIGNATURE" nil
'koma-letter
:empty
)
439 (:inbuffer-with-backaddress nil
"backaddress" 'koma-letter
:empty
)
440 (:inbuffer-with-email nil
"email" 'koma-letter
:empty
)
441 (:inbuffer-with-foldmarks nil
"foldmarks" 'koma-letter
:empty
)
442 (:inbuffer-with-phone nil
"phone" 'koma-letter
:empty
))
443 :translate-alist
'((export-block . org-koma-letter-export-block
)
444 (export-snippet . org-koma-letter-export-snippet
)
445 (headline . org-koma-letter-headline
)
446 (keyword . org-koma-letter-keyword
)
447 (template . org-koma-letter-template
))
449 '(?k
"Export with KOMA Scrlttr2"
450 ((?L
"As LaTeX buffer" org-koma-letter-export-as-latex
)
451 (?l
"As LaTeX file" org-koma-letter-export-to-latex
)
452 (?p
"As PDF file" org-koma-letter-export-to-pdf
)
453 (?o
"As PDF file and open"
455 (if a
(org-koma-letter-export-to-pdf t s v b
)
456 (org-open-file (org-koma-letter-export-to-pdf nil s v b
))))))))
462 (defun org-koma-letter-email ()
463 "Return the current `user-mail-address'."
466 ;; The following is taken from/inspired by ox-grof.el
469 (defun org-koma-letter--get-tagged-contents (key)
470 "Get contents from a headline tagged with KEY.
471 The contents is stored in `org-koma-letter-special-contents'."
472 (cdr (assoc-string (org-koma-letter--get-value key
)
473 org-koma-letter-special-contents
)))
475 (defun org-koma-letter--get-value (value)
476 "Turn value into a string whenever possible.
477 Determines if VALUE is nil, a string, a function or a symbol and
478 return a string or nil."
480 (cond ((stringp value
) value
)
481 ((functionp value
) (funcall value
))
482 ((symbolp value
) (symbol-name value
))
485 (defun org-koma-letter--special-contents-as-macro
486 (keywords &optional keep-newlines no-tag
)
487 "Process KEYWORDS members of `org-koma-letter-special-contents'.
488 KEYWORDS is a list of symbols. Return them as a string to be
491 The function is used for inserting content of special headings
494 If KEEP-NEWLINES is non-nil leading and trailing newlines are not
495 removed. If NO-TAG is non-nil the content in
496 `org-koma-letter-special-contents' are not wrapped in a macro
497 named whatever the members of KEYWORDS are called."
500 (let* ((name (org-koma-letter--get-value keyword
))
501 (value (org-koma-letter--get-tagged-contents name
)))
502 (cond ((not value
) nil
)
503 (no-tag (if keep-newlines value
(org-trim value
)))
504 (t (format "\\%s{%s}\n"
506 (if keep-newlines value
(org-trim value
)))))))
510 (defun org-koma-letter--determine-to-and-from (info key
)
511 "Given INFO determine KEY for the letter.
512 KEY should be `to' or `from'.
514 `ox-koma-letter' allows two ways to specify TO and FROM. If both
515 are present return the preferred one as determined by
516 `org-koma-letter-prefer-special-headings'."
517 (let ((option (org-string-nw-p
518 (plist-get info
(if (eq key
'to
) :to-address
:from-address
))))
519 (headline (org-koma-letter--get-tagged-contents key
)))
520 (replace-regexp-in-string
523 (if (plist-get info
:special-headings
) (or headline option
"")
524 (or option headline
""))))))
528 ;;; Transcode Functions
532 (defun org-koma-letter-export-block (export-block contents info
)
533 "Transcode an EXPORT-BLOCK element into KOMA Scrlttr2 code.
534 CONTENTS is nil. INFO is a plist used as a communication
536 (when (member (org-element-property :type export-block
) '("KOMA-LETTER" "LATEX"))
537 (org-remove-indentation (org-element-property :value export-block
))))
541 (defun org-koma-letter-export-snippet (export-snippet contents info
)
542 "Transcode an EXPORT-SNIPPET object into KOMA Scrlttr2 code.
543 CONTENTS is nil. INFO is a plist used as a communication
545 (when (memq (org-export-snippet-backend export-snippet
) '(latex koma-letter
))
546 (org-element-property :value export-snippet
)))
550 (defun org-koma-letter-keyword (keyword contents info
)
551 "Transcode a KEYWORD element into KOMA Scrlttr2 code.
552 CONTENTS is nil. INFO is a plist used as a communication
554 (let ((key (org-element-property :key keyword
))
555 (value (org-element-property :value keyword
)))
556 ;; Handle specifically KOMA-LETTER keywords. Otherwise, fallback
557 ;; to `latex' back-end.
558 (if (equal key
"KOMA-LETTER") value
559 (org-export-with-backend 'latex keyword contents info
))))
563 (defun org-koma-letter-headline (headline contents info
)
564 "Transcode a HEADLINE element from Org to LaTeX.
565 CONTENTS holds the contents of the headline. INFO is a plist
566 holding contextual information.
568 Note that if a headline is tagged with a tag from
569 `org-koma-letter-special-tags' it will not be exported, but
570 stored in `org-koma-letter-special-contents' and included at the
572 (let ((special-tag (org-koma-letter--special-tag headline info
)))
573 (if (not special-tag
)
575 (push (cons special-tag contents
) org-koma-letter-special-contents
)
578 (defun org-koma-letter--special-tag (headline info
)
579 "Non-nil if HEADLINE is a special headline.
580 INFO is a plist holding contextual information. Return first
581 special tag headline."
582 (let ((special-tags (plist-get info
:special-tags
)))
584 (dolist (tag (org-export-get-tags headline info
))
585 (let ((tag (assoc-string tag special-tags
)))
586 (when tag
(throw 'exit tag
)))))))
588 (defun org-koma-letter--keyword-or-headline (plist-key pred info
)
589 "Return the correct version of opening or closing.
590 PLIST-KEY should be a key in info, typically :opening
591 or :closing. PRED is a predicate run on headline to determine
592 which title to use which takes two arguments, a headline element
593 and an info plist. INFO is a plist holding contextual
594 information. Return the preferred candidate for the exported of
596 (let* ((keyword-candidate (plist-get info plist-key
))
597 (headline-candidate (when (and (plist-get info
:with-headline-opening
)
598 (or (plist-get info
:special-headings
)
599 (not keyword-candidate
)))
600 (org-element-map (plist-get info
:parse-tree
)
603 (when (funcall pred head info
)
604 (org-element-property :title head
)))
606 (org-export-data (or headline-candidate keyword-candidate
"") info
)))
610 (defun org-koma-letter-template (contents info
)
611 "Return complete document string after KOMA Scrlttr2 conversion.
612 CONTENTS is the transcoded contents string. INFO is a plist
613 holding export options."
616 (and (plist-get info
:time-stamp-file
)
617 (format-time-string "%% Created %Y-%m-%d %a %H:%M\n"))
618 ;; Document class and packages.
619 (org-latex--make-header info
)
620 ;; Settings. They can come from three locations, in increasing
621 ;; order of precedence: global variables, LCO files and in-buffer
622 ;; settings. Thus, we first insert settings coming from global
623 ;; variables, then we insert LCO files, and, eventually, we insert
624 ;; settings coming from buffer keywords.
625 (org-koma-letter--build-settings 'global info
)
626 (mapconcat #'(lambda (file) (format "\\LoadLetterOption{%s}\n" file
))
627 (org-split-string (or (plist-get info
:lco
) "") " ")
629 (org-koma-letter--build-settings 'buffer info
)
631 (let ((from-address (org-koma-letter--determine-to-and-from info
'from
)))
632 (when (org-string-nw-p from-address
)
633 (format "\\setkomavar{fromaddress}{%s}\n" from-address
)))
635 (format "\\date{%s}\n" (org-export-data (org-export-get-date info
) info
))
636 ;; Hyperref, document start, and subject and title.
637 (let* ((with-subject (plist-get info
:with-subject
))
638 (with-title (plist-get info
:with-title
))
639 (title-as-subject (and with-subject
640 (plist-get info
:with-title-as-subject
)))
641 (subject* (org-string-nw-p
642 (org-export-data (plist-get info
:subject
) info
)))
643 (title* (and with-title
645 (org-export-data (plist-get info
:title
) info
))))
646 (subject (cond ((not with-subject
) nil
)
647 (title-as-subject (or subject
* title
*))
649 (title (cond ((not with-title
) nil
)
650 (title-as-subject (and subject
* title
*))
652 (hyperref-template (plist-get info
:latex-hyperref-template
))
653 (spec (append (list (cons ?t
(or title subject
"")))
654 (org-latex--format-spec info
))))
656 (when (and with-subject
(not (eq with-subject t
)))
657 (format "\\KOMAoption{subject}{%s}\n"
658 (if (symbolp with-subject
) with-subject
659 (mapconcat #'symbol-name with-subject
","))))
661 (format-spec hyperref-template spec
)
663 "\\begin{document}\n\n"
664 ;; Subject and title.
665 (when subject
(format "\\setkomavar{subject}{%s}\n" subject
))
666 (when title
(format "\\setkomavar{title}{%s}\n" title
))
667 (when (or (org-string-nw-p title
) (org-string-nw-p subject
)) "\n")))
669 (format "\\begin{letter}{%%\n%s}\n\n"
670 (org-koma-letter--determine-to-and-from info
'to
))
672 (format "\\opening{%s}\n\n"
673 (org-koma-letter--keyword-or-headline
674 :opening
(lambda (h i
) (not (org-koma-letter--special-tag h i
)))
679 (format "\\closing{%s}\n"
680 (org-koma-letter--keyword-or-headline
681 :closing
(lambda (h i
) (eq (org-koma-letter--special-tag h i
)
684 (org-koma-letter--special-contents-as-macro
685 (plist-get info
:with-after-closing
))
688 (org-koma-letter--special-contents-as-macro
689 (plist-get info
:with-after-letter
) t t
)
691 "\n\\end{document}"))
693 (defun org-koma-letter--build-settings (scope info
)
694 "Build settings string according to type.
695 SCOPE is either `global' or `buffer'. INFO is a plist used as
696 a communication channel."
699 ;; Non-nil value when SETTING was defined in SCOPE.
701 (let ((property (intern (format ":inbuffer-%s" setting
))))
702 (if (eq scope
'global
)
703 (eq (plist-get info property
) 'koma-letter
:empty
)
704 (not (eq (plist-get info property
) 'koma-letter
:empty
))))))))
707 (let ((author (plist-get info
:author
)))
709 (funcall check-scope
'author
)
710 (format "\\setkomavar{fromname}{%s}\n"
711 (org-export-data author info
))))
713 (let ((email (plist-get info
:email
)))
715 (funcall check-scope
'email
)
716 (format "\\setkomavar{fromemail}{%s}\n" email
)))
717 (and (funcall check-scope
'with-email
)
718 (format "\\KOMAoption{fromemail}{%s}\n"
719 (if (plist-get info
:with-email
) "true" "false")))
721 (let ((phone-number (plist-get info
:phone-number
)))
722 (and (org-string-nw-p phone-number
)
723 (funcall check-scope
'phone-number
)
724 (format "\\setkomavar{fromphone}{%s}\n" phone-number
)))
725 (and (funcall check-scope
'with-phone
)
726 (format "\\KOMAoption{fromphone}{%s}\n"
727 (if (plist-get info
:with-phone
) "true" "false")))
730 (and (plist-get info
:with-headline-opening
)
734 (org-koma-letter--get-tagged-contents 'closing
)
736 (signature (org-string-nw-p (plist-get info
:signature
)))
737 (signature-scope (funcall check-scope
'signature
)))
738 (and (or (and signature signature-scope
)
740 (not (and (eq scope
'global
) heading-val
))
741 (format "\\setkomavar{signature}{%s}\n"
742 (if signature-scope signature heading-val
))))
744 (and (funcall check-scope
'with-backaddress
)
745 (format "\\KOMAoption{backaddress}{%s}\n"
746 (if (plist-get info
:with-backaddress
) "true" "false")))
748 (and (funcall check-scope
'place
)
749 (format "\\setkomavar{place}{%s}\n"
750 (if (plist-get info
:with-place
) (plist-get info
:place
) "")))
752 (and (funcall check-scope
'with-foldmarks
)
753 (let ((foldmarks (plist-get info
:with-foldmarks
)))
754 (cond ((consp foldmarks
)
755 (format "\\KOMAoptions{foldmarks=true,foldmarks=%s}\n"
756 (mapconcat #'symbol-name foldmarks
"")))
757 (foldmarks "\\KOMAoptions{foldmarks=true}\n")
758 (t "\\KOMAoptions{foldmarks=false}\n")))))))
765 (defun org-koma-letter-export-as-latex
766 (&optional async subtreep visible-only body-only ext-plist
)
767 "Export current buffer as a KOMA Scrlttr2 letter.
769 If narrowing is active in the current buffer, only export its
772 If a region is active, export that region.
774 A non-nil optional argument ASYNC means the process should happen
775 asynchronously. The resulting buffer should be accessible
776 through the `org-export-stack' interface.
778 When optional argument SUBTREEP is non-nil, export the sub-tree
779 at point, extracting information from the headline properties
782 When optional argument VISIBLE-ONLY is non-nil, don't export
783 contents of hidden elements.
785 When optional argument BODY-ONLY is non-nil, only write code
786 between \"\\begin{letter}\" and \"\\end{letter}\".
788 EXT-PLIST, when provided, is a proeprty list with external
789 parameters overriding Org default settings, but still inferior to
792 Export is done in a buffer named \"*Org KOMA-LETTER Export*\". It
793 will be displayed if `org-export-show-temporary-export-buffer' is
796 (let (org-koma-letter-special-contents)
797 (org-export-to-buffer 'koma-letter
"*Org KOMA-LETTER Export*"
798 async subtreep visible-only body-only ext-plist
799 (lambda () (LaTeX-mode)))))
802 (defun org-koma-letter-export-to-latex
803 (&optional async subtreep visible-only body-only ext-plist
)
804 "Export current buffer as a KOMA Scrlttr2 letter (tex).
806 If narrowing is active in the current buffer, only export its
809 If a region is active, export that region.
811 A non-nil optional argument ASYNC means the process should happen
812 asynchronously. The resulting file should be accessible through
813 the `org-export-stack' interface.
815 When optional argument SUBTREEP is non-nil, export the sub-tree
816 at point, extracting information from the headline properties
819 When optional argument VISIBLE-ONLY is non-nil, don't export
820 contents of hidden elements.
822 When optional argument BODY-ONLY is non-nil, only write code
823 between \"\\begin{letter}\" and \"\\end{letter}\".
825 EXT-PLIST, when provided, is a property list with external
826 parameters overriding Org default settings, but still inferior to
829 When optional argument PUB-DIR is set, use it as the publishing
832 Return output file's name."
834 (let ((outfile (org-export-output-file-name ".tex" subtreep
))
835 (org-koma-letter-special-contents))
836 (org-export-to-file 'koma-letter outfile
837 async subtreep visible-only body-only ext-plist
)))
840 (defun org-koma-letter-export-to-pdf
841 (&optional async subtreep visible-only body-only ext-plist
)
842 "Export current buffer as a KOMA Scrlttr2 letter (pdf).
844 If narrowing is active in the current buffer, only export its
847 If a region is active, export that region.
849 A non-nil optional argument ASYNC means the process should happen
850 asynchronously. The resulting file should be accessible through
851 the `org-export-stack' interface.
853 When optional argument SUBTREEP is non-nil, export the sub-tree
854 at point, extracting information from the headline properties
857 When optional argument VISIBLE-ONLY is non-nil, don't export
858 contents of hidden elements.
860 When optional argument BODY-ONLY is non-nil, only write code
861 between \"\\begin{letter}\" and \"\\end{letter}\".
863 EXT-PLIST, when provided, is a property list with external
864 parameters overriding Org default settings, but still inferior to
867 Return PDF file's name."
869 (let ((file (org-export-output-file-name ".tex" subtreep
))
870 (org-koma-letter-special-contents))
871 (org-export-to-file 'koma-letter file
872 async subtreep visible-only body-only ext-plist
873 (lambda (file) (org-latex-compile file
)))))
876 (provide 'ox-koma-letter
)
877 ;;; ox-koma-letter.el ends here