Function: org-latex-headline

org-latex-headline is a byte-compiled function defined in ox-latex.el.gz.

Signature

(org-latex-headline HEADLINE CONTENTS INFO)

Documentation

Transcode a HEADLINE element from Org to LaTeX.

CONTENTS holds the contents of the headline. INFO is a plist holding contextual information.

Source Code

;; Defined in /usr/src/emacs/lisp/org/ox-latex.el.gz
(defun org-latex-headline (headline contents info)
  "Transcode a HEADLINE element from Org to LaTeX.
CONTENTS holds the contents of the headline.  INFO is a plist
holding contextual information."
  (unless (org-element-property :footnote-section-p headline)
    (let* ((level (org-export-get-relative-level headline info))
           ;; "LaTeX TOC handling"
           ;; :unnumbered: toc will add the heading to the ToC
           ;; "Org TOC handling"
           ;; :unnumbered: notoc to suppress heading from the ToC
           ;; else include all headings (including unnumbered) like other modes
           (unnumbered-type (org-export-get-node-property :UNNUMBERED headline t))
	   (numberedp (org-export-numbered-headline-p headline info))
	   ;; Section formatting will set two placeholders: one for
	   ;; the title and the other for the contents.
	   (section-fmt (org-latex--get-section-format headline info))
	   (text
	    (org-export-data-with-backend
	     (org-element-property :title headline)
             org-latex--section-backend info))
           (text-no-footnote
            (org-export-data-with-backend
	     (org-element-property :title headline)
             org-latex--section-no-footnote-backend info))
	   (todo
	    (and (plist-get info :with-todo-keywords)
		 (let ((todo (org-element-property :todo-keyword headline)))
		   (and todo (org-export-data todo info)))))
	   (todo-type (and todo (org-element-property :todo-type headline)))
	   (tags (and (plist-get info :with-tags)
		      (org-export-get-tags headline info)))
	   (priority (and (plist-get info :with-priority)
			  (org-element-property :priority headline)))
	   ;; Create the headline text along with a no-tag version.
	   ;; The latter is required to remove tags from toc.
	   (full-text (funcall (plist-get info :latex-format-headline-function)
			       todo todo-type priority text tags info))
           (full-text-no-footnote
            (funcall (plist-get info :latex-format-headline-function)
		     todo todo-type priority text-no-footnote tags info))
	   ;; Associate \label to the headline for internal links.
	   (headline-label (org-latex--label headline info t t))
	   (pre-blanks
	    (make-string (org-element-property :pre-blank headline) ?\n)))
      (if (or (not section-fmt) (org-export-low-level-p headline info))
	  ;; This is a deep sub-tree: export it as a list item.  Also
	  ;; export as items headlines for which no section format has
	  ;; been found.
	  (let ((low-level-body
		 (concat
		  ;; If headline is the first sibling, start a list.
		  (when (org-export-first-sibling-p headline info)
		    (format "\\begin{%s}\n" (if numberedp 'enumerate 'itemize)))
		  ;; Itemize headline
		  "\\item"
		  (and full-text
		       (string-match-p "\\`[ \t]*\\[" full-text)
		       "\\relax")
		  " " full-text "\n"
		  headline-label
		  pre-blanks
		  contents)))
	    ;; If headline is not the last sibling simply return
	    ;; LOW-LEVEL-BODY.  Otherwise, also close the list, before
	    ;; any blank line.
	    (if (not (org-export-last-sibling-p headline info)) low-level-body
	      (replace-regexp-in-string
	       "[ \t\n]*\\'"
	       (format "\n\\\\end{%s}" (if numberedp 'enumerate 'itemize))
	       low-level-body)))
	;; This is a standard headline.  Export it as a section.  Add
	;; an alternative heading when possible, and when this is not
	;; identical to the usual heading.
	(let ((opt-title
	       (funcall (plist-get info :latex-format-headline-function)
			todo todo-type priority
			(org-export-data-with-backend
                         ;; Returns alternative title when provided or
                         ;; title itself.
			 (org-export-get-alt-title headline info)
			 org-latex--section-backend info)
			(and (eq (plist-get info :with-tags) t) tags)
			info))
	      ;; Maybe end local TOC (see `org-latex-keyword').
	      (contents
	       (concat
		contents
		(let ((case-fold-search t)
		      (section
		       (let ((first (car (org-element-contents headline))))
			 (and (org-element-type-p first 'section) first))))
		  (org-element-map section 'keyword
		    (lambda (k)
		      (and (equal (org-element-property :key k) "TOC")
			   (let ((v (org-element-property :value k)))
			     (and (string-match-p "\\<headlines\\>" v)
				  (string-match-p "\\<local\\>" v)
				  (format "\\stopcontents[level-%d]" level)))))
		    info t)))))
          ;; When do we need to explicitly specify a heading for TOC?
          ;; 1. On numbered section with footnotes in title or alt_title
          ;; 2. On an unnumbered section if :UNNUMBERED: allows it regardless of footnotes
          ;; This applies to anything that may go into the ToC.
          ;; Specifically for paragraphs, see first answer of
          ;; https://tex.stackexchange.com/questions/288072/footnotes-within-paragraph
          (let ((section-kw
                 (and (string-match "\\`\\\\\\(.+?\\){" section-fmt)
                      (match-string 1 section-fmt)))
                need-alternative-toc-title)
            (if (not section-kw)
                ;; We only know how to add \SECTION-KW{...} to TOC.
                (setq need-alternative-toc-title nil)
              (if (string-suffix-p "*" section-kw)
                  ;; FIXME: In theory, user may customize section-fmt
                  ;; to use, e.g. \section{...} for unnumbered headings
                  ;; We do not handle such scenario.
                  (progn ;; unnumbered sections (ending with *)
                    ;; Then we need to obey what the :UNNUMBERED: property says
                    (if org-latex-toc-include-unnumbered
                        ;; Treat the ToC closer to what other exporters do
                        ;; Include unnumbered section into TOC unless
                        ;; explicitly requested not to.
                        (if (string= unnumbered-type "notoc")
                            (setq need-alternative-toc-title nil)
                          (setq need-alternative-toc-title t))
                      ;; Ignore unnumbered headings in ToC - as in LaTeX
                      ;; unless explicitly requested to include.
                      (if (string= unnumbered-type "toc")
                          (setq need-alternative-toc-title t)
                        (setq need-alternative-toc-title nil))))
                ;; Numbered sections
                ;; Specify special TOC title only when there is
                ;; opt-title or when title contains footnotes.
                (if (and (string= full-text full-text-no-footnote)  ;; no footnotes
                         ;; opt-title is either ALT_TITLE or title itself
                         ;; as returned by `org-export-get-alt-title'
                         (string= full-text opt-title)) ;; same alternative title
                    (setq need-alternative-toc-title nil)
                  (setq need-alternative-toc-title t))))
            ;; In all cases
            ;; Get rid of the footnotes in opt-title
            (when (and (not (string= full-text-no-footnote full-text)) ;; when we have footnotess
                       (string= full-text opt-title))      ;; And we do not impose an alternative title
              (setq opt-title full-text-no-footnote))
	    (if need-alternative-toc-title
                (let ((new-format section-fmt)
                      (new-extra  "")) ;; put the addcontentsline here
                  (if (string-suffix-p "*" section-kw)
                      ;; Subsection that needs alternative title:
                      ;; Keep section format, use \\addcontentsline
                      (setq new-extra
                            (format "\\addcontentsline{toc}{%s}{%s}\n"
                                    (string-remove-suffix "*" section-kw)
                                    opt-title))
                    ;; section... we need the brackets
                    (let*
                        ;; Replace square brackets with parenthesis
                        ;; since square brackets are not supported in
                        ;; optional arguments.
                        ((un-bracketed-alt (replace-regexp-in-string
                                            "\\[" "(" (replace-regexp-in-string "\\]" ")" opt-title)))
                         (replacement-re (concat
                                          "\\1["
                                          (replace-regexp-in-string (rx "\\") "\\\\" un-bracketed-alt nil t)
                                          "]")))
                      (setq new-format (replace-match replacement-re nil nil section-fmt 1))))
                  (format new-format
                          full-text
                          (concat headline-label new-extra pre-blanks contents)))
	      ;; Don't need or cannot have alternative heading.
	      ;; Use regular sectioning format string.
	      (format section-fmt full-text
		      (concat headline-label pre-blanks contents)))))))))