summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/lisp/ox-groff.el2
-rw-r--r--lisp/ob-lilypond.el230
-rw-r--r--lisp/ob-sh.el8
-rw-r--r--lisp/org-agenda.el12
-rw-r--r--lisp/org-element.el206
-rw-r--r--lisp/org-loaddefs.el38
-rw-r--r--lisp/org-src.el37
-rw-r--r--lisp/org-table.el10
-rw-r--r--lisp/org-version.el4
-rw-r--r--lisp/org.el59
-rw-r--r--lisp/ox-ascii.el24
-rw-r--r--lisp/ox-beamer.el2
-rw-r--r--lisp/ox-html.el143
-rw-r--r--lisp/ox-latex.el5
-rw-r--r--lisp/ox-md.el141
-rw-r--r--lisp/ox-odt.el2
-rw-r--r--lisp/ox-publish.el6
-rw-r--r--lisp/ox-texinfo.el1324
-rw-r--r--lisp/ox.el37
-rw-r--r--mk/org-fixup.el16
-rw-r--r--mk/version.mk4
21 files changed, 1013 insertions, 1297 deletions
diff --git a/contrib/lisp/ox-groff.el b/contrib/lisp/ox-groff.el
index 8484def..b3e3ad3 100644
--- a/contrib/lisp/ox-groff.el
+++ b/contrib/lisp/ox-groff.el
@@ -1268,7 +1268,7 @@ INFO is a plist holding contextual information. See
;; description.
((string= type "radio")
(let ((destination (org-export-resolve-radio-link link info)))
- (when destination
+ (if (not destination) desc
(format "\\fI [%s] \\fP"
(org-export-solidify-link-text
(org-element-property :value destination))))))
diff --git a/lisp/ob-lilypond.el b/lisp/ob-lilypond.el
index 9b57546..00a951d 100644
--- a/lisp/ob-lilypond.el
+++ b/lisp/ob-lilypond.el
@@ -39,62 +39,62 @@
(defvar org-babel-default-header-args:lilypond '()
"Default header arguments for lilypond code blocks.
NOTE: The arguments are determined at lilypond compile time.
-See (ly-set-header-args)")
+See (org-babel-lilypond-set-header-args)")
-(defvar ly-compile-post-tangle t
+(defvar org-babel-lilypond-compile-post-tangle t
"Following the org-babel-tangle (C-c C-v t) command,
-ly-compile-post-tangle determines whether ob-lilypond should
+org-babel-lilypond-compile-post-tangle determines whether ob-lilypond should
automatically attempt to compile the resultant tangled file.
If the value is nil, no automated compilation takes place.
Default value is t")
-(defvar ly-display-pdf-post-tangle t
+(defvar org-babel-lilypond-display-pdf-post-tangle t
"Following a successful LilyPond compilation
-ly-display-pdf-post-tangle determines whether to automate the
+org-babel-lilypond-display-pdf-post-tangle determines whether to automate the
drawing / redrawing of the resultant pdf. If the value is nil,
the pdf is not automatically redrawn. Default value is t")
-(defvar ly-play-midi-post-tangle t
+(defvar org-babel-lilypond-play-midi-post-tangle t
"Following a successful LilyPond compilation
-ly-play-midi-post-tangle determines whether to automate the
+org-babel-lilypond-play-midi-post-tangle determines whether to automate the
playing of the resultant midi file. If the value is nil,
the midi file is not automatically played. Default value is t")
-(defvar ly-OSX-ly-path
+(defvar org-babel-lilypond-OSX-ly-path
"/Applications/lilypond.app/Contents/Resources/bin/lilypond")
-(defvar ly-OSX-pdf-path "open")
-(defvar ly-OSX-midi-path "open")
+(defvar org-babel-lilypond-OSX-pdf-path "open")
+(defvar org-babel-lilypond-OSX-midi-path "open")
-(defvar ly-nix-ly-path "/usr/bin/lilypond")
-(defvar ly-nix-pdf-path "evince")
-(defvar ly-nix-midi-path "timidity")
+(defvar org-babel-lilypond-nix-ly-path "/usr/bin/lilypond")
+(defvar org-babel-lilypond-nix-pdf-path "evince")
+(defvar org-babel-lilypond-nix-midi-path "timidity")
-(defvar ly-w32-ly-path "lilypond")
-(defvar ly-w32-pdf-path "")
-(defvar ly-w32-midi-path "")
+(defvar org-babel-lilypond-w32-ly-path "lilypond")
+(defvar org-babel-lilypond-w32-pdf-path "")
+(defvar org-babel-lilypond-w32-midi-path "")
-(defvar ly-gen-png nil
+(defvar org-babel-lilypond-gen-png nil
"Image generation (png) can be turned on by default by setting
-LY-GEN-PNG to t")
+ORG-BABEL-LILYPOND-GEN-PNG to t")
-(defvar ly-gen-svg nil
+(defvar org-babel-lilypond-gen-svg nil
"Image generation (SVG) can be turned on by default by setting
-LY-GEN-SVG to t")
+ORG-BABEL-LILYPOND-GEN-SVG to t")
-(defvar ly-gen-html nil
+(defvar org-babel-lilypond-gen-html nil
"HTML generation can be turned on by default by setting
-LY-GEN-HTML to t")
+ORG-BABEL-LILYPOND-GEN-HTML to t")
-(defvar ly-gen-pdf nil
+(defvar org-babel-lilypond-gen-pdf nil
"PDF generation can be turned on by default by setting
-LY-GEN-PDF to t")
+ORG-BABEL-LILYPOND-GEN-PDF to t")
-(defvar ly-use-eps nil
+(defvar org-babel-lilypond-use-eps nil
"You can force the compiler to use the EPS backend by setting
-LY-USE-EPS to t")
+ORG-BABEL-LILYPOND-USE-EPS to t")
-(defvar ly-arrange-mode nil
- "Arrange mode is turned on by setting LY-ARRANGE-MODE
+(defvar org-babel-lilypond-arrange-mode nil
+ "Arrange mode is turned on by setting ORG-BABEL-LILYPOND-ARRANGE-MODE
to t. In Arrange mode the following settings are altered
from default...
:tangle yes, :noweb yes
@@ -123,20 +123,20 @@ Depending on whether we are in arrange mode either:
1. Attempt to execute lilypond block according to header settings
(This is the default basic mode)
2. Tangle all lilypond blocks and process the result (arrange mode)"
- (ly-set-header-args ly-arrange-mode)
- (if ly-arrange-mode
- (ly-tangle)
- (ly-process-basic body params)))
+ (org-babel-lilypond-set-header-args org-babel-lilypond-arrange-mode)
+ (if org-babel-lilypond-arrange-mode
+ (org-babel-lilypond-tangle)
+ (org-babel-lilypond-process-basic body params)))
-(defun ly-tangle ()
+(defun org-babel-lilypond-tangle ()
"ob-lilypond specific tangle, attempts to invoke
=ly-execute-tangled-ly= if tangle is successful. Also passes
specific arguments to =org-babel-tangle="
(interactive)
(if (org-babel-tangle nil "yes" "lilypond")
- (ly-execute-tangled-ly) nil))
+ (org-babel-lilypond-execute-tangled-ly) nil))
-(defun ly-process-basic (body params)
+(defun org-babel-lilypond-process-basic (body params)
"Execute a lilypond block in basic mode."
(let* ((result-params (cdr (assoc :result-params params)))
(out-file (cdr (assoc :file params)))
@@ -148,7 +148,7 @@ specific arguments to =org-babel-tangle="
(insert (org-babel-expand-body:generic body params)))
(org-babel-eval
(concat
- (ly-determine-ly-path)
+ (org-babel-lilypond-determine-ly-path)
" -dbackend=eps "
"-dno-gs-load-fonts "
"-dinclude-eps-fonts "
@@ -167,45 +167,45 @@ specific arguments to =org-babel-tangle="
"Return an error because LilyPond exporter does not support sessions."
(error "Sorry, LilyPond does not currently support sessions!"))
-(defun ly-execute-tangled-ly ()
+(defun org-babel-lilypond-execute-tangled-ly ()
"Compile result of block tangle with lilypond.
If error in compilation, attempt to mark the error in lilypond org file"
- (when ly-compile-post-tangle
- (let ((ly-tangled-file (ly-switch-extension
+ (when org-babel-lilypond-compile-post-tangle
+ (let ((org-babel-lilypond-tangled-file (org-babel-lilypond-switch-extension
(buffer-file-name) ".lilypond"))
- (ly-temp-file (ly-switch-extension
+ (org-babel-lilypond-temp-file (org-babel-lilypond-switch-extension
(buffer-file-name) ".ly")))
- (if (file-exists-p ly-tangled-file)
+ (if (file-exists-p org-babel-lilypond-tangled-file)
(progn
- (when (file-exists-p ly-temp-file)
- (delete-file ly-temp-file))
- (rename-file ly-tangled-file
- ly-temp-file))
+ (when (file-exists-p org-babel-lilypond-temp-file)
+ (delete-file org-babel-lilypond-temp-file))
+ (rename-file org-babel-lilypond-tangled-file
+ org-babel-lilypond-temp-file))
(error "Error: Tangle Failed!") t)
(switch-to-buffer-other-window "*lilypond*")
(erase-buffer)
- (ly-compile-lilyfile ly-temp-file)
+ (org-babel-lilypond-compile-lilyfile org-babel-lilypond-temp-file)
(goto-char (point-min))
- (if (not (ly-check-for-compile-error ly-temp-file))
+ (if (not (org-babel-lilypond-check-for-compile-error org-babel-lilypond-temp-file))
(progn
(other-window -1)
- (ly-attempt-to-open-pdf ly-temp-file)
- (ly-attempt-to-play-midi ly-temp-file))
+ (org-babel-lilypond-attempt-to-open-pdf org-babel-lilypond-temp-file)
+ (org-babel-lilypond-attempt-to-play-midi org-babel-lilypond-temp-file))
(error "Error in Compilation!")))) nil)
-(defun ly-compile-lilyfile (file-name &optional test)
+(defun org-babel-lilypond-compile-lilyfile (file-name &optional test)
"Compile lilypond file and check for compile errors
FILE-NAME is full path to lilypond (.ly) file"
(message "Compiling LilyPond...")
- (let ((arg-1 (ly-determine-ly-path)) ;program
+ (let ((arg-1 (org-babel-lilypond-determine-ly-path)) ;program
(arg-2 nil) ;infile
(arg-3 "*lilypond*") ;buffer
(arg-4 t) ;display
- (arg-5 (if ly-gen-png "--png" "")) ;&rest...
- (arg-6 (if ly-gen-html "--html" ""))
- (arg-7 (if ly-gen-pdf "--pdf" ""))
- (arg-8 (if ly-use-eps "-dbackend=eps" ""))
- (arg-9 (if ly-gen-svg "-dbackend=svg" ""))
+ (arg-5 (if org-babel-lilypond-gen-png "--png" "")) ;&rest...
+ (arg-6 (if org-babel-lilypond-gen-html "--html" ""))
+ (arg-7 (if org-babel-lilypond-gen-pdf "--pdf" ""))
+ (arg-8 (if org-babel-lilypond-use-eps "-dbackend=eps" ""))
+ (arg-9 (if org-babel-lilypond-gen-svg "-dbackend=svg" ""))
(arg-10 (concat "--output=" (file-name-sans-extension file-name)))
(arg-11 file-name))
(if test
@@ -215,7 +215,7 @@ FILE-NAME is full path to lilypond (.ly) file"
arg-1 arg-2 arg-3 arg-4 arg-5 arg-6
arg-7 arg-8 arg-9 arg-10 arg-11))))
-(defun ly-check-for-compile-error (file-name &optional test)
+(defun org-babel-lilypond-check-for-compile-error (file-name &optional test)
"Check for compile error.
This is performed by parsing the *lilypond* buffer
containing the output message from the compilation.
@@ -226,24 +226,24 @@ nil as file-name since it is unused in this context"
(if (not test)
(if (not is-error)
nil
- (ly-process-compile-error file-name))
+ (org-babel-lilypond-process-compile-error file-name))
is-error)))
-(defun ly-process-compile-error (file-name)
+(defun org-babel-lilypond-process-compile-error (file-name)
"Process the compilation error that has occurred.
FILE-NAME is full path to lilypond file"
- (let ((line-num (ly-parse-line-num)))
- (let ((error-lines (ly-parse-error-line file-name line-num)))
- (ly-mark-error-line file-name error-lines)
+ (let ((line-num (org-babel-lilypond-parse-line-num)))
+ (let ((error-lines (org-babel-lilypond-parse-error-line file-name line-num)))
+ (org-babel-lilypond-mark-error-line file-name error-lines)
(error "Error: Compilation Failed!"))))
-(defun ly-mark-error-line (file-name line)
+(defun org-babel-lilypond-mark-error-line (file-name line)
"Mark the erroneous lines in the lilypond org buffer.
FILE-NAME is full path to lilypond file.
LINE is the erroneous line"
(switch-to-buffer-other-window
(concat (file-name-nondirectory
- (ly-switch-extension file-name ".org"))))
+ (org-babel-lilypond-switch-extension file-name ".org"))))
(let ((temp (point)))
(goto-char (point-min))
(setq case-fold-search nil)
@@ -254,7 +254,7 @@ LINE is the erroneous line"
(goto-char (- (point) (length line))))
(goto-char temp))))
-(defun ly-parse-line-num (&optional buffer)
+(defun org-babel-lilypond-parse-line-num (&optional buffer)
"Extract error line number."
(when buffer
(set-buffer buffer))
@@ -276,12 +276,12 @@ LINE is the erroneous line"
nil)))
nil)))
-(defun ly-parse-error-line (file-name lineNo)
+(defun org-babel-lilypond-parse-error-line (file-name lineNo)
"Extract the erroneous line from the tangled .ly file
FILE-NAME is full path to lilypond file.
LINENO is the number of the erroneous line"
(with-temp-buffer
- (insert-file-contents (ly-switch-extension file-name ".ly")
+ (insert-file-contents (org-babel-lilypond-switch-extension file-name ".ly")
nil nil nil t)
(if (> lineNo 0)
(progn
@@ -290,128 +290,128 @@ LINENO is the number of the erroneous line"
(buffer-substring (point) (point-at-eol)))
nil)))
-(defun ly-attempt-to-open-pdf (file-name &optional test)
+(defun org-babel-lilypond-attempt-to-open-pdf (file-name &optional test)
"Attempt to display the generated pdf file
FILE-NAME is full path to lilypond file
If TEST is non-nil, the shell command is returned and is not run"
- (when ly-display-pdf-post-tangle
- (let ((pdf-file (ly-switch-extension file-name ".pdf")))
+ (when org-babel-lilypond-display-pdf-post-tangle
+ (let ((pdf-file (org-babel-lilypond-switch-extension file-name ".pdf")))
(if (file-exists-p pdf-file)
(let ((cmd-string
- (concat (ly-determine-pdf-path) " " pdf-file)))
+ (concat (org-babel-lilypond-determine-pdf-path) " " pdf-file)))
(if test
cmd-string
(start-process
"\"Audition pdf\""
"*lilypond*"
- (ly-determine-pdf-path)
+ (org-babel-lilypond-determine-pdf-path)
pdf-file)))
(message "No pdf file generated so can't display!")))))
-(defun ly-attempt-to-play-midi (file-name &optional test)
+(defun org-babel-lilypond-attempt-to-play-midi (file-name &optional test)
"Attempt to play the generated MIDI file
FILE-NAME is full path to lilypond file
If TEST is non-nil, the shell command is returned and is not run"
- (when ly-play-midi-post-tangle
- (let ((midi-file (ly-switch-extension file-name ".midi")))
+ (when org-babel-lilypond-play-midi-post-tangle
+ (let ((midi-file (org-babel-lilypond-switch-extension file-name ".midi")))
(if (file-exists-p midi-file)
(let ((cmd-string
- (concat (ly-determine-midi-path) " " midi-file)))
+ (concat (org-babel-lilypond-determine-midi-path) " " midi-file)))
(if test
cmd-string
(start-process
"\"Audition midi\""
"*lilypond*"
- (ly-determine-midi-path)
+ (org-babel-lilypond-determine-midi-path)
midi-file)))
(message "No midi file generated so can't play!")))))
-(defun ly-determine-ly-path (&optional test)
+(defun org-babel-lilypond-determine-ly-path (&optional test)
"Return correct path to ly binary depending on OS
If TEST is non-nil, it contains a simulation of the OS for test purposes"
(let ((sys-type
(or test system-type)))
(cond ((string= sys-type "darwin")
- ly-OSX-ly-path)
+ org-babel-lilypond-OSX-ly-path)
((string= sys-type "windows-nt")
- ly-w32-ly-path)
- (t ly-nix-ly-path))))
+ org-babel-lilypond-w32-ly-path)
+ (t org-babel-lilypond-nix-ly-path))))
-(defun ly-determine-pdf-path (&optional test)
+(defun org-babel-lilypond-determine-pdf-path (&optional test)
"Return correct path to pdf viewer depending on OS
If TEST is non-nil, it contains a simulation of the OS for test purposes"
(let ((sys-type
(or test system-type)))
(cond ((string= sys-type "darwin")
- ly-OSX-pdf-path)
+ org-babel-lilypond-OSX-pdf-path)
((string= sys-type "windows-nt")
- ly-w32-pdf-path)
- (t ly-nix-pdf-path))))
+ org-babel-lilypond-w32-pdf-path)
+ (t org-babel-lilypond-nix-pdf-path))))
-(defun ly-determine-midi-path (&optional test)
+(defun org-babel-lilypond-determine-midi-path (&optional test)
"Return correct path to midi player depending on OS
If TEST is non-nil, it contains a simulation of the OS for test purposes"
(let ((sys-type
(or test test system-type)))
(cond ((string= sys-type "darwin")
- ly-OSX-midi-path)
+ org-babel-lilypond-OSX-midi-path)
((string= sys-type "windows-nt")
- ly-w32-midi-path)
- (t ly-nix-midi-path))))
+ org-babel-lilypond-w32-midi-path)
+ (t org-babel-lilypond-nix-midi-path))))
-(defun ly-toggle-midi-play ()
+(defun org-babel-lilypond-toggle-midi-play ()
"Toggle whether midi will be played following a successful compilation."
(interactive)
- (setq ly-play-midi-post-tangle
- (not ly-play-midi-post-tangle))
+ (setq org-babel-lilypond-play-midi-post-tangle
+ (not org-babel-lilypond-play-midi-post-tangle))
(message (concat "Post-Tangle MIDI play has been "
- (if ly-play-midi-post-tangle
+ (if org-babel-lilypond-play-midi-post-tangle
"ENABLED." "DISABLED."))))
-(defun ly-toggle-pdf-display ()
+(defun org-babel-lilypond-toggle-pdf-display ()
"Toggle whether pdf will be displayed following a successful compilation."
(interactive)
- (setq ly-display-pdf-post-tangle
- (not ly-display-pdf-post-tangle))
+ (setq org-babel-lilypond-display-pdf-post-tangle
+ (not org-babel-lilypond-display-pdf-post-tangle))
(message (concat "Post-Tangle PDF display has been "
- (if ly-display-pdf-post-tangle
+ (if org-babel-lilypond-display-pdf-post-tangle
"ENABLED." "DISABLED."))))
-(defun ly-toggle-png-generation ()
+(defun org-babel-lilypond-toggle-png-generation ()
"Toggle whether png image will be generated by compilation."
(interactive)
- (setq ly-gen-png (not ly-gen-png))
+ (setq org-babel-lilypond-gen-png (not org-babel-lilypond-gen-png))
(message (concat "PNG image generation has been "
- (if ly-gen-png "ENABLED." "DISABLED."))))
+ (if org-babel-lilypond-gen-png "ENABLED." "DISABLED."))))
-(defun ly-toggle-html-generation ()
+(defun org-babel-lilypond-toggle-html-generation ()
"Toggle whether html will be generated by compilation."
(interactive)
- (setq ly-gen-html (not ly-gen-html))
+ (setq org-babel-lilypond-gen-html (not org-babel-lilypond-gen-html))
(message (concat "HTML generation has been "
- (if ly-gen-html "ENABLED." "DISABLED."))))
+ (if org-babel-lilypond-gen-html "ENABLED." "DISABLED."))))
-(defun ly-toggle-pdf-generation ()
+(defun org-babel-lilypond-toggle-pdf-generation ()
"Toggle whether pdf will be generated by compilation."
(interactive)
- (setq ly-gen-pdf (not ly-gen-pdf))
+ (setq org-babel-lilypond-gen-pdf (not org-babel-lilypond-gen-pdf))
(message (concat "PDF generation has been "
- (if ly-gen-pdf "ENABLED." "DISABLED."))))
+ (if org-babel-lilypond-gen-pdf "ENABLED." "DISABLED."))))
-(defun ly-toggle-arrange-mode ()
+(defun org-babel-lilypond-toggle-arrange-mode ()
"Toggle whether in Arrange mode or Basic mode."
(interactive)
- (setq ly-arrange-mode
- (not ly-arrange-mode))
+ (setq org-babel-lilypond-arrange-mode
+ (not org-babel-lilypond-arrange-mode))
(message (concat "Arrange mode has been "
- (if ly-arrange-mode "ENABLED." "DISABLED."))))
+ (if org-babel-lilypond-arrange-mode "ENABLED." "DISABLED."))))
-(defun ly-switch-extension (file-name ext)
+(defun org-babel-lilypond-switch-extension (file-name ext)
"Utility command to swap current FILE-NAME extension with EXT"
(concat (file-name-sans-extension
file-name) ext))
-(defun ly-get-header-args (mode)
+(defun org-babel-lilypond-get-header-args (mode)
"Default arguments to use when evaluating a lilypond
source block. These depend upon whether we are in arrange
mode i.e. ARRANGE-MODE is t"
@@ -425,11 +425,11 @@ mode i.e. ARRANGE-MODE is t"
'((:results . "file")
(:exports . "results")))))
-(defun ly-set-header-args (mode)
+(defun org-babel-lilypond-set-header-args (mode)
"Set org-babel-default-header-args:lilypond
-dependent on LY-ARRANGE-MODE"
+dependent on ORG-BABEL-LILYPOND-ARRANGE-MODE"
(setq org-babel-default-header-args:lilypond
- (ly-get-header-args mode)))
+ (org-babel-lilypond-get-header-args mode)))
(provide 'ob-lilypond)
diff --git a/lisp/ob-sh.el b/lisp/ob-sh.el
index 96f275b..856c7a0 100644
--- a/lisp/ob-sh.el
+++ b/lisp/ob-sh.el
@@ -123,7 +123,13 @@ Emacs-lisp table, otherwise return the results as a string."
(when (and session (not (string= session "none")))
(save-window-excursion
(or (org-babel-comint-buffer-livep session)
- (progn (shell session) (get-buffer (current-buffer)))))))
+ (progn
+ (shell session)
+ ;; Needed for Emacs 23 since the marker is initially
+ ;; undefined and the filter functions try to use it without
+ ;; checking.
+ (set-marker comint-last-output-start (point))
+ (get-buffer (current-buffer)))))))
(defvar org-babel-sh-eoe-indicator "echo 'org_babel_sh_eoe'"
"String to indicate that evaluation has completed.")
diff --git a/lisp/org-agenda.el b/lisp/org-agenda.el
index 0067165..c11c1c8 100644
--- a/lisp/org-agenda.el
+++ b/lisp/org-agenda.el
@@ -1472,6 +1472,7 @@ symbols specifying conditions when the grid should be displayed:
weekly if the agenda shows an entire week
today show grid on current date, independent of daily/weekly display
require-timed show grid only if at least one item has a time specification
+ remove-match skip grid times already present in an entry
The second item is a string which will be placed behind the grid time.
@@ -3352,7 +3353,7 @@ If AGENDA-BUFFER-NAME, use this as the buffer name for the agenda to write."
content)))
(find-file file)
(erase-buffer)
- (mapcar (lambda (s) (org-paste-subtree 1 s)) (reverse content))
+ (dolist (s content) (org-paste-subtree 1 s))
(write-file file)
(kill-buffer (current-buffer))
(message "Org file written to %s" file)))
@@ -5088,8 +5089,7 @@ of what a project is and how to check if it stuck, customize the variable
"Get the (Emacs Calendar) diary entries for DATE."
(require 'diary-lib)
(let* ((diary-fancy-buffer "*temporary-fancy-diary-buffer*")
- (diary-display-hook '(fancy-diary-display))
- (diary-display-function 'fancy-diary-display)
+ (diary-display-function 'diary-fancy-display)
(pop-up-frames nil)
(diary-list-entries-hook
(cons 'org-diary-default-entry diary-list-entries-hook))
@@ -9627,7 +9627,7 @@ This is a command that has to be installed in `calendar-mode-map'."
(overlay-put ov 'type 'org-marked-entry-overlay))
(end-of-line 1)
(or (ignore-errors
- (goto-char (next-single-property-change (point) 'txt)))
+ (goto-char (next-single-property-change (point) 'org-hd-marker)))
(beginning-of-line 2))
(while (and (get-char-property (point) 'invisible) (not (eobp)))
(beginning-of-line 2))
@@ -9645,7 +9645,7 @@ This is a command that has to be installed in `calendar-mode-map'."
(let ((entries-marked 0) txt-at-point)
(save-excursion
(goto-char (point-min))
- (goto-char (next-single-property-change (point) 'txt))
+ (goto-char (next-single-property-change (point) 'org-hd-marker))
(while (and (re-search-forward regexp nil t)
(setq txt-at-point (get-text-property (point) 'txt)))
(when (string-match regexp txt-at-point)
@@ -9681,7 +9681,7 @@ This is a command that has to be installed in `calendar-mode-map'."
(save-excursion
(goto-char (point-min))
(while (ignore-errors
- (goto-char (next-single-property-change (point) 'txt)))
+ (goto-char (next-single-property-change (point) 'org-hd-marker)))
(org-agenda-bulk-toggle))))
(defun org-agenda-bulk-toggle ()
diff --git a/lisp/org-element.el b/lisp/org-element.el
index bbed67a..eb8ff41 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -727,11 +727,11 @@ CONTENTS is the contents of the footnote-definition."
Return a list whose CAR is `headline' and CDR is a plist
containing `:raw-value', `:title', `:alt-title', `:begin',
-`:end', `:pre-blank', `:hiddenp', `:contents-begin' and
+`:end', `:pre-blank', `:hiddenp', `:contents-begin',
`:contents-end', `:level', `:priority', `:tags',
`:todo-keyword',`:todo-type', `:scheduled', `:deadline',
-`:closed', `:quotedp', `:archivedp', `:commentedp' and
-`:footnote-section-p' keywords.
+`:closed', `:quotedp', `:archivedp', `:commentedp',
+`:footnote-section-p' and `:post-blank' keywords.
The plist also contains any property set in the property drawer,
with its name in upper cases and colons added at the
@@ -870,38 +870,40 @@ CONTENTS is the contents of the element."
(org-element-property :tags headline))
(org-element-property :tags headline))))
(and tag-list
- (format ":%s:" (mapconcat 'identity tag-list ":")))))
+ (format ":%s:" (mapconcat #'identity tag-list ":")))))
(commentedp (org-element-property :commentedp headline))
(quotedp (org-element-property :quotedp headline))
(pre-blank (or (org-element-property :pre-blank headline) 0))
- (heading (concat (make-string (org-reduced-level level) ?*)
- (and todo (concat " " todo))
- (and quotedp (concat " " org-quote-string))
- (and commentedp (concat " " org-comment-string))
- (and priority
- (format " [#%s]" (char-to-string priority)))
- (cond ((and org-footnote-section
- (org-element-property
- :footnote-section-p headline))
- (concat " " org-footnote-section))
- (title (concat " " title))))))
- (concat heading
- ;; Align tags.
- (when tags
- (cond
- ((zerop org-tags-column) (format " %s" tags))
- ((< org-tags-column 0)
- (concat
- (make-string
- (max (- (+ org-tags-column (length heading) (length tags))) 1)
- ? )
- tags))
- (t
- (concat
- (make-string (max (- org-tags-column (length heading)) 1) ? )
- tags))))
- (make-string (1+ pre-blank) 10)
- contents)))
+ (heading
+ (concat (make-string (if org-odd-levels-only (1- (* level 2)) level)
+ ?*)
+ (and todo (concat " " todo))
+ (and quotedp (concat " " org-quote-string))
+ (and commentedp (concat " " org-comment-string))
+ (and priority (format " [#%s]" (char-to-string priority)))
+ " "
+ (if (and org-footnote-section
+ (org-element-property :footnote-section-p headline))
+ org-footnote-section
+ title))))
+ (concat
+ heading
+ ;; Align tags.
+ (when tags
+ (cond
+ ((zerop org-tags-column) (format " %s" tags))
+ ((< org-tags-column 0)
+ (concat
+ (make-string
+ (max (- (+ org-tags-column (length heading) (length tags))) 1)
+ ?\s)
+ tags))
+ (t
+ (concat
+ (make-string (max (- org-tags-column (length heading)) 1) ?\s)
+ tags))))
+ (make-string (1+ pre-blank) ?\n)
+ contents)))
;;;; Inlinetask
@@ -1310,36 +1312,36 @@ containing `:begin', `:end', `:hiddenp', `:contents-begin',
`:contents-end', `:post-blank' and `:post-affiliated' keywords.
Assume point is at the beginning of the property drawer."
- (save-excursion
- (let ((case-fold-search t))
- (if (not (save-excursion
- (re-search-forward "^[ \t]*:END:[ \t]*$" limit t)))
- ;; Incomplete drawer: parse it as a paragraph.
- (org-element-paragraph-parser limit affiliated)
- (save-excursion
- (let* ((drawer-end-line (match-beginning 0))
- (begin (car affiliated))
- (post-affiliated (point))
- (contents-begin (progn (forward-line)
- (and (< (point) drawer-end-line)
- (point))))
- (contents-end (and contents-begin drawer-end-line))
- (hidden (org-invisible-p2))
- (pos-before-blank (progn (goto-char drawer-end-line)
- (forward-line)
- (point)))
- (end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (line-beginning-position)))))
- (list 'property-drawer
- (nconc
- (list :begin begin
- :end end
- :hiddenp hidden
- :contents-begin contents-begin
- :contents-end contents-end
- :post-blank (count-lines pos-before-blank end)
- :post-affiliated post-affiliated)
- (cdr affiliated)))))))))
+ (let ((case-fold-search t))
+ (if (not (save-excursion (re-search-forward "^[ \t]*:END:[ \t]*$" limit t)))
+ ;; Incomplete drawer: parse it as a paragraph.
+ (org-element-paragraph-parser limit affiliated)
+ (save-excursion
+ (let* ((drawer-end-line (match-beginning 0))
+ (begin (car affiliated))
+ (post-affiliated (point))
+ (contents-begin
+ (progn
+ (forward-line)
+ (and (re-search-forward org-property-re drawer-end-line t)
+ (line-beginning-position))))
+ (contents-end (and contents-begin drawer-end-line))
+ (hidden (org-invisible-p2))
+ (pos-before-blank (progn (goto-char drawer-end-line)
+ (forward-line)
+ (point)))
+ (end (progn (skip-chars-forward " \r\t\n" limit)
+ (if (eobp) (point) (line-beginning-position)))))
+ (list 'property-drawer
+ (nconc
+ (list :begin begin
+ :end end
+ :hiddenp hidden
+ :contents-begin contents-begin
+ :contents-end contents-end
+ :post-blank (count-lines pos-before-blank end)
+ :post-affiliated post-affiliated)
+ (cdr affiliated))))))))
(defun org-element-property-drawer-interpreter (property-drawer contents)
"Interpret PROPERTY-DRAWER element as Org syntax.
@@ -2094,28 +2096,28 @@ LIMIT bounds the search.
Return a list whose CAR is `node-property' and CDR is a plist
containing `:key', `:value', `:begin', `:end' and `:post-blank'
keywords."
- (save-excursion
- (looking-at org-property-re)
- (let ((case-fold-search t)
- (begin (point))
- (key (org-match-string-no-properties 2))
- (value (org-match-string-no-properties 3))
- (pos-before-blank (progn (forward-line) (point)))
- (end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol)))))
- (list 'node-property
- (list :key key
- :value value
- :begin begin
- :end end
- :post-blank (count-lines pos-before-blank end))))))
+ (looking-at org-property-re)
+ (let ((begin (point))
+ (key (org-match-string-no-properties 2))
+ (value (org-match-string-no-properties 3))
+ (end (save-excursion
+ (end-of-line)
+ (if (re-search-forward org-property-re limit t)
+ (line-beginning-position)
+ limit))))
+ (list 'node-property
+ (list :key key
+ :value value
+ :begin begin
+ :end end
+ :post-blank 0))))
(defun org-element-node-property-interpreter (node-property contents)
"Interpret NODE-PROPERTY element as Org syntax.
CONTENTS is nil."
(format org-property-format
(format ":%s:" (org-element-property :key node-property))
- (org-element-property :value node-property)))
+ (or (org-element-property :value node-property) "")))
;;;; Paragraph
@@ -2481,7 +2483,7 @@ Assume point is at the beginning of the table."
(defun org-element-table-interpreter (table contents)
"Interpret TABLE element as Org syntax.
-CONTENTS is nil."
+CONTENTS is a string, if table's type is `org', or nil."
(if (eq (org-element-property :type table) 'table.el)
(org-remove-indentation (org-element-property :value table))
(concat (with-temp-buffer (insert contents)
@@ -4612,29 +4614,29 @@ indentation is not done with TAB characters."
(let* ((min-ind most-positive-fixnum)
find-min-ind ; For byte-compiler.
(find-min-ind
- (function
- ;; Return minimal common indentation within BLOB. This is
- ;; done by walking recursively BLOB and updating MIN-IND
- ;; along the way. FIRST-FLAG is non-nil when the first
- ;; string hasn't been seen yet. It is required as this
- ;; string is the only one whose indentation doesn't happen
- ;; after a newline character.
- (lambda (blob first-flag)
- (dolist (object (org-element-contents blob))
- (when (and first-flag (stringp object))
- (setq first-flag nil)
- (string-match "\\`\\( *\\)" object)
- (let ((len (length (match-string 1 object))))
- ;; An indentation of zero means no string will be
- ;; modified. Quit the process.
- (if (zerop len) (throw 'zero (setq min-ind 0))
- (setq min-ind (min len min-ind)))))
- (cond
- ((stringp object)
- (dolist (line (delq "" (cdr (org-split-string object " *\n"))))
- (setq min-ind (min (org-get-indentation line) min-ind))))
- ((memq (org-element-type object) org-element-recursive-objects)
- (funcall find-min-ind object first-flag))))))))
+ ;; Return minimal common indentation within BLOB. This is
+ ;; done by walking recursively BLOB and updating MIN-IND
+ ;; along the way. FIRST-FLAG is non-nil when the first
+ ;; string hasn't been seen yet. It is required as this
+ ;; string is the only one whose indentation doesn't happen
+ ;; after a newline character.
+ (lambda (blob first-flag)
+ (dolist (object (org-element-contents blob))
+ (when (and first-flag (stringp object))
+ (setq first-flag nil)
+ (string-match "\\` *" object)
+ (let ((len (match-end 0)))
+ ;; An indentation of zero means no string will be
+ ;; modified. Quit the process.
+ (if (zerop len) (throw 'zero (setq min-ind 0))
+ (setq min-ind (min len min-ind)))))
+ (cond
+ ((stringp object)
+ (dolist (line (cdr (org-split-string object " *\n")))
+ (unless (string= line "")
+ (setq min-ind (min (org-get-indentation line) min-ind)))))
+ ((memq (org-element-type object) org-element-recursive-objects)
+ (funcall find-min-ind object first-flag)))))))
;; Find minimal indentation in ELEMENT.
(catch 'zero (funcall find-min-ind element (not ignore-first)))
(if (or (zerop min-ind) (= min-ind most-positive-fixnum)) element
diff --git a/lisp/org-loaddefs.el b/lisp/org-loaddefs.el
index 4695dad..4f937cc 100644
--- a/lisp/org-loaddefs.el
+++ b/lisp/org-loaddefs.el
@@ -292,7 +292,7 @@ used to limit the exported source code blocks by language.
;;;;;; org-search-view org-agenda-list org-batch-store-agenda-views
;;;;;; org-store-agenda-views org-batch-agenda-csv org-batch-agenda
;;;;;; org-agenda org-toggle-sticky-agenda) "org-agenda" "org-agenda.el"
-;;;;;; (21464 32404))
+;;;;;; (21562 65218))
;;; Generated autoloads from org-agenda.el
(autoload 'org-toggle-sticky-agenda "org-agenda" "\
@@ -644,8 +644,8 @@ Extract anniversaries from BBDB for display in the agenda.
;;;***
;;;### (autoloads (org-capture-import-remember-templates org-capture
-;;;;;; org-capture-string) "org-capture" "org-capture.el" (21464
-;;;;;; 32404))
+;;;;;; org-capture-string) "org-capture" "org-capture.el" (21562
+;;;;;; 3391))
;;; Generated autoloads from org-capture.el
(autoload 'org-capture-string "org-capture" "\
@@ -821,7 +821,7 @@ Otherwise, return nil.
;;;### (autoloads (org-agenda-columns org-insert-columns-dblock org-dblock-write:columnview
;;;;;; org-columns-number-to-string org-columns-compute org-columns
;;;;;; org-columns-get-format-and-top-level org-columns-remove-overlays)
-;;;;;; "org-colview" "org-colview.el" (21464 32404))
+;;;;;; "org-colview" "org-colview.el" (21562 3391))
;;; Generated autoloads from org-colview.el
(autoload 'org-columns-remove-overlays "org-colview" "\
@@ -885,7 +885,7 @@ Turn on or update column view in the agenda.
;;;***
;;;### (autoloads (org-check-version) "org-compat" "org-compat.el"
-;;;;;; (21464 32404))
+;;;;;; (21562 3391))
;;; Generated autoloads from org-compat.el
(autoload 'org-check-version "org-compat" "\
@@ -910,7 +910,7 @@ tree can be found.
;;;***
;;;### (autoloads (org-element-context org-element-at-point org-element-interpret-data)
-;;;;;; "org-element" "org-element.el" "54914322a8abcdde97acf3e16c5153bb")
+;;;;;; "org-element" "org-element.el" "40b84110bb3b104027a4d7ca4fda8d30")
;;; Generated autoloads from org-element.el
(autoload 'org-element-interpret-data "org-element" "\
@@ -1156,7 +1156,7 @@ Dispatch to the appropriate function to store a link to an IRC session.
;;;***
;;;### (autoloads (org-load-noerror-mustsuffix) "org-macs" "org-macs.el"
-;;;;;; (21464 32404))
+;;;;;; (21562 3391))
;;; Generated autoloads from org-macs.el
(autoload 'org-load-noerror-mustsuffix "org-macs" "\
@@ -1219,7 +1219,7 @@ line directly before or after the table.
;;;;;; org-table-begin org-table-align org-table-export org-table-import
;;;;;; org-table-convert-region org-table-create org-table-create-or-convert-from-region
;;;;;; org-table-create-with-table\.el) "org-table" "org-table.el"
-;;;;;; "eb0c58570f974a880afb6dbc990b4604")
+;;;;;; "9b6e8818ec6951cc97eba4e5d0822cef")
;;; Generated autoloads from org-table.el
(autoload 'org-table-create-with-table\.el "org-table" "\
@@ -1891,7 +1891,7 @@ replace any running timer.
;;;***
;;;### (autoloads (org-git-version org-release) "org-version" "org-version.el"
-;;;;;; (21464 43563))
+;;;;;; (21562 65320))
;;; Generated autoloads from org-version.el
(autoload 'org-release "org-version" "\
@@ -1917,7 +1917,7 @@ The location of ODT styles.")
;;;;;; org-run-like-in-org-mode turn-on-orgstruct++ turn-on-orgstruct
;;;;;; orgstruct-mode org-global-cycle org-cycle org-mode org-clock-persistence-insinuate
;;;;;; turn-on-orgtbl org-version org-babel-load-file org-babel-do-load-languages)
-;;;;;; "org" "org.el" (21464 32405))
+;;;;;; "org" "org.el" (21562 3391))
;;; Generated autoloads from org.el
(autoload 'org-babel-do-load-languages "org" "\
@@ -2140,7 +2140,7 @@ Call the customize function with org as argument.
;;;### (autoloads (org-ascii-publish-to-utf8 org-ascii-publish-to-latin1
;;;;;; org-ascii-publish-to-ascii org-ascii-export-to-ascii org-ascii-export-as-ascii)
-;;;;;; "ox-ascii" "ox-ascii.el" "b6167fea7127509f3138b6133b279333")
+;;;;;; "ox-ascii" "ox-ascii.el" "8bba507846964285c7ecb40e66b6afe3")
;;; Generated autoloads from ox-ascii.el
(autoload 'org-ascii-export-as-ascii "ox-ascii" "\
@@ -2243,7 +2243,7 @@ Return output file name.
;;;### (autoloads (org-beamer-publish-to-pdf org-beamer-publish-to-latex
;;;;;; org-beamer-insert-options-template org-beamer-select-environment
;;;;;; org-beamer-export-to-pdf org-beamer-export-to-latex org-beamer-export-as-latex
-;;;;;; org-beamer-mode) "ox-beamer" "ox-beamer.el" "0348058cc4cbc1e72026db6215d71d9f")
+;;;;;; org-beamer-mode) "ox-beamer" "ox-beamer.el" "6e708817388023e1e1df3de8f27188ce")
;;; Generated autoloads from ox-beamer.el
(autoload 'org-beamer-mode "ox-beamer" "\
@@ -2385,7 +2385,7 @@ Return output file name.
;;;### (autoloads (org-html-publish-to-html org-html-export-to-html
;;;;;; org-html-convert-region-to-html org-html-export-as-html org-html-htmlize-generate-css)
-;;;;;; "ox-html" "ox-html.el" "d5c9c4a0e85bc0c8d4341a5ae06255a3")
+;;;;;; "ox-html" "ox-html.el" "65604b7a2a80c70979b37eb44119d6f9")
;;; Generated autoloads from ox-html.el
(put 'org-html-head-include-default-style 'safe-local-variable 'booleanp)
@@ -2545,7 +2545,7 @@ The file is stored under the name chosen in
;;;### (autoloads (org-latex-publish-to-pdf org-latex-publish-to-latex
;;;;;; org-latex-export-to-pdf org-latex-export-to-latex org-latex-convert-region-to-latex
-;;;;;; org-latex-export-as-latex) "ox-latex" "ox-latex.el" "89b0609c28a8054b8c4bb3c76caaa41e")
+;;;;;; org-latex-export-as-latex) "ox-latex" "ox-latex.el" "6277aa86c5275b5aae6c2c2d578a04fb")
;;; Generated autoloads from ox-latex.el
(autoload 'org-latex-export-as-latex "ox-latex" "\
@@ -2671,7 +2671,7 @@ Return output file name.
;;;***
;;;### (autoloads (org-md-export-to-markdown org-md-convert-region-to-md
-;;;;;; org-md-export-as-markdown) "ox-md" "ox-md.el" "050e805f316d1908d1309facb5cb7d5b")
+;;;;;; org-md-export-as-markdown) "ox-md" "ox-md.el" "02d27e093680dff82b16ebedcda8cba8")
;;; Generated autoloads from ox-md.el
(autoload 'org-md-export-as-markdown "ox-md" "\
@@ -2733,7 +2733,7 @@ Return output file's name.
;;;***
;;;### (autoloads (org-odt-convert org-odt-export-to-odt org-odt-export-as-odf-and-open
-;;;;;; org-odt-export-as-odf) "ox-odt" "ox-odt.el" "5c27e9fcb578e9179a9788880e547448")
+;;;;;; org-odt-export-as-odf) "ox-odt" "ox-odt.el" "688d009902f7a23ab86bb93a843abdf5")
;;; Generated autoloads from ox-odt.el
(put 'org-odt-preferred-output-format 'safe-local-variable 'stringp)
@@ -2870,7 +2870,7 @@ Return output file name.
;;;### (autoloads (org-publish-current-project org-publish-current-file
;;;;;; org-publish-all org-publish) "ox-publish" "ox-publish.el"
-;;;;;; "4ebb7ea664336aa5b508cba81203f819")
+;;;;;; "e9f7e2ede20ea11ead21108abf19db90")
;;; Generated autoloads from ox-publish.el
(defalias 'org-publish-project 'org-publish)
@@ -2914,7 +2914,7 @@ the project.
;;;***
;;;### (autoloads (org-texinfo-convert-region-to-texinfo org-texinfo-publish-to-texinfo)
-;;;;;; "ox-texinfo" "ox-texinfo.el" "2b693692963e10fb670fdafe4674f894")
+;;;;;; "ox-texinfo" "ox-texinfo.el" "ae3f8dd17715c8093138512ae3c347cc")
;;; Generated autoloads from ox-texinfo.el
(autoload 'org-texinfo-publish-to-texinfo "ox-texinfo" "\
@@ -2940,7 +2940,7 @@ this command to convert it.
;;;### (autoloads (org-export-dispatch org-export-to-file org-export-to-buffer
;;;;;; org-export-insert-default-template org-export-replace-region-by
-;;;;;; org-export-string-as org-export-as) "ox" "ox.el" "94545423f577521d4c74654b04f13148")
+;;;;;; org-export-string-as org-export-as) "ox" "ox.el" "abbaf953c164e76b9957d5ea22f805c8")
;;; Generated autoloads from ox.el
(autoload 'org-export-as "ox" "\
diff --git a/lisp/org-src.el b/lisp/org-src.el
index f870b2c..752fa30 100644
--- a/lisp/org-src.el
+++ b/lisp/org-src.el
@@ -376,23 +376,21 @@ the display of windows containing the Org buffer and the code buffer."
(when (fboundp edit-prep-func)
(funcall edit-prep-func full-info)))
(or org-edit-src-code-timer
+ (zerop org-edit-src-auto-save-idle-delay)
(setq org-edit-src-code-timer
- (unless (zerop org-edit-src-auto-save-idle-delay)
- (run-with-idle-timer
- org-edit-src-auto-save-idle-delay t
- (lambda ()
- (cond
- ((and (string-match "\*Org Src" (buffer-name))
- (buffer-modified-p))
- (org-edit-src-save))
- ((not
- (delq nil (mapcar
- (lambda (b)
- (string-match "\*Org Src" (buffer-name b)))
- (buffer-list))))
- (cancel-timer org-edit-src-code-timer)
- (setq org-edit-src-code-timer)))))))))
- t)))
+ (run-with-idle-timer
+ org-edit-src-auto-save-idle-delay t
+ (lambda ()
+ (cond
+ ((org-string-match-p "\\`\\*Org Src" (buffer-name))
+ (when (buffer-modified-p) (org-edit-src-save)))
+ ((not (org-some (lambda (b)
+ (org-string-match-p "\\`\\*Org Src"
+ (buffer-name b)))
+ (buffer-list)))
+ (cancel-timer org-edit-src-code-timer)
+ (setq org-edit-src-code-timer nil))))))))
+ t)))
(defun org-edit-src-continue (e)
"Continue editing source blocks." ;; Fixme: be more accurate
@@ -757,8 +755,8 @@ with \",*\", \",#+\", \",,*\" and \",,#+\"."
(delete-region beg (max beg end))
(unless (string-match "\\`[ \t]*\\'" code)
(insert code))
- ;; Make sure the overlay stays in place
- (when (eq context 'save) (move-overlay ovl beg (point)))
+ ;; Make sure the overlay stays in place
+ (when (eq context 'save) (move-overlay ovl beg (point)))
(goto-char beg)
(if single (just-one-space)))
(if (memq t (mapcar (lambda (overlay)
@@ -774,9 +772,6 @@ with \",*\", \",#+\", \",,*\" and \",,#+\"."
(unless (eq context 'save)
(move-marker beg nil)
(move-marker end nil)))
- (when org-edit-src-code-timer
- (cancel-timer org-edit-src-code-timer)
- (setq org-edit-src-code-timer nil))
(unless (eq context 'save)
(when org-edit-src-saved-temp-window-config
(set-window-configuration org-edit-src-saved-temp-window-config)
diff --git a/lisp/org-table.el b/lisp/org-table.el
index f19c027..30a66c9 100644
--- a/lisp/org-table.el
+++ b/lisp/org-table.el
@@ -436,11 +436,15 @@ available parameters."
"[ \t]*|[ \t]*")))))))
(defvar org-table-clean-did-remove-column nil) ; dynamically scoped
-(defun org-table-clean-before-export (lines)
+(defun org-table-clean-before-export (lines &optional maybe-quoted)
"Check if the table has a marking column.
If yes remove the column and the special lines."
- (let ((special "^[ \t]*| *[#!$*_^/] *|")
- (ignore "^[ \t]*| *[!$_^/] *|"))
+ (let ((special (if maybe-quoted
+ "^[ \t]*| *\\\\?[\#!$*_^/ ] *|"
+ "^[ \t]*| *[\#!$*_^/ ] *|"))
+ (ignore (if maybe-quoted
+ "^[ \t]*| *\\\\?[!$_^/] *|"
+ "^[ \t]*| *[!$_^/] *|")))
(setq org-table-clean-did-remove-column
(not (memq nil
(mapcar
diff --git a/lisp/org-version.el b/lisp/org-version.el
index ee0a178..e8c6044 100644
--- a/lisp/org-version.el
+++ b/lisp/org-version.el
@@ -5,13 +5,13 @@
(defun org-release ()
"The release version of org-mode.
Inserted by installing org-mode or when a release is made."
- (let ((org-release "8.2.7c"))
+ (let ((org-release "8.2.10"))
org-release))
;;;###autoload
(defun org-git-version ()
"The Git version of org-mode.
Inserted by installing org-mode or when a release is made."
- (let ((org-git-version "8.2.7c-dist"))
+ (let ((org-git-version "8.2.10-dist"))
org-git-version))
;;;###autoload
(defvar org-odt-data-dir "/usr/share/emacs/etc/org"
diff --git a/lisp/org.el b/lisp/org.el
index 9c18677..2b5603c 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -6152,13 +6152,21 @@ Use `org-reduced-level' to remove the effect of `org-odd-levels'."
(defvar org-font-lock-keywords nil)
(defsubst org-re-property (property &optional literal allow-null)
- "Return a regexp matching a PROPERTY line.
- Match group 3 will be set to the value if it exists."
- (concat "^\\(?4:[ \t]*\\)\\(?1::\\(?2:"
- (if literal property (regexp-quote property))
- "\\):\\)[ \t]+\\(?3:[^ \t\r\n]"
- (if allow-null "*")
- ".*?\\)\\(?5:[ \t]*\\)$"))
+ "Return a regexp matching a PROPERTY line.
+
+When optional argument LITERAL is non-nil, do not quote PROPERTY.
+This is useful when PROPERTY is a regexp. When ALLOW-NULL is
+non-nil, match properties even without a value.
+
+Match group 3 is set to the value when it exists. If there is no
+value and ALLOW-NULL is non-nil, it is set to the empty string."
+ (concat
+ "^\\(?4:[ \t]*\\)"
+ (format "\\(?1::\\(?2:%s\\):\\)"
+ (if literal property (regexp-quote property)))
+ (if allow-null
+ "\\(?:\\(?3:$\\)\\|[ \t]+\\(?3:.*?\\)\\)\\(?5:[ \t]*\\)$"
+ "[ \t]+\\(?3:[^ \r\t\n]+.*?\\)\\(?5:[ \t]*\\)$")))
(defconst org-property-re
(org-re-property ".*?" 'literal t)
@@ -6720,7 +6728,8 @@ in special contexts.
(setq org-cycle-global-status 'overview)
(run-hook-with-args 'org-cycle-hook 'overview)))))
-(defvar org-called-with-limited-levels);Dyn-bound in ̀org-with-limited-levels'.
+(defvar org-called-with-limited-levels nil
+ "Non-nil when `org-with-limited-levels' is currently active.")
(defun org-cycle-internal-local ()
"Do the local cycling action."
@@ -7724,13 +7733,12 @@ command."
"Make the number of empty lines before current exactly N.
So this will delete or add empty lines."
(save-excursion
- (goto-char (point-at-bol))
- (if (looking-back "\\s-+" nil 'greedy)
- (replace-match ""))
- (or (bobp) (insert "\n"))
- (while (> N 0)
- (insert "\n")
- (setq N (1- N)))))
+ (beginning-of-line)
+ (let ((p (point)))
+ (skip-chars-backward " \r\t\n")
+ (unless (bolp) (forward-line))
+ (delete-region (point) p))
+ (when (> N 0) (insert (make-string N ?\n)))))
(defun org-get-heading (&optional no-tags no-todo)
"Return the heading of the current entry, without the stars.
@@ -9091,14 +9099,16 @@ if `orgstruct-heading-prefix-regexp' is not empty."
(if fallback
(let* ((orgstruct-mode)
(binding
- (loop with key = ,key
- for rep in
- '(nil
- ("<\\([^>]*\\)tab>" . "\\1TAB")
- ("<\\([^>]*\\)return>" . "\\1RET")
- ("<\\([^>]*\\)escape>" . "\\1ESC")
- ("<\\([^>]*\\)delete>" . "\\1DEL"))
- do
+ (let ((key ,key))
+ (catch 'exit
+ (dolist
+ (rep
+ '(nil
+ ("<\\([^>]*\\)tab>" . "\\1TAB")
+ ("<\\([^>]*\\)return>" . "\\1RET")
+ ("<\\([^>]*\\)escape>" . "\\1ESC")
+ ("<\\([^>]*\\)delete>" . "\\1DEL"))
+ nil)
(when rep
(setq key (read-kbd-macro
(let ((case-fold-search))
@@ -9106,7 +9116,8 @@ if `orgstruct-heading-prefix-regexp' is not empty."
(car rep)
(cdr rep)
(key-description key))))))
- thereis (key-binding key))))
+ (when (key-binding key)
+ (throw 'exit (key-binding key))))))))
(if (keymapp binding)
(org-set-transient-map binding)
(let ((func (or binding
diff --git a/lisp/ox-ascii.el b/lisp/ox-ascii.el
index 4a6696e..cd2a9af 100644
--- a/lisp/ox-ascii.el
+++ b/lisp/ox-ascii.el
@@ -423,17 +423,17 @@ equivalent to `left'. For a justification that doesn't also fill
string, see `org-ascii--justify-string'.
Return nil if S isn't a string."
- ;; Don't fill paragraph when break should be preserved.
- (cond ((not (stringp s)) nil)
- ((plist-get info :preserve-breaks) s)
- (t (let ((double-space-p sentence-end-double-space))
- (with-temp-buffer
- (let ((fill-column text-width)
- (use-hard-newlines t)
- (sentence-end-double-space double-space-p))
- (insert s)
- (fill-region (point-min) (point-max) justify))
- (buffer-string))))))
+ (when (stringp s)
+ (let ((double-space-p sentence-end-double-space))
+ (with-temp-buffer
+ (let ((fill-column text-width)
+ (use-hard-newlines t)
+ (sentence-end-double-space double-space-p))
+ (insert (if (plist-get info :preserve-breaks)
+ (replace-regexp-in-string "\n" hard-newline s)
+ s))
+ (fill-region (point-min) (point-max) justify))
+ (buffer-string)))))
(defun org-ascii--justify-string (s text-width how)
"Justify string S.
@@ -463,7 +463,7 @@ Empty lines are not indented."
"Return string S with a partial box to its left.
INFO is a plist used as a communication channel."
(let ((utf8p (eq (plist-get info :ascii-charset) 'utf-8)))
- (format (if utf8p "╭────\n%s\n╰────" ",----\n%s\n`----")
+ (format (if utf8p "┌────\n%s\n└────" ",----\n%s\n`----")
(replace-regexp-in-string
"^" (if utf8p "│ " "| ")
;; Remove last newline character.
diff --git a/lisp/ox-beamer.el b/lisp/ox-beamer.el
index 1d487e9..5ab805d 100644
--- a/lisp/ox-beamer.el
+++ b/lisp/ox-beamer.el
@@ -687,7 +687,7 @@ used as a communication channel."
(cond
((equal type "radio")
(let ((destination (org-export-resolve-radio-link link info)))
- (when destination
+ (if (not destination) contents
(format "\\hyperlink%s{%s}{%s}"
(or (org-beamer--element-has-overlay-p link) "")
(org-export-solidify-link-text
diff --git a/lisp/ox-html.el b/lisp/ox-html.el
index 3eaeb0a..23498b2 100644
--- a/lisp/ox-html.el
+++ b/lisp/ox-html.el
@@ -2275,83 +2275,70 @@ holding contextual information."
"Transcode a HEADLINE element from Org to HTML.
CONTENTS holds the contents of the headline. INFO is a plist
holding contextual information."
- ;; Empty contents?
- (setq contents (or contents ""))
- (let* ((numberedp (org-export-numbered-headline-p headline info))
- (level (org-export-get-relative-level headline info))
- (text (org-export-data (org-element-property :title headline) 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)))
- (section-number (and (org-export-numbered-headline-p headline info)
- (mapconcat 'number-to-string
- (org-export-get-headline-number
- headline info) ".")))
- ;; Create the headline text.
- (full-text (org-html-format-headline--wrap headline info)))
- (cond
- ;; Case 1: This is a footnote section: ignore it.
- ((org-element-property :footnote-section-p headline) nil)
- ;; Case 2. 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.
- ((org-export-low-level-p headline info)
- ;; Build the real contents of the sub-tree.
- (let* ((type (if numberedp 'ordered 'unordered))
- (itemized-body (org-html-format-list-item
- contents type nil info nil full-text)))
- (concat
- (and (org-export-first-sibling-p headline info)
- (org-html-begin-plain-list type))
- itemized-body
- (and (org-export-last-sibling-p headline info)
- (org-html-end-plain-list type)))))
- ;; Case 3. Standard headline. Export it as a section.
- (t
- (let* ((section-number (mapconcat 'number-to-string
- (org-export-get-headline-number
- headline info) "-"))
- (ids (remove 'nil
- (list (org-element-property :CUSTOM_ID headline)
- (concat "sec-" section-number)
- (org-element-property :ID headline))))
- (preferred-id (car ids))
- (extra-ids (cdr ids))
- (extra-class (org-element-property :HTML_CONTAINER_CLASS headline))
- (level1 (+ level (1- org-html-toplevel-hlevel)))
- (first-content (car (org-element-contents headline))))
- (format "<%s id=\"%s\" class=\"%s\">%s%s</%s>\n"
- (org-html--container headline info)
- (format "outline-container-%s"
- (or (org-element-property :CUSTOM_ID headline)
- (concat "sec-" section-number)))
- (concat (format "outline-%d" level1) (and extra-class " ")
- extra-class)
- (format "\n<h%d id=\"%s\">%s%s</h%d>\n"
- level1
- preferred-id
- (mapconcat
- (lambda (x)
- (let ((id (org-export-solidify-link-text
- (if (org-uuidgen-p x) (concat "ID-" x)
- x))))
- (org-html--anchor id)))
- extra-ids "")
- full-text
- level1)
- ;; When there is no section, pretend there is an empty
- ;; one to get the correct <div class="outline- ...>
- ;; which is needed by `org-info.js'.
- (if (not (eq (org-element-type first-content) 'section))
- (concat (org-html-section first-content "" info)
- contents)
- contents)
- (org-html--container headline info)))))))
+ (unless (org-element-property :footnote-section-p headline)
+ (let* ((contents (or contents ""))
+ (numberedp (org-export-numbered-headline-p headline info))
+ (level (org-export-get-relative-level headline info))
+ (text (org-export-data (org-element-property :title headline) 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)))
+ (section-number (mapconcat #'number-to-string
+ (org-export-get-headline-number
+ headline info) "-"))
+ (ids (delq 'nil
+ (list (org-element-property :CUSTOM_ID headline)
+ (concat "sec-" section-number)
+ (org-element-property :ID headline))))
+ (preferred-id (car ids))
+ (extra-ids (mapconcat
+ (lambda (id)
+ (org-html--anchor
+ (org-export-solidify-link-text
+ (if (org-uuidgen-p id) (concat "ID-" id) id))))
+ (cdr ids) ""))
+ ;; Create the headline text.
+ (full-text (org-html-format-headline--wrap headline info)))
+ (if (org-export-low-level-p headline info)
+ ;; This is a deep sub-tree: export it as a list item.
+ (let* ((type (if numberedp 'ordered 'unordered))
+ (itemized-body
+ (org-html-format-list-item
+ contents type nil info nil
+ (concat (org-html--anchor preferred-id) extra-ids
+ full-text))))
+ (concat
+ (and (org-export-first-sibling-p headline info)
+ (org-html-begin-plain-list type))
+ itemized-body
+ (and (org-export-last-sibling-p headline info)
+ (org-html-end-plain-list type))))
+ ;; Standard headline. Export it as a section.
+ (let ((extra-class (org-element-property :HTML_CONTAINER_CLASS headline))
+ (level1 (+ level (1- org-html-toplevel-hlevel)))
+ (first-content (car (org-element-contents headline))))
+ (format "<%s id=\"%s\" class=\"%s\">%s%s</%s>\n"
+ (org-html--container headline info)
+ (format "outline-container-%s"
+ (or (org-element-property :CUSTOM_ID headline)
+ (concat "sec-" section-number)))
+ (concat (format "outline-%d" level1) (and extra-class " ")
+ extra-class)
+ (format "\n<h%d id=\"%s\">%s%s</h%d>\n"
+ level1 preferred-id extra-ids full-text level1)
+ ;; When there is no section, pretend there is an
+ ;; empty one to get the correct <div class="outline-
+ ;; ...> which is needed by `org-info.js'.
+ (if (not (eq (org-element-type first-content) 'section))
+ (concat (org-html-section first-content "" info)
+ contents)
+ contents)
+ (org-html--container headline info)))))))
(defun org-html--container (headline info)
(or (org-element-property :HTML_CONTAINER headline)
@@ -2720,7 +2707,7 @@ INFO is a plist holding contextual information. See
;; link's description.
((string= type "radio")
(let ((destination (org-export-resolve-radio-link link info)))
- (when destination
+ (if (not destination) desc
(format "<a href=\"#%s\"%s>%s</a>"
(org-export-solidify-link-text
(org-element-property :value destination))
diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el
index 5f171da..2c71f7d 100644
--- a/lisp/ox-latex.el
+++ b/lisp/ox-latex.el
@@ -1809,7 +1809,7 @@ INFO is a plist holding contextual information. See
;; description.
((string= type "radio")
(let ((destination (org-export-resolve-radio-link link info)))
- (when destination
+ (if (not destination) desc
(format "\\hyperref[%s]{%s}"
(org-export-solidify-link-text
(org-element-property :value destination))
@@ -1842,7 +1842,8 @@ INFO is a plist holding contextual information. See
'number-to-string
(org-export-get-headline-number destination info)
"-"))))
- (if (and (plist-get info :section-numbers) (not desc))
+ (if (and (not desc)
+ (org-export-numbered-headline-p destination info))
(format "\\ref{%s}" label)
(format "\\hyperref[%s]{%s}" label
(or desc
diff --git a/lisp/ox-md.el b/lisp/ox-md.el
index f1c4db9..99a4ae0 100644
--- a/lisp/ox-md.el
+++ b/lisp/ox-md.el
@@ -102,21 +102,28 @@ This variable can be set to either `atx' or `setext'."
TREE is the parse tree being exported. BACKEND is the export
back-end used. INFO is a plist used as a communication channel.
-Make sure there's no blank line before a plain list, unless it is
-located right after a paragraph. Otherwise, add a blank line
-between elements. Blank lines between items are preserved.
+Enforce a blank line between elements. There are three
+exceptions to this rule:
+
+ 1. Preserve blank lines between sibling items in a plain list,
+
+ 2. Outside of plain lists, preserve blank lines between
+ a paragraph and a plain list,
+
+ 3. In an item, remove any blank line before the very first
+ paragraph and the next sub-list.
Assume BACKEND is `md'."
(org-element-map tree (remq 'item org-element-all-elements)
- (lambda (elem)
- (org-element-put-property
- elem :post-blank
- (if (and (eq (org-element-type (org-export-get-next-element elem info))
- 'plain-list)
- (not (and (eq (org-element-type elem) 'paragraph)
- (org-export-get-previous-element elem info))))
- 0
- 1))))
+ (lambda (e)
+ (cond
+ ((not (and (eq (org-element-type e) 'paragraph)
+ (eq (org-element-type (org-export-get-next-element e info))
+ 'plain-list)))
+ (org-element-put-property e :post-blank 1))
+ ((not (eq (org-element-type (org-element-property :parent e)) 'item)))
+ (t (org-element-put-property
+ e :post-blank (if (org-export-get-previous-element e info) 1 0))))))
;; Return updated tree.
tree)
@@ -287,57 +294,65 @@ a communication channel."
(concat (file-name-sans-extension raw-path) ".md")
raw-path))))
(type (org-element-property :type link)))
- (cond ((member type '("custom-id" "id"))
- (let ((destination (org-export-resolve-id-link link info)))
- (if (stringp destination) ; External file.
- (let ((path (funcall link-org-files-as-md destination)))
- (if (not contents) (format "<%s>" path)
- (format "[%s](%s)" contents path)))
- (concat
- (and contents (concat contents " "))
- (format "(%s)"
- (format (org-export-translate "See section %s" :html info)
- (mapconcat 'number-to-string
- (org-export-get-headline-number
- destination info)
- ".")))))))
- ((org-export-inline-image-p link org-html-inline-image-rules)
- (let ((path (let ((raw-path (org-element-property :path link)))
- (if (not (file-name-absolute-p raw-path)) raw-path
- (expand-file-name raw-path))))
- (caption (org-export-data
- (org-export-get-caption
- (org-export-get-parent-element link)) info)))
- (format "![img](%s)"
- (if (not (org-string-nw-p caption)) path
- (format "%s \"%s\"" path caption)))))
- ((string= type "coderef")
- (let ((ref (org-element-property :path link)))
- (format (org-export-get-coderef-format ref contents)
- (org-export-resolve-coderef ref info))))
- ((equal type "radio") contents)
- ((equal type "fuzzy")
- (let ((destination (org-export-resolve-fuzzy-link link info)))
- (if (org-string-nw-p contents) contents
- (when destination
- (let ((number (org-export-get-ordinal destination info)))
- (when number
- (if (atom number) (number-to-string number)
- (mapconcat 'number-to-string number "."))))))))
- (t (let* ((raw-path (org-element-property :path link))
- (path
- (cond
- ((member type '("http" "https" "ftp"))
- (concat type ":" raw-path))
- ((string= type "file")
- (let ((path (funcall link-org-files-as-md raw-path)))
- (if (not (file-name-absolute-p path)) path
- ;; If file path is absolute, prepend it
- ;; with "file:" component.
- (concat "file:" path))))
- (t raw-path))))
- (if (not contents) (format "<%s>" path)
- (format "[%s](%s)" contents path)))))))
+ (cond
+ ((member type '("custom-id" "id"))
+ (let ((destination (org-export-resolve-id-link link info)))
+ (if (stringp destination) ; External file.
+ (let ((path (funcall link-org-files-as-md destination)))
+ (if (not contents) (format "<%s>" path)
+ (format "[%s](%s)" contents path)))
+ (concat
+ (and contents (concat contents " "))
+ (format "(%s)"
+ (format (org-export-translate "See section %s" :html info)
+ (mapconcat 'number-to-string
+ (org-export-get-headline-number
+ destination info)
+ ".")))))))
+ ((org-export-inline-image-p link org-html-inline-image-rules)
+ (let ((path (let ((raw-path (org-element-property :path link)))
+ (if (not (file-name-absolute-p raw-path)) raw-path
+ (expand-file-name raw-path))))
+ (caption (org-export-data
+ (org-export-get-caption
+ (org-export-get-parent-element link)) info)))
+ (format "![img](%s)"
+ (if (not (org-string-nw-p caption)) path
+ (format "%s \"%s\"" path caption)))))
+ ((string= type "coderef")
+ (let ((ref (org-element-property :path link)))
+ (format (org-export-get-coderef-format ref contents)
+ (org-export-resolve-coderef ref info))))
+ ((equal type "radio") contents)
+ ((equal type "fuzzy")
+ (let ((destination (org-export-resolve-fuzzy-link link info)))
+ (if (org-string-nw-p contents) contents
+ (when destination
+ (let ((number (org-export-get-ordinal destination info)))
+ (when number
+ (if (atom number) (number-to-string number)
+ (mapconcat 'number-to-string number "."))))))))
+ ;; Link type is handled by a special function.
+ ((let ((protocol (nth 2 (assoc type org-link-protocols))))
+ (and (functionp protocol)
+ (funcall protocol
+ (org-link-unescape (org-element-property :path link))
+ contents
+ 'md))))
+ (t (let* ((raw-path (org-element-property :path link))
+ (path
+ (cond
+ ((member type '("http" "https" "ftp"))
+ (concat type ":" raw-path))
+ ((string= type "file")
+ (let ((path (funcall link-org-files-as-md raw-path)))
+ (if (not (file-name-absolute-p path)) path
+ ;; If file path is absolute, prepend it
+ ;; with "file:" component.
+ (concat "file:" path))))
+ (t raw-path))))
+ (if (not contents) (format "<%s>" path)
+ (format "[%s](%s)" contents path)))))))
;;;; Paragraph
diff --git a/lisp/ox-odt.el b/lisp/ox-odt.el
index 6640e8a..03b3214 100644
--- a/lisp/ox-odt.el
+++ b/lisp/ox-odt.el
@@ -2733,7 +2733,7 @@ INFO is a plist holding contextual information. See
;; link's description.
((string= type "radio")
(let ((destination (org-export-resolve-radio-link link info)))
- (when destination
+ (if (not destination) desc
(format
"<text:bookmark-ref text:reference-format=\"text\" text:ref-name=\"OrgXref.%s\">%s</text:bookmark-ref>"
(org-export-solidify-link-text
diff --git a/lisp/ox-publish.el b/lisp/ox-publish.el
index 1dc790d..efc70d2 100644
--- a/lisp/ox-publish.el
+++ b/lisp/ox-publish.el
@@ -881,7 +881,7 @@ publishing will be done asynchronously, in another process."
;; project is still a string here.
(list (assoc project org-publish-project-alist)))))
(if async
- (org-export-async-start 'ignore
+ (org-export-async-start (lambda (results) nil)
`(let ((org-publish-use-timestamps-flag
(if ',force nil ,org-publish-use-timestamps-flag)))
(org-publish-projects ',project-alist)))
@@ -899,7 +899,7 @@ optional argument ASYNC, publishing will be done asynchronously,
in another process."
(interactive "P")
(if async
- (org-export-async-start 'ignore
+ (org-export-async-start (lambda (results) nil)
`(progn
(when ',force (org-publish-remove-all-timestamps))
(let ((org-publish-use-timestamps-flag
@@ -921,7 +921,7 @@ asynchronously, in another process."
(interactive "P")
(let ((file (buffer-file-name (buffer-base-buffer))))
(if async
- (org-export-async-start 'ignore
+ (org-export-async-start (lambda (results) nil)
`(let ((org-publish-use-timestamps-flag
(if ',force nil ,org-publish-use-timestamps-flag)))
(org-publish-file ,file)))
diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el
index a961d7a..37841d7 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -21,38 +21,7 @@
;;; Commentary:
;;
-;; This library implements a Texinfo back-end for Org generic
-;; exporter.
-;;
-;; To test it, run
-;;
-;; M-: (org-export-to-buffer 'texinfo "*Test Texinfo*") RET
-;;
-;; in an Org mode buffer then switch to the buffer to see the Texinfo
-;; export. See ox.el for more details on how this exporter works.
-;;
-
-;; It introduces nine new buffer keywords: "TEXINFO_CLASS",
-;; "TEXINFO_FILENAME", "TEXINFO_HEADER", "TEXINFO_POST_HEADER",
-;; "TEXINFO_DIR_CATEGORY", "TEXINFO_DIR_TITLE", "TEXINFO_DIR_DESC"
-;; "SUBTITLE" and "SUBAUTHOR".
-
-;;
-;; It introduces 1 new headline property keywords:
-;; "TEXINFO_MENU_TITLE" for optional menu titles.
-;;
-;; To include inline code snippets (for example for generating @kbd{}
-;; and @key{} commands), the following export-snippet keys are
-;; accepted:
-;;
-;; texinfo
-;; info
-;;
-;; You can add them for export snippets via any of the below:
-;;
-;; (add-to-list 'org-export-snippet-translation-alist
-;; '("info" . "texinfo"))
-;;
+;; See Org manual for details.
;;; Code:
@@ -70,8 +39,8 @@
(center-block . org-texinfo-center-block)
(clock . org-texinfo-clock)
(code . org-texinfo-code)
- (comment . org-texinfo-comment)
- (comment-block . org-texinfo-comment-block)
+ (comment . (lambda (&rest args) ""))
+ (comment-block . (lambda (&rest args) ""))
(drawer . org-texinfo-drawer)
(dynamic-block . org-texinfo-dynamic-block)
(entity . org-texinfo-entity)
@@ -114,13 +83,14 @@
:export-block "TEXINFO"
:filters-alist
'((:filter-headline . org-texinfo-filter-section-blank-lines)
+ (:filter-parse-tree . org-texinfo--normalize-headlines)
(:filter-section . org-texinfo-filter-section-blank-lines))
:menu-entry
'(?i "Export to Texinfo"
((?t "As TEXI file" org-texinfo-export-to-texinfo)
(?i "As INFO file" org-texinfo-export-to-info)))
:options-alist
- '((:texinfo-filename "TEXINFO_FILENAME" nil org-texinfo-filename t)
+ '((:texinfo-filename "TEXINFO_FILENAME" nil nil t)
(:texinfo-class "TEXINFO_CLASS" nil org-texinfo-default-class t)
(:texinfo-header "TEXINFO_HEADER" nil nil newline)
(:texinfo-post-header "TEXINFO_POST_HEADER" nil nil newline)
@@ -128,7 +98,8 @@
(:subauthor "SUBAUTHOR" nil nil newline)
(:texinfo-dircat "TEXINFO_DIR_CATEGORY" nil nil t)
(:texinfo-dirtitle "TEXINFO_DIR_TITLE" nil nil t)
- (:texinfo-dirdesc "TEXINFO_DIR_DESC" nil nil t)))
+ (:texinfo-dirdesc "TEXINFO_DIR_DESC" nil nil t)
+ (:texinfo-printed-title "TEXINFO_PRINTED_TITLE" nil nil t)))
@@ -141,12 +112,7 @@
:package-version '(Org . "8.0")
:group 'org-export)
-;;; Preamble
-
-(defcustom org-texinfo-filename ""
- "Default filename for Texinfo output."
- :group 'org-export-texinfo
- :type '(string :tag "Export Filename"))
+;;;; Preamble
(defcustom org-texinfo-coding-system nil
"Default document encoding for Texinfo output.
@@ -162,19 +128,42 @@ If `nil' it will default to `buffer-file-coding-system'."
(defcustom org-texinfo-classes
'(("info"
- "\\input texinfo @c -*- texinfo -*-"
+ "@documentencoding AUTO\n@documentlanguage AUTO"
("@chapter %s" . "@unnumbered %s")
("@section %s" . "@unnumberedsec %s")
("@subsection %s" . "@unnumberedsubsec %s")
("@subsubsection %s" . "@unnumberedsubsubsec %s")))
"Alist of Texinfo classes and associated header and structure.
-If #+Texinfo_CLASS is set in the buffer, use its value and the
+If #+TEXINFO_CLASS is set in the buffer, use its value and the
associated information. Here is the structure of each cell:
\(class-name
header-string
- \(numbered-section . unnumbered-section\)
- ...\)
+ \(numbered-section . unnumbered-section)
+ ...)
+
+
+The header string
+-----------------
+
+The header string is inserted in the header of the generated
+document, right after \"@setfilename\" and \"@settitle\"
+commands.
+
+If it contains the special string
+
+ \"@documentencoding AUTO\"
+
+\"AUTO\" will be replaced with an appropriate coding system. See
+`org-texinfo-coding-system' for more information. Likewise, if
+the string contains the special string
+
+ \"@documentlanguage AUTO\"
+
+\"AUTO\" will be replaced with the language defined in the
+buffer, through #+LANGUAGE keyword, or globally, with
+`org-export-default-language', which see.
+
The sectioning structure
------------------------
@@ -186,10 +175,12 @@ section string and will be replaced by the title of the section.
Instead of a list of sectioning commands, you can also specify
a function name. That function will be called with two
-parameters, the \(reduced) level of the headline, and a predicate
+parameters, the reduced) level of the headline, and a predicate
non-nil when the headline should be numbered. It must return
a format string in which the section title will be added."
:group 'org-export-texinfo
+ :version "24.4"
+ :package-version '(Org . "8.2")
:type '(repeat
(list (string :tag "Texinfo class")
(string :tag "Texinfo header")
@@ -200,7 +191,7 @@ a format string in which the section title will be added."
(string :tag "unnumbered"))
(function :tag "Hook computing sectioning"))))))
-;;; Headline
+;;;; Headline
(defcustom org-texinfo-format-headline-function 'ignore
"Function to format headline text.
@@ -230,22 +221,16 @@ order to reproduce the default set-up:
:group 'org-export-texinfo
:type 'function)
-;;; Node listing (menu)
+;;;; Node listing (menu)
(defcustom org-texinfo-node-description-column 32
- "Column at which to start the description in the node
- listings.
-
+ "Column at which to start the description in the node listings.
If a node title is greater than this length, the description will
be placed after the end of the title."
:group 'org-export-texinfo
:type 'integer)
-;;; Footnotes
-;;
-;; Footnotes are inserted directly
-
-;;; Timestamps
+;;;; Timestamps
(defcustom org-texinfo-active-timestamp-format "@emph{%s}"
"A printf format string to be applied to active timestamps."
@@ -262,14 +247,14 @@ be placed after the end of the title."
:group 'org-export-texinfo
:type 'string)
-;;; Links
+;;;; Links
(defcustom org-texinfo-link-with-unknown-path-format "@indicateurl{%s}"
"Format string for links with unknown path type."
:group 'org-export-texinfo
:type 'string)
-;;; Tables
+;;;; Tables
(defcustom org-texinfo-tables-verbatim nil
"When non-nil, tables are exported verbatim."
@@ -285,14 +270,14 @@ When nil, no transformation is made."
:group 'org-export-texinfo
:type '(choice
(string :tag "Format string")
- (const :tag "No formatting")))
+ (const :tag "No formatting" nil)))
(defcustom org-texinfo-def-table-markup "@samp"
"Default setting for @table environments."
:group 'org-export-texinfo
:type 'string)
-;;; Text markup
+;;;; Text markup
(defcustom org-texinfo-text-markup-alist '((bold . "@strong{%s}")
(code . code)
@@ -316,7 +301,7 @@ returned as-is."
:type 'alist
:options '(bold code italic verbatim comment))
-;;; Drawers
+;;;; Drawers
(defcustom org-texinfo-format-drawer-function
(lambda (name contents) contents)
@@ -331,10 +316,10 @@ The function should return the string to be exported.
The default function simply returns the value of CONTENTS."
:group 'org-export-texinfo
:version "24.4"
- :package-version '(Org . "8.3")
+ :package-version '(Org . "8.2")
:type 'function)
-;;; Inlinetasks
+;;;; Inlinetasks
(defcustom org-texinfo-format-inlinetask-function 'ignore
"Function called to format an inlinetask in Texinfo code.
@@ -370,18 +355,13 @@ in order to mimic default behavior:
:group 'org-export-texinfo
:type 'function)
-;;; Src blocks
-;;
-;; Src Blocks are example blocks, except for LISP
-
-;;; Compilation
+;;;; Compilation
-(defcustom org-texinfo-info-process
- '("makeinfo %f")
+(defcustom org-texinfo-info-process '("makeinfo %f")
"Commands to process a Texinfo file to an INFO file.
This is list of strings, each of them will be given to the shell
as a command. %f in the command will be replaced by the full
-file name, %b by the file base name \(i.e without extension) and
+file name, %b by the file base name (i.e without extension) and
%o by the base directory of the file."
:group 'org-export-texinfo
:type '(repeat :tag "Shell command sequence"
@@ -403,12 +383,13 @@ set `org-texinfo-logfiles-extensions'."
:group 'org-export-latex
:type 'boolean)
-
;;; Constants
+
(defconst org-texinfo-max-toc-depth 4
- "Maximum depth for creation of detailed menu listings. Beyond
- this depth Texinfo will not recognize the nodes and will cause
- errors. Left as a constant in case this value ever changes.")
+ "Maximum depth for creation of detailed menu listings.
+Beyond this depth, Texinfo will not recognize the nodes and will
+cause errors. Left as a constant in case this value ever
+changes.")
(defconst org-texinfo-supported-coding-systems
'("US-ASCII" "UTF-8" "ISO-8859-15" "ISO-8859-1" "ISO-8859-2" "koi8-r" "koi8-u")
@@ -425,6 +406,31 @@ If two strings share the same prefix (e.g. \"ISO-8859-1\" and
(let ((blanks (make-string 2 ?\n)))
(replace-regexp-in-string "\n\\(?:\n[ \t]*\\)*\\'" blanks headline)))
+(defun org-texinfo--normalize-headlines (tree back-end info)
+ "Normalize headlines in TREE.
+
+BACK-END is the symbol specifying back-end used for export. INFO
+is a plist used as a communication channel.
+
+Make sure every headline in TREE contains a section, since those
+are required to install a menu. Also put exactly one blank line
+at the end of each section.
+
+Return new tree."
+ (org-element-map tree 'headline
+ (lambda (hl)
+ (org-element-put-property hl :post-blank 1)
+ (let ((contents (org-element-contents hl)))
+ (when contents
+ (let ((first (org-element-map contents '(headline section)
+ #'identity info t)))
+ (unless (eq (org-element-type first) 'section)
+ (apply #'org-element-set-contents
+ hl
+ (cons `(section (:parent ,hl)) contents)))))))
+ info)
+ tree)
+
(defun org-texinfo--find-verb-separator (s)
"Return a character not used in string S.
This is used to choose a separator for constructs like \\verb."
@@ -433,18 +439,6 @@ This is used to choose a separator for constructs like \\verb."
when (not (string-match (regexp-quote (char-to-string c)) s))
return (char-to-string c))))
-(defun org-texinfo--make-option-string (options)
- "Return a comma separated string of keywords and values.
-OPTIONS is an alist where the key is the options keyword as
-a string, and the value a list containing the keyword value, or
-nil."
- (mapconcat (lambda (pair)
- (concat (first pair)
- (when (> (length (second pair)) 0)
- (concat "=" (second pair)))))
- options
- ","))
-
(defun org-texinfo--text-markup (text markup)
"Format TEXT depending on MARKUP text markup.
See `org-texinfo-text-markup-alist' for details."
@@ -472,207 +466,44 @@ See `org-texinfo-text-markup-alist' for details."
;; Else use format string.
(t (format fmt text)))))
-(defun org-texinfo--get-node (headline info)
- "Return node entry associated to HEADLINE.
-INFO is a plist used as a communication channel."
- (let ((menu-title (org-export-get-alt-title headline info)))
- (org-texinfo--sanitize-menu
- (replace-regexp-in-string
- "%" "%%"
- (if menu-title (org-export-data menu-title info)
- (org-texinfo--sanitize-headline
- (org-element-property :title headline) info))))))
-
-;;; Headline sanitizing
-
-(defun org-texinfo--sanitize-headline (headline info)
- "Remove all formatting from the text of a headline for use in
- node and menu listing."
- (mapconcat 'identity
- (org-texinfo--sanitize-headline-contents headline info) " "))
-
-(defun org-texinfo--sanitize-headline-contents (headline info)
- "Retrieve the content of the headline.
-
-Any content that can contain further formatting is checked
-recursively, to ensure that nested content is also properly
-retrieved."
- (loop for contents in headline append
- (cond
- ;; already a string
- ((stringp contents)
- (list (replace-regexp-in-string " $" "" contents)))
- ;; Is exported as-is (value)
- ((org-element-map contents '(verbatim code)
- (lambda (value) (org-element-property :value value)) info))
- ;; Has content and recurse into the content
- ((org-element-contents contents)
- (org-texinfo--sanitize-headline-contents
- (org-element-contents contents) info)))))
-
-;;; Menu sanitizing
-
-(defun org-texinfo--sanitize-menu (title)
- "Remove invalid characters from TITLE for use in menus and
-nodes.
-
-Based on Texinfo specifications, the following must be removed:
-@ { } ( ) : . ,"
- (replace-regexp-in-string "[@{}():,.]" "" title))
-
-;;; Content sanitizing
+(defun org-texinfo--get-node (blob info)
+ "Return node or anchor associated to BLOB.
+BLOB is an element or object. INFO is a plist used as
+a communication channel. The function guarantees the node or
+anchor name is unique."
+ (let ((cache (plist-get info :texinfo-node-cache)))
+ (or (cdr (assq blob cache))
+ (let ((name
+ (org-texinfo--sanitize-node
+ (case (org-element-type blob)
+ (headline
+ (org-export-data (org-export-get-alt-title blob info) info))
+ ((radio-target target) (org-element-property :value blob))
+ (otherwise (or (org-element-property :name blob) ""))))))
+ ;; Ensure NAME is unique.
+ (while (rassoc name cache) (setq name (concat name "x")))
+ (plist-put info :texinfo-node-cache (cons (cons blob name) cache))
+ name))))
+
+;;;; Menu sanitizing
+
+(defun org-texinfo--sanitize-node (title)
+ "Bend string TITLE to node line requirements.
+Trim string and collapse multiple whitespace characters as they
+are not significant. Also remove the following characters: @
+{ } ( ) : . ,"
+ (replace-regexp-in-string
+ "[:,.]" ""
+ (replace-regexp-in-string
+ "\\`(\\(.*)\\)" "[\\1"
+ (org-trim (replace-regexp-in-string "[ \t]\\{2,\\}" " " title)))))
+
+;;;; Content sanitizing
(defun org-texinfo--sanitize-content (text)
- "Ensure characters are properly escaped when used in headlines or blocks.
-
-Escape characters are: @ { }"
- (replace-regexp-in-string "\\\([@{}]\\\)" "@\\1" text))
-
-;;; Menu creation
-
-(defun org-texinfo--build-menu (tree level info &optional detailed)
- "Create the @menu/@end menu information from TREE at headline
-level LEVEL.
-
-TREE contains the parse-tree to work with, either of the entire
-document or of a specific parent headline. LEVEL indicates what
-level of headlines to look at when generating the menu. INFO is
-a plist containing contextual information.
-
-Detailed determines whether to build a single level of menu, or
-recurse into all children as well."
- (let ((menu (org-texinfo--generate-menu-list tree level info))
- output text-menu)
- (cond
- (detailed
- ;; Looping is done within the menu generation.
- (setq text-menu (org-texinfo--generate-detailed menu level info)))
- (t
- (setq text-menu (org-texinfo--generate-menu-items menu info))))
- (when text-menu
- (setq output (org-texinfo--format-menu text-menu))
- (mapconcat 'identity output "\n"))))
-
-(defun org-texinfo--generate-detailed (menu level info)
- "Generate a detailed listing of all subheadings within MENU starting at LEVEL.
-
-MENU is the parse-tree to work with. LEVEL is the starting level
-for the menu headlines and from which recursion occurs. INFO is
-a plist containing contextual information."
- (when level
- (let ((max-depth (min org-texinfo-max-toc-depth
- (plist-get info :headline-levels))))
- (when (> max-depth level)
- (loop for headline in menu append
- (let* ((title (org-texinfo--menu-headlines headline info))
- ;; Create list of menu entries for the next level
- (sublist (org-texinfo--generate-menu-list
- headline (1+ level) info))
- ;; Generate the menu items for that level. If
- ;; there are none omit that heading completely,
- ;; otherwise join the title to it's related entries.
- (submenu (if (org-texinfo--generate-menu-items sublist info)
- (append (list title)
- (org-texinfo--generate-menu-items sublist info))
- 'nil))
- ;; Start the process over the next level down.
- (recursion (org-texinfo--generate-detailed sublist (1+ level) info)))
- (setq recursion (append submenu recursion))
- recursion))))))
-
-(defun org-texinfo--generate-menu-list (tree level info)
- "Generate the list of headlines that are within a given level
-of the tree for further formatting.
-
-TREE is the parse-tree containing the headlines. LEVEL is the
-headline level to generate a list of. INFO is a plist holding
-contextual information."
- (org-element-map tree 'headline
- (lambda (head)
- (and (= (org-export-get-relative-level head info) level)
- ;; Do not take note of footnotes or copying headlines.
- (not (org-element-property :COPYING head))
- (not (org-element-property :footnote-section-p head))
- ;; Collect headline.
- head))
- info))
-
-(defun org-texinfo--generate-menu-items (items info)
- "Generate a list of headline information from the listing ITEMS.
-
-ITEMS is a list of the headlines to be converted into entries.
-INFO is a plist containing contextual information.
-
-Returns a list containing the following information from each
-headline: length, title, description. This is used to format the
-menu using `org-texinfo--format-menu'."
- (loop for headline in items collect
- (let* ((menu-title (org-texinfo--sanitize-menu
- (org-export-data
- (org-export-get-alt-title headline info)
- info)))
- (title (org-texinfo--sanitize-menu
- (org-texinfo--sanitize-headline
- (org-element-property :title headline) info)))
- (descr (org-export-data
- (org-element-property :DESCRIPTION headline)
- info))
- (menu-entry (if (string= "" menu-title) title menu-title))
- (len (length menu-entry))
- (output (list len menu-entry descr)))
- output)))
-
-(defun org-texinfo--menu-headlines (headline info)
- "Retrieve the title from HEADLINE.
-
-INFO is a plist holding contextual information.
-
-Return the headline as a list of (length title description) with
-length of -1 and nil description. This is used in
-`org-texinfo--format-menu' to identify headlines as opposed to
-entries."
- (let ((title (org-export-data
- (org-element-property :title headline) info)))
- (list -1 title 'nil)))
-
-(defun org-texinfo--format-menu (text-menu)
- "Format the TEXT-MENU items to be properly printed in the menu.
-
-Each entry in the menu should be provided as (length title
-description).
-
-Headlines in the detailed menu are given length -1 to ensure they
-are never confused with other entries. They also have no
-description.
-
-Other menu items are output as:
- Title:: description
-
-With the spacing between :: and description based on the length
-of the longest menu entry."
-
- (let (output)
- (setq output
- (mapcar (lambda (name)
- (let* ((title (nth 1 name))
- (desc (nth 2 name))
- (length (nth 0 name))
- (column (max
- ;;6 is "* " ":: " for inserted text
- length
- (-
- org-texinfo-node-description-column
- 6)))
- (spacing (- column length)
- ))
- (if (> length -1)
- (concat "* " title ":: "
- (make-string spacing ?\s)
- (if desc
- (concat desc)))
- (concat "\n" title "\n"))))
- text-menu))
- output))
+ "Escape special characters in string TEXT.
+Special characters are: @ { }"
+ (replace-regexp-in-string "[@{}]" "@\\&" text))
;;; Template
@@ -680,145 +511,127 @@ of the longest menu entry."
"Return complete document string after Texinfo conversion.
CONTENTS is the transcoded contents string. INFO is a plist
holding export options."
- (let* ((title (org-export-data (plist-get info :title) info))
- (info-filename (or (plist-get info :texinfo-filename)
- (file-name-nondirectory
- (org-export-output-file-name ".info"))))
- (author (org-export-data (plist-get info :author) info))
- (lang (org-export-data (plist-get info :language) info))
- (texinfo-header (plist-get info :texinfo-header))
- (texinfo-post-header (plist-get info :texinfo-post-header))
- (subtitle (plist-get info :subtitle))
- (subauthor (plist-get info :subauthor))
- (class (plist-get info :texinfo-class))
- (header (nth 1 (assoc class org-texinfo-classes)))
- (copying
- (org-element-map (plist-get info :parse-tree) 'headline
- (lambda (hl) (and (org-element-property :COPYING hl) hl)) info t))
- (dircat (plist-get info :texinfo-dircat))
- (dirtitle (plist-get info :texinfo-dirtitle))
- (dirdesc (plist-get info :texinfo-dirdesc))
- ;; Spacing to align description (column 32 - 3 for `* ' and
- ;; `.' in text.
- (dirspacing (- 29 (length dirtitle)))
- (menu (org-texinfo-make-menu info 'main))
- (detail-menu (org-texinfo-make-menu info 'detailed)))
+ (let ((title (org-export-data (plist-get info :title) info))
+ ;; Copying data is the contents of the first headline in
+ ;; parse tree with a non-nil copying property.
+ (copying (org-element-map (plist-get info :parse-tree) 'headline
+ (lambda (hl)
+ (and (org-not-nil (org-element-property :COPYING hl))
+ (org-element-contents hl)))
+ info t)))
(concat
- ;; Header
- header "\n"
+ "\\input texinfo @c -*- texinfo -*-\n"
"@c %**start of header\n"
- ;; Filename and Title
- "@setfilename " info-filename "\n"
- "@settitle " title "\n"
- ;; Coding system.
- (format
- "@documentencoding %s\n"
- (catch 'coding-system
- (let ((case-fold-search t)
- (name (symbol-name (or org-texinfo-coding-system
- buffer-file-coding-system))))
- (dolist (system org-texinfo-supported-coding-systems "UTF-8")
- (when (org-string-match-p (regexp-quote system) name)
- (throw 'coding-system system))))))
- "\n"
- (format "@documentlanguage %s\n" lang)
- "\n\n"
- "@c Version and Contact Info\n"
- "@set AUTHOR " author "\n"
-
- ;; Additional Header Options set by `#+TEXINFO_HEADER
- (if texinfo-header
- (concat "\n"
- texinfo-header
- "\n"))
-
- "@c %**end of header\n"
- "@finalout\n"
- "\n\n"
-
- ;; Additional Header Options set by #+TEXINFO_POST_HEADER
- (if texinfo-post-header
- (concat "\n"
- texinfo-post-header
- "\n"))
-
- ;; Copying
- "@copying\n"
- ;; Only export the content of the headline, do not need the
- ;; initial headline.
- (org-export-data (nth 2 copying) info)
- "@end copying\n"
- "\n\n"
-
- ;; Info directory information
- ;; Only supply if both title and category are provided
- (if (and dircat dirtitle)
+ (let ((file (or (plist-get info :texinfo-filename)
+ (let ((f (plist-get info :output-file)))
+ (and f (concat (file-name-sans-extension f) ".info"))))))
+ (and file (format "@setfilename %s\n" file)))
+ (format "@settitle %s\n" title)
+ ;; Insert class-defined header.
+ (org-element-normalize-string
+ (let ((header (nth 1 (assoc (plist-get info :texinfo-class)
+ org-texinfo-classes)))
+ (coding
+ (catch 'coding-system
+ (let ((case-fold-search t)
+ (name (symbol-name (or org-texinfo-coding-system
+ buffer-file-coding-system))))
+ (dolist (system org-texinfo-supported-coding-systems "UTF-8")
+ (when (org-string-match-p (regexp-quote system) name)
+ (throw 'coding-system system))))))
+ (language (plist-get info :language))
+ (case-fold-search nil))
+ ;; Auto coding system.
+ (replace-regexp-in-string
+ "^@documentencoding \\(AUTO\\)$"
+ coding
+ (replace-regexp-in-string
+ "^@documentlanguage \\(AUTO\\)$" language header t nil 1) t nil 1)))
+ ;; Additional header options set by #+TEXINFO_HEADER.
+ (let ((texinfo-header (plist-get info :texinfo-header)))
+ (and texinfo-header (org-element-normalize-string texinfo-header)))
+ "@c %**end of header\n\n"
+ ;; Additional options set by #+TEXINFO_POST_HEADER.
+ (let ((texinfo-post-header (plist-get info :texinfo-post-header)))
+ (and texinfo-post-header
+ (org-element-normalize-string texinfo-post-header)))
+ ;; Copying.
+ (and copying
+ (format "@copying\n%s@end copying\n\n"
+ (org-element-normalize-string
+ (org-export-data copying info))))
+ ;; Info directory information. Only supply if both title and
+ ;; category are provided.
+ (let ((dircat (plist-get info :texinfo-dircat))
+ (dirtitle
+ (let ((title (plist-get info :texinfo-dirtitle)))
+ (and title
+ (string-match "^\\(?:\\* \\)?\\(.*?\\)\\(\\.\\)?$" title)
+ (format "* %s." (match-string 1 title))))))
+ (when (and dircat dirtitle)
(concat "@dircategory " dircat "\n"
"@direntry\n"
- "* " dirtitle "."
- (make-string dirspacing ?\s)
- dirdesc "\n"
- "@end direntry\n"))
- "\n\n"
-
+ (let ((dirdesc
+ (let ((desc (plist-get info :texinfo-dirdesc)))
+ (cond ((not desc) nil)
+ ((org-string-match-p "\\.$" desc) desc)
+ (t (concat desc "."))))))
+ (if dirdesc (format "%-23s %s" dirtitle dirdesc) dirtitle))
+ "\n"
+ "@end direntry\n\n")))
;; Title
+ "@finalout\n"
"@titlepage\n"
- "@title " title "\n\n"
- (if subtitle
- (concat "@subtitle " subtitle "\n"))
- "@author " author "\n"
- (if subauthor
- (concat subauthor "\n"))
- "\n"
- "@c The following two commands start the copyright page.\n"
- "@page\n"
- "@vskip 0pt plus 1filll\n"
- "@insertcopying\n"
+ (format "@title %s\n" (or (plist-get info :texinfo-printed-title) title))
+ (let ((subtitle (plist-get info :subtitle)))
+ (and subtitle
+ (org-element-normalize-string
+ (replace-regexp-in-string "^" "@subtitle " subtitle))))
+ (when (plist-get info :with-author)
+ (concat
+ ;; Primary author.
+ (let ((author (org-string-nw-p
+ (org-export-data (plist-get info :author) info)))
+ (email (and (plist-get info :with-email)
+ (org-string-nw-p
+ (org-export-data (plist-get info :email) info)))))
+ (cond ((and author email)
+ (format "@author %s (@email{%s})\n" author email))
+ (author (format "@author %s\n" author))
+ (email (format "@author @email{%s}\n" email))))
+ ;; Other authors.
+ (let ((subauthor (plist-get info :subauthor)))
+ (and subauthor
+ (org-element-normalize-string
+ (replace-regexp-in-string "^" "@author " subauthor))))))
+ (and copying "@page\n@vskip 0pt plus 1filll\n@insertcopying\n")
"@end titlepage\n\n"
- "@c Output the table of contents at the beginning.\n"
- "@contents\n\n"
-
+ ;; Table of contents.
+ (and (plist-get info :with-toc) "@contents\n\n")
;; Configure Top Node when not for Tex
"@ifnottex\n"
"@node Top\n"
- "@top " title " Manual\n"
- "@insertcopying\n"
+ (format "@top %s\n" title)
+ (and copying "@insertcopying\n")
"@end ifnottex\n\n"
-
- ;; Do not output menus if they are empty
- (if menu
- ;; Menu
- (concat "@menu\n"
- menu
- "\n\n"
- ;; Detailed Menu
- (if detail-menu
- (concat "@detailmenu\n"
- " --- The Detailed Node Listing ---\n"
- detail-menu
- "\n\n"
- "@end detailmenu\n"))
- "@end menu\n"))
- "\n\n"
-
- ;; Document's body.
- contents
+ ;; Menu.
+ (org-texinfo-make-menu (plist-get info :parse-tree) info 'master)
"\n"
+ ;; Document's body.
+ contents "\n"
;; Creator.
- (let ((creator-info (plist-get info :with-creator)))
- (cond
- ((not creator-info) "")
- ((eq creator-info 'comment)
- (format "@c %s\n" (plist-get info :creator)))
- (t (concat (plist-get info :creator) "\n"))))
+ (case (plist-get info :with-creator)
+ ((nil) nil)
+ (comment (format "@c %s\n" (plist-get info :creator)))
+ (otherwise (concat (plist-get info :creator) "\n")))
;; Document end.
- "\n@bye")))
+ "@bye")))
;;; Transcode Functions
-;;; Bold
+;;;; Bold
(defun org-texinfo-bold (bold contents info)
"Transcode BOLD from Org to Texinfo.
@@ -826,7 +639,7 @@ CONTENTS is the text with bold markup. INFO is a plist holding
contextual information."
(org-texinfo--text-markup contents 'bold))
-;;; Center Block
+;;;; Center Block
(defun org-texinfo-center-block (center-block contents info)
"Transcode a CENTER-BLOCK element from Org to Texinfo.
@@ -834,7 +647,7 @@ CONTENTS holds the contents of the block. INFO is a plist used
as a communication channel."
contents)
-;;; Clock
+;;;; Clock
(defun org-texinfo-clock (clock contents info)
"Transcode a CLOCK element from Org to Texinfo.
@@ -851,7 +664,7 @@ information."
(and time (format " (%s)" time)))))
"@*"))
-;;; Code
+;;;; Code
(defun org-texinfo-code (code contents info)
"Transcode a CODE object from Org to Texinfo.
@@ -859,23 +672,7 @@ CONTENTS is nil. INFO is a plist used as a communication
channel."
(org-texinfo--text-markup (org-element-property :value code) 'code))
-;;; Comment
-
-(defun org-texinfo-comment (comment contents info)
- "Transcode a COMMENT object from Org to Texinfo.
-CONTENTS is the text in the comment. INFO is a plist holding
-contextual information."
- (org-texinfo--text-markup (org-element-property :value comment) 'comment))
-
-;;; Comment Block
-
-(defun org-texinfo-comment-block (comment-block contents info)
- "Transcode a COMMENT-BLOCK object from Org to Texinfo.
-CONTENTS is the text within the block. INFO is a plist holding
-contextual information."
- (format "@ignore\n%s@end ignore" (org-element-property :value comment-block)))
-
-;;; Drawer
+;;;; Drawer
(defun org-texinfo-drawer (drawer contents info)
"Transcode a DRAWER element from Org to Texinfo.
@@ -886,15 +683,15 @@ holding contextual information."
name contents)))
output))
-;;; Dynamic Block
+;;;; Dynamic Block
(defun org-texinfo-dynamic-block (dynamic-block contents info)
"Transcode a DYNAMIC-BLOCK element from Org to Texinfo.
CONTENTS holds the contents of the block. INFO is a plist
-holding contextual information. See `org-export-data'."
+holding contextual information."
contents)
-;;; Entity
+;;;; Entity
(defun org-texinfo-entity (entity contents info)
"Transcode an ENTITY object from Org to Texinfo.
@@ -903,7 +700,7 @@ contextual information."
(let ((ent (org-element-property :latex entity)))
(if (org-element-property :latex-math-p entity) (format "@math{%s}" ent) ent)))
-;;; Example Block
+;;;; Example Block
(defun org-texinfo-example-block (example-block contents info)
"Transcode an EXAMPLE-BLOCK element from Org to Texinfo.
@@ -912,7 +709,7 @@ information."
(format "@verbatim\n%s@end verbatim"
(org-export-format-code-default example-block info)))
-;;; Export Block
+;;;; Export Block
(defun org-texinfo-export-block (export-block contents info)
"Transcode a EXPORT-BLOCK element from Org to Texinfo.
@@ -920,7 +717,7 @@ CONTENTS is nil. INFO is a plist holding contextual information."
(when (string= (org-element-property :type export-block) "TEXINFO")
(org-remove-indentation (org-element-property :value export-block))))
-;;; Export Snippet
+;;;; Export Snippet
(defun org-texinfo-export-snippet (export-snippet contents info)
"Transcode a EXPORT-SNIPPET object from Org to Texinfo.
@@ -928,7 +725,7 @@ CONTENTS is nil. INFO is a plist holding contextual information."
(when (eq (org-export-snippet-backend export-snippet) 'texinfo)
(org-element-property :value export-snippet)))
-;;; Fixed Width
+;;;; Fixed Width
(defun org-texinfo-fixed-width (fixed-width contents info)
"Transcode a FIXED-WIDTH element from Org to Texinfo.
@@ -938,8 +735,7 @@ CONTENTS is nil. INFO is a plist holding contextual information."
(org-texinfo--sanitize-content
(org-element-property :value fixed-width)))))
-;;; Footnote Reference
-;;
+;;;; Footnote Reference
(defun org-texinfo-footnote-reference (footnote contents info)
"Create a footnote reference for FOOTNOTE.
@@ -950,7 +746,7 @@ plist holding contextual information."
(format "@footnote{%s}"
(org-trim (org-export-data def info)))))
-;;; Headline
+;;;; Headline
(defun org-texinfo-headline (headline contents info)
"Transcode a HEADLINE element from Org to Texinfo.
@@ -960,66 +756,29 @@ holding contextual information."
(level (org-export-get-relative-level headline info))
(numberedp (org-export-numbered-headline-p headline info))
(class-sectioning (assoc class org-texinfo-classes))
- ;; Find the index type, if any
+ ;; Find the index type, if any.
(index (org-element-property :INDEX headline))
- ;; Check if it is an appendix
- (appendix (org-element-property :APPENDIX headline))
- ;; Retrieve headline text
- (text (org-texinfo--sanitize-headline
- (org-element-property :title headline) info))
;; Create node info, to insert it before section formatting.
- ;; Use custom menu title if present
+ ;; Use custom menu title if present.
(node (format "@node %s\n" (org-texinfo--get-node headline info)))
- ;; Menus must be generated with first child, otherwise they
- ;; will not nest properly
- (menu (let* ((first (org-export-first-sibling-p headline info))
- (parent (org-export-get-parent-headline headline))
- (title (org-texinfo--sanitize-headline
- (org-element-property :title parent) info))
- heading listing
- (tree (plist-get info :parse-tree)))
- (if first
- (org-element-map (plist-get info :parse-tree) 'headline
- (lambda (ref)
- (if (member title (org-element-property :title ref))
- (push ref heading)))
- info t))
- (setq listing (org-texinfo--build-menu
- (car heading) level info))
- (if listing
- (setq listing (replace-regexp-in-string
- "%" "%%" listing)
- listing (format
- "\n@menu\n%s\n@end menu\n\n" listing))
- 'nil)))
;; Section formatting will set two placeholders: one for the
;; title and the other for the contents.
(section-fmt
- (let ((sec (if (and (symbolp (nth 2 class-sectioning))
- (fboundp (nth 2 class-sectioning)))
- (funcall (nth 2 class-sectioning) level numberedp)
- (nth (1+ level) class-sectioning))))
- (cond
- ;; No section available for that LEVEL.
- ((not sec) nil)
- ;; Section format directly returned by a function.
- ((stringp sec) sec)
- ;; (numbered-section . unnumbered-section)
- ((not (consp (cdr sec)))
+ (if (org-not-nil (org-element-property :APPENDIX headline))
+ "@appendix %s\n%s"
+ (let ((sec (if (and (symbolp (nth 2 class-sectioning))
+ (fboundp (nth 2 class-sectioning)))
+ (funcall (nth 2 class-sectioning) level numberedp)
+ (nth (1+ level) class-sectioning))))
(cond
- ;;If an index, always unnumbered
- (index
- (concat menu node (cdr sec) "\n%s"))
- (appendix
- (concat menu node (replace-regexp-in-string
- "unnumbered"
- "appendix"
- (cdr sec)) "\n%s"))
- ;; Otherwise number as needed.
- (t
- (concat menu node
- (funcall
- (if numberedp #'car #'cdr) sec) "\n%s")))))))
+ ;; No section available for that LEVEL.
+ ((not sec) nil)
+ ;; Section format directly returned by a function.
+ ((stringp sec) sec)
+ ;; (numbered-section . unnumbered-section)
+ ((not (consp (cdr sec)))
+ (concat (if (or index (not numberedp)) (cdr sec) (car sec))
+ "\n%s"))))))
(todo
(and (plist-get info :with-todo-keywords)
(let ((todo (org-element-property :todo-keyword headline)))
@@ -1029,100 +788,54 @@ holding contextual information."
(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 table of contents.
- (full-text (org-texinfo--sanitize-content
- (if (not (eq org-texinfo-format-headline-function 'ignore))
- ;; User-defined formatting function.
- (funcall org-texinfo-format-headline-function
- todo todo-type priority text tags)
- ;; Default formatting.
- (concat
- (when todo
- (format "@strong{%s} " todo))
- (when priority (format "@emph{#%s} " priority))
- text
- (when tags
- (format " :%s:"
- (mapconcat 'identity tags ":")))))))
- (full-text-no-tag
- (org-texinfo--sanitize-content
- (if (not (eq org-texinfo-format-headline-function 'ignore))
- ;; User-defined formatting function.
- (funcall org-texinfo-format-headline-function
- todo todo-type priority text nil)
- ;; Default formatting.
- (concat
- (when todo (format "@strong{%s} " todo))
- (when priority (format "@emph{#%c} " priority))
- text))))
- (pre-blanks
- (make-string (org-element-property :pre-blank headline) 10)))
+ (text (org-export-data (org-element-property :title headline) info))
+ (full-text (if (not (eq org-texinfo-format-headline-function 'ignore))
+ ;; User-defined formatting function.
+ (funcall org-texinfo-format-headline-function
+ todo todo-type priority text tags)
+ ;; Default formatting.
+ (concat
+ (when todo
+ (format "@strong{%s} " todo))
+ (when priority (format "@emph{#%s} " priority))
+ text
+ (when tags
+ (format " :%s:"
+ (mapconcat 'identity tags ":"))))))
+ (contents (if (org-string-nw-p contents) (concat "\n" contents) "")))
(cond
;; Case 1: This is a footnote section: ignore it.
((org-element-property :footnote-section-p headline) nil)
;; Case 2: This is the `copying' section: ignore it
;; This is used elsewhere.
- ((org-element-property :COPYING headline) nil)
+ ((org-not-nil (org-element-property :COPYING headline)) nil)
;; Case 3: An index. If it matches one of the known indexes,
;; print it as such following the contents, otherwise
;; print the contents and leave the index up to the user.
(index
- (format
- section-fmt full-text
- (concat pre-blanks contents "\n"
- (if (member index '("cp" "fn" "ky" "pg" "tp" "vr"))
- (concat "@printindex " index)))))
+ (concat node
+ (format
+ section-fmt
+ full-text
+ (concat contents
+ (and (member index '("cp" "fn" "ky" "pg" "tp" "vr"))
+ (concat "\n@printindex " index))))))
;; Case 4: 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.
((or (not section-fmt) (org-export-low-level-p headline info))
;; Build the real contents of the sub-tree.
- (let ((low-level-body
- (concat
- ;; If the headline is the first sibling, start a list.
- (when (org-export-first-sibling-p headline info)
- (format "@%s\n" (if numberedp 'enumerate 'itemize)))
- ;; Itemize headline
- "@item\n" full-text "\n" 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))))
+ (concat (and (org-export-first-sibling-p headline info)
+ (format "@%s\n" (if numberedp 'enumerate 'itemize)))
+ "@item\n" full-text "\n"
+ contents
+ (if (org-export-last-sibling-p headline info)
+ (format "@end %s" (if numberedp 'enumerate 'itemize))
+ "\n")))
;; Case 5: Standard headline. Export it as a section.
- (t
- (cond
- ((not (and tags (eq (plist-get info :with-tags) 'not-in-toc)))
- ;; Regular section. Use specified format string.
- (format (replace-regexp-in-string "%]" "%%]" section-fmt) full-text
- (concat pre-blanks contents)))
- ((string-match "\\`@\\(.*?\\){" section-fmt)
- ;; If tags should be removed from table of contents, insert
- ;; title without tags as an alternative heading in sectioning
- ;; command.
- (format (replace-match (concat (match-string 1 section-fmt) "[%s]")
- nil nil section-fmt 1)
- ;; Replace square brackets with parenthesis since
- ;; square brackets are not supported in optional
- ;; arguments.
- (replace-regexp-in-string
- "\\[" "("
- (replace-regexp-in-string
- "\\]" ")"
- full-text-no-tag))
- full-text
- (concat pre-blanks contents)))
- (t
- ;; Impossible to add an alternative heading. Fallback to
- ;; regular sectioning format string.
- (format (replace-regexp-in-string "%]" "%%]" section-fmt) full-text
- (concat pre-blanks contents))))))))
-
-;;; Inline Src Block
+ (t (concat node (format section-fmt full-text contents))))))
+
+;;;; Inline Src Block
(defun org-texinfo-inline-src-block (inline-src-block contents info)
"Transcode an INLINE-SRC-BLOCK element from Org to Texinfo.
@@ -1132,7 +845,7 @@ contextual information."
(separator (org-texinfo--find-verb-separator code)))
(concat "@verb{" separator code separator "}")))
-;;; Inlinetask
+;;;; Inlinetask
(defun org-texinfo-inlinetask (inlinetask contents info)
"Transcode an INLINETASK element from Org to Texinfo.
@@ -1165,7 +878,7 @@ holding contextual information."
"\n")
full-title contents)))))
-;;; Italic
+;;;; Italic
(defun org-texinfo-italic (italic contents info)
"Transcode ITALIC from Org to Texinfo.
@@ -1173,18 +886,18 @@ CONTENTS is the text with italic markup. INFO is a plist holding
contextual information."
(org-texinfo--text-markup contents 'italic))
-;;; Item
+;;;; Item
(defun org-texinfo-item (item contents info)
"Transcode an ITEM element from Org to Texinfo.
CONTENTS holds the contents of the item. INFO is a plist holding
contextual information."
- (let* ((tag (org-element-property :tag item))
- (desc (org-export-data tag info)))
- (concat "\n@item " (if tag desc) "\n"
- (and contents (org-trim contents)) "\n")))
+ (format "@item%s\n%s"
+ (let ((tag (org-element-property :tag item)))
+ (if tag (concat " " (org-export-data tag info)) ""))
+ (or contents "")))
-;;; Keyword
+;;;; Keyword
(defun org-texinfo-keyword (keyword contents info)
"Transcode a KEYWORD element from Org to Texinfo.
@@ -1200,14 +913,14 @@ CONTENTS is nil. INFO is a plist holding contextual information."
((string= key "TINDEX") (format "@tindex %s" value))
((string= key "VINDEX") (format "@vindex %s" value)))))
-;;; Line Break
+;;;; Line Break
(defun org-texinfo-line-break (line-break contents info)
"Transcode a LINE-BREAK object from Org to Texinfo.
CONTENTS is nil. INFO is a plist holding contextual information."
"@*\n")
-;;; Link
+;;;; Link
(defun org-texinfo-link (link desc info)
"Transcode a LINK object from Org to Texinfo.
@@ -1225,55 +938,69 @@ INFO is a plist holding contextual information. See
((and (string= type "file") (file-name-absolute-p raw-path))
(concat "file:" raw-path))
(t raw-path)))
- (email (if (string= type "mailto")
- (let ((text (replace-regexp-in-string
- "@" "@@" raw-path)))
- (concat text (if desc (concat "," desc))))))
protocol)
(cond
- ;; Links pointing to a headline: Find destination and build
- ;; appropriate referencing command.
- ((member type '("custom-id" "id"))
- (let ((destination (org-export-resolve-id-link link info)))
+ ((equal type "radio")
+ (let ((destination (org-export-resolve-radio-link link info)))
+ (if (not destination) desc
+ (format "@ref{%s,,%s}"
+ (org-texinfo--get-node destination info)
+ desc))))
+ ((member type '("custom-id" "id" "fuzzy"))
+ (let ((destination
+ (if (equal type "fuzzy")
+ (org-export-resolve-fuzzy-link link info)
+ (org-export-resolve-id-link link info))))
(case (org-element-type destination)
+ ((nil)
+ (format org-texinfo-link-with-unknown-path-format
+ (org-texinfo--sanitize-content path)))
;; Id link points to an external file.
(plain-text
(if desc (format "@uref{file://%s,%s}" destination desc)
(format "@uref{file://%s}" destination)))
- ;; LINK points to a headline. Use the headline as the NODE target
(headline
(format "@ref{%s,%s}"
(org-texinfo--get-node destination info)
- (or desc "")))
+ (cond
+ (desc)
+ ((org-export-numbered-headline-p destination info)
+ (org-export-data
+ (org-element-property :title destination) info))
+ (t
+ (mapconcat
+ #'number-to-string
+ (org-export-get-headline-number destination info) ".")))))
(otherwise
- (let ((path (org-export-solidify-link-text path)))
- (if (not desc) (format "@ref{%s}" path)
- (format "@ref{%s,,%s}" path desc)))))))
- ((member type '("info"))
+ (let ((topic
+ (or desc
+ (if (and (eq (org-element-type destination) 'headline)
+ (not (org-export-numbered-headline-p
+ destination info)))
+ (org-export-data
+ (org-element-property :title destination) info))
+ (let ((n (org-export-get-ordinal destination info)))
+ (cond
+ ((not n) nil)
+ ((integerp n) n)
+ (t (mapconcat #'number-to-string n ".")))))))
+ (when topic
+ (format "@ref{%s,,%s}"
+ (org-texinfo--get-node destination info)
+ topic)))))))
+ ((equal type "info")
(let* ((info-path (split-string path "[:#]"))
(info-manual (car info-path))
(info-node (or (cadr info-path) "top"))
(title (or desc "")))
(format "@ref{%s,%s,,%s,}" info-node title info-manual)))
- ((member type '("fuzzy"))
- (let ((destination (org-export-resolve-fuzzy-link link info)))
- (case (org-element-type destination)
- ;; Id link points to an external file.
- (plain-text
- (if desc (format "@uref{file://%s,%s}" destination desc)
- (format "@uref{file://%s}" destination)))
- ;; LINK points to a headline. Use the headline as the NODE target
- (headline
- (format "@ref{%s,%s}"
- (org-texinfo--get-node destination info)
- (or desc "")))
- (otherwise
- (let ((path (org-export-solidify-link-text path)))
- (if (not desc) (format "@ref{%s}" path)
- (format "@ref{%s,,%s}" path desc)))))))
- ;; Special case for email addresses
- (email
- (format "@email{%s}" email))
+ ((string= type "mailto")
+ (format "@email{%s}"
+ (concat (org-texinfo--sanitize-content path)
+ (and desc (concat "," desc)))))
+ ((let ((protocol (nth 2 (assoc type org-link-protocols))))
+ (and (functionp protocol)
+ (funcall protocol (org-link-unescape path) desc 'texinfo))))
;; External link with a description part.
((and path desc) (format "@uref{%s,%s}" path desc))
;; External link without a description part.
@@ -1282,27 +1009,97 @@ INFO is a plist holding contextual information. See
(t (format org-texinfo-link-with-unknown-path-format desc)))))
-;;; Menu
-
-(defun org-texinfo-make-menu (info level)
- "Create the menu for inclusion in the texifo document.
-
-INFO is the parsed buffer that contains the headlines. LEVEL
-determines whether to make the main menu, or the detailed menu.
-
-This is only used for generating the primary menu. In-Node menus
-are generated directly."
- (let ((parse (plist-get info :parse-tree)))
- (cond
- ;; Generate the main menu
- ((eq level 'main) (org-texinfo--build-menu parse 1 info))
- ;; Generate the detailed (recursive) menu
- ((eq level 'detailed)
- ;; Requires recursion
- ;;(org-texinfo--build-detailed-menu parse top info)
- (org-texinfo--build-menu parse 1 info 'detailed)))))
-
-;;; Paragraph
+;;;; Menu
+
+(defun org-texinfo-make-menu (scope info &optional master)
+ "Create the menu for inclusion in the Texinfo document.
+
+SCOPE is a headline or a full parse tree. INFO is the
+communication channel, as a plist.
+
+When optional argument MASTER is non-nil, generate a master menu,
+including detailed node listing."
+ (let ((menu (org-texinfo--build-menu scope info)))
+ (when (org-string-nw-p menu)
+ (org-element-normalize-string
+ (format
+ "@menu\n%s@end menu"
+ (concat menu
+ (when master
+ (let ((detailmenu
+ (org-texinfo--build-menu
+ scope info
+ (let ((toc-depth (plist-get info :with-toc)))
+ (if (wholenump toc-depth) toc-depth
+ org-texinfo-max-toc-depth)))))
+ (when (org-string-nw-p detailmenu)
+ (concat "\n@detailmenu\n"
+ "--- The Detailed Node Listing ---\n\n"
+ detailmenu
+ "@end detailmenu\n"))))))))))
+
+(defun org-texinfo--build-menu (scope info &optional level)
+ "Build menu for entries within SCOPE.
+SCOPE is a headline or a full parse tree. INFO is a plist
+containing contextual information. When optional argument LEVEL
+is an integer, build the menu recursively, down to this depth."
+ (cond
+ ((not level)
+ (org-texinfo--format-entries (org-texinfo--menu-entries scope info) info))
+ ((zerop level) nil)
+ (t
+ (org-element-normalize-string
+ (mapconcat
+ (lambda (h)
+ (let ((entries (org-texinfo--menu-entries h info)))
+ (when entries
+ (concat
+ (format "%s\n\n%s\n"
+ (org-export-data (org-export-get-alt-title h info) info)
+ (org-texinfo--format-entries entries info))
+ (org-texinfo--build-menu h info (1- level))))))
+ (org-texinfo--menu-entries scope info) "")))))
+
+(defun org-texinfo--format-entries (entries info)
+ "Format all direct menu entries in SCOPE, as a string.
+SCOPE is either a headline or a full Org document. INFO is
+a plist containing contextual information."
+ (org-element-normalize-string
+ (mapconcat
+ (lambda (h)
+ (let* ((title (org-export-data
+ (org-export-get-alt-title h info) info))
+ (node (org-texinfo--get-node h info))
+ (entry (concat "* " title ":"
+ (if (string= title node) ":"
+ (concat " " node ". "))))
+ (desc (org-element-property :DESCRIPTION h)))
+ (if (not desc) entry
+ (format (format "%%-%ds %%s" org-texinfo-node-description-column)
+ entry desc))))
+ entries "\n")))
+
+(defun org-texinfo--menu-entries (scope info)
+ "List direct children in SCOPE needing a menu entry.
+SCOPE is a headline or a full parse tree. INFO is a plist
+holding contextual information."
+ (let* ((cache (or (plist-get info :texinfo-entries-cache)
+ (plist-get (plist-put info :texinfo-entries-cache
+ (make-hash-table :test #'eq))
+ :texinfo-entries-cache)))
+ (cached-entries (gethash scope cache 'no-cache)))
+ (if (not (eq cached-entries 'no-cache)) cached-entries
+ (puthash scope
+ (org-element-map (org-element-contents scope) 'headline
+ (lambda (h)
+ (and (not (org-not-nil (org-element-property :COPYING h)))
+ (not (org-element-property :footnote-section-p h))
+ (not (org-export-low-level-p h info))
+ h))
+ info nil 'headline)
+ cache))))
+
+;;;; Paragraph
(defun org-texinfo-paragraph (paragraph contents info)
"Transcode a PARAGRAPH element from Org to Texinfo.
@@ -1310,32 +1107,27 @@ CONTENTS is the contents of the paragraph, as a string. INFO is
the plist used as a communication channel."
contents)
-;;; Plain List
+;;;; Plain List
(defun org-texinfo-plain-list (plain-list contents info)
"Transcode a PLAIN-LIST element from Org to Texinfo.
CONTENTS is the contents of the list. INFO is a plist holding
contextual information."
(let* ((attr (org-export-read-attribute :attr_texinfo plain-list))
- (indic (or (plist-get attr :indic)
- org-texinfo-def-table-markup))
- (type (org-element-property :type plain-list))
+ (indic (or (plist-get attr :indic) org-texinfo-def-table-markup))
(table-type (plist-get attr :table-type))
- ;; Ensure valid texinfo table type.
- (table-type (if (member table-type '("ftable" "vtable")) table-type
- "table"))
+ (type (org-element-property :type plain-list))
(list-type (cond
((eq type 'ordered) "enumerate")
((eq type 'unordered) "itemize")
- ((eq type 'descriptive) table-type))))
- (format "@%s%s\n@end %s"
- (if (eq type 'descriptive)
- (concat list-type " " indic)
- list-type)
+ ((member table-type '("ftable" "vtable")) table-type)
+ (t "table"))))
+ (format "@%s\n%s@end %s"
+ (if (eq type 'descriptive) (concat list-type " " indic) list-type)
contents
list-type)))
-;;; Plain Text
+;;;; Plain Text
(defun org-texinfo-plain-text (text info)
"Transcode a TEXT string from Org to Texinfo.
@@ -1366,7 +1158,7 @@ contextual information."
;; Return value.
output))
-;;; Planning
+;;;; Planning
(defun org-texinfo-planning (planning contents info)
"Transcode a PLANNING element from Org to Texinfo.
@@ -1402,7 +1194,7 @@ information."
" ")
"@*"))
-;;; Property Drawer
+;;;; Property Drawer
(defun org-texinfo-property-drawer (property-drawer contents info)
"Transcode a PROPERTY-DRAWER element from Org to Texinfo.
@@ -1412,7 +1204,7 @@ information."
;; lines nonetheless.
"")
-;;; Quote Block
+;;;; Quote Block
(defun org-texinfo-quote-block (quote-block contents info)
"Transcode a QUOTE-BLOCK element from Org to Texinfo.
@@ -1424,7 +1216,7 @@ holding contextual information."
(format " %s" title)))))
(format "%s\n%s@end quotation" start-quote contents)))
-;;; Quote Section
+;;;; Quote Section
(defun org-texinfo-quote-section (quote-section contents info)
"Transcode a QUOTE-SECTION element from Org to Texinfo.
@@ -1433,7 +1225,7 @@ CONTENTS is nil. INFO is a plist holding contextual information."
(org-element-property :value quote-section))))
(when value (format "@verbatim\n%s@end verbatim" value))))
-;;; Radio Target
+;;;; Radio Target
(defun org-texinfo-radio-target (radio-target text info)
"Transcode a RADIO-TARGET object from Org to Texinfo.
@@ -1444,15 +1236,17 @@ contextual information."
(org-element-property :value radio-target))
text))
-;;; Section
+;;;; Section
(defun org-texinfo-section (section contents info)
"Transcode a SECTION element from Org to Texinfo.
CONTENTS holds the contents of the section. INFO is a plist
holding contextual information."
- contents)
+ (concat contents
+ (let ((parent (org-export-get-parent-headline section)))
+ (and parent (org-texinfo-make-menu parent info)))))
-;;; Special Block
+;;;; Special Block
(defun org-texinfo-special-block (special-block contents info)
"Transcode a SPECIAL-BLOCK element from Org to Texinfo.
@@ -1460,34 +1254,26 @@ CONTENTS holds the contents of the block. INFO is a plist used
as a communication channel."
contents)
-;;; Src Block
+;;;; Src Block
(defun org-texinfo-src-block (src-block contents info)
"Transcode a SRC-BLOCK element from Org to Texinfo.
CONTENTS holds the contents of the item. INFO is a plist holding
contextual information."
- (let* ((lang (org-element-property :language src-block))
- (lisp-p (string-match-p "lisp" lang))
- (src-contents (org-texinfo--sanitize-content
- (org-export-format-code-default src-block info))))
- (cond
- ;; Case 1. Lisp Block
- (lisp-p
- (format "@lisp\n%s@end lisp"
- src-contents))
- ;; Case 2. Other blocks
- (t
- (format "@example\n%s@end example"
- src-contents)))))
+ (let ((lispp (org-string-match-p "lisp"
+ (org-element-property :language src-block)))
+ (code (org-texinfo--sanitize-content
+ (org-export-format-code-default src-block info))))
+ (format (if lispp "@lisp\n%s@end lisp" "@example\n%s@end example") code)))
-;;; Statistics Cookie
+;;;; Statistics Cookie
(defun org-texinfo-statistics-cookie (statistics-cookie contents info)
"Transcode a STATISTICS-COOKIE object from Org to Texinfo.
CONTENTS is nil. INFO is a plist holding contextual information."
(org-element-property :value statistics-cookie))
-;;; Subscript
+;;;; Subscript
(defun org-texinfo-subscript (subscript contents info)
"Transcode a SUBSCRIPT object from Org to Texinfo.
@@ -1495,7 +1281,7 @@ CONTENTS is the contents of the object. INFO is a plist holding
contextual information."
(format "@math{_%s}" contents))
-;;; Superscript
+;;;; Superscript
(defun org-texinfo-superscript (superscript contents info)
"Transcode a SUPERSCRIPT object from Org to Texinfo.
@@ -1503,96 +1289,47 @@ CONTENTS is the contents of the object. INFO is a plist holding
contextual information."
(format "@math{^%s}" contents))
-;;; Table
-;;
-;; `org-texinfo-table' is the entry point for table transcoding. It
-;; takes care of tables with a "verbatim" attribute. Otherwise, it
-;; delegates the job to either `org-texinfo-table--table.el-table' or
-;; `org-texinfo-table--org-table' functions, depending of the type of
-;; the table.
-;;
-;; `org-texinfo-table--align-string' is a subroutine used to build
-;; alignment string for Org tables.
+;;;; Table
(defun org-texinfo-table (table contents info)
"Transcode a TABLE element from Org to Texinfo.
CONTENTS is the contents of the table. INFO is a plist holding
contextual information."
- (cond
- ;; Case 1: verbatim table.
- ((or org-texinfo-tables-verbatim
- (let ((attr (mapconcat 'identity
- (org-element-property :attr_latex table)
- " ")))
- (and attr (string-match "\\<verbatim\\>" attr))))
- (format "@verbatim \n%s\n@end verbatim"
- ;; Re-create table, without affiliated keywords.
- (org-trim
- (org-element-interpret-data
- `(table nil ,@(org-element-contents table))))))
- ;; Case 2: table.el table. Convert it using appropriate tools.
- ((eq (org-element-property :type table) 'table.el)
- (org-texinfo-table--table.el-table table contents info))
- ;; Case 3: Standard table.
- (t (org-texinfo-table--org-table table contents info))))
+ (if (eq (org-element-property :type table) 'table.el)
+ (format "@verbatim\n%s@end verbatim"
+ (org-element-normalize-string
+ (org-element-property :value table)))
+ (let* ((col-width (org-export-read-attribute :attr_texinfo table :columns))
+ (columns
+ (if col-width (format "@columnfractions %s" col-width)
+ (org-texinfo-table-column-widths table info))))
+ (format "@multitable %s\n%s@end multitable"
+ columns
+ contents))))
(defun org-texinfo-table-column-widths (table info)
"Determine the largest table cell in each column to process alignment.
-
TABLE is the table element to transcode. INFO is a plist used as
a communication channel."
- (let* ((rows (org-element-map table 'table-row 'identity info))
- (collected (loop for row in rows collect
- (org-element-map row 'table-cell 'identity info)))
- (number-cells (length (car collected)))
- cells counts)
- (loop for row in collected do
- (push (mapcar (lambda (ref)
- (let* ((start (org-element-property :contents-begin ref))
- (end (org-element-property :contents-end ref))
- (length (- end start)))
- length)) row) cells))
- (setq cells (org-remove-if 'null cells))
- (push (loop for count from 0 to (- number-cells 1) collect
- (loop for item in cells collect
- (nth count item))) counts)
- (mapconcat (lambda (size)
- (make-string size ?a)) (mapcar (lambda (ref)
- (apply 'max `(,@ref))) (car counts))
- "} {")))
-
-(defun org-texinfo-table--org-table (table contents info)
- "Return appropriate Texinfo code for an Org table.
-
-TABLE is the table type element to transcode. CONTENTS is its
-contents, as a string. INFO is a plist used as a communication
-channel.
-
-This function assumes TABLE has `org' as its `:type' attribute."
- (let* ((attr (org-export-read-attribute :attr_texinfo table))
- (col-width (plist-get attr :columns))
- (columns (if col-width
- (format "@columnfractions %s"
- col-width)
- (format "{%s}"
- (org-texinfo-table-column-widths
- table info)))))
- ;; Prepare the final format string for the table.
- (cond
- ;; Longtable.
- ;; Others.
- (t (concat
- (format "@multitable %s\n%s@end multitable"
- columns
- contents))))))
-
-(defun org-texinfo-table--table.el-table (table contents info)
- "Returns nothing.
-
-Rather than return an invalid table, nothing is returned."
- 'nil)
-
-;;; Table Cell
+ (let ((widths (make-vector (cdr (org-export-table-dimensions table info)) 0)))
+ (org-element-map table 'table-row
+ (lambda (row)
+ (let ((idx 0))
+ (org-element-map row 'table-cell
+ (lambda (cell)
+ ;; Length of the cell in the original buffer is only an
+ ;; approximation of the length of the cell in the
+ ;; output. It can sometimes fail (e.g. it considers
+ ;; "/a/" being larger than "ab").
+ (let ((w (- (org-element-property :contents-end cell)
+ (org-element-property :contents-begin cell))))
+ (aset widths idx (max w (aref widths idx))))
+ (incf idx))
+ info)))
+ info)
+ (format "{%s}" (mapconcat (lambda (w) (make-string w ?a)) widths "} {"))))
+
+;;;; Table Cell
(defun org-texinfo-table-cell (table-cell contents info)
"Transcode a TABLE-CELL element from Org to Texinfo.
@@ -1609,7 +1346,7 @@ a communication channel."
contents)
(when (org-export-get-next-element table-cell info) "\n@tab ")))
-;;; Table Row
+;;;; Table Row
(defun org-texinfo-table-row (table-row contents info)
"Transcode a TABLE-ROW element from Org to Texinfo.
@@ -1618,21 +1355,15 @@ a communication channel."
;; Rules are ignored since table separators are deduced from
;; borders of the current row.
(when (eq (org-element-property :type table-row) 'standard)
- (let ((rowgroup-tag
- (cond
- ;; Case 1: Belongs to second or subsequent rowgroup.
- ((not (= 1 (org-export-table-row-group table-row info)))
- "@item ")
- ;; Case 2: Row is from first rowgroup. Table has >=1 rowgroups.
- ((org-export-table-has-header-p
- (org-export-get-parent-table table-row) info)
- "@headitem ")
- ;; Case 3: Row is from first and only row group.
- (t "@item "))))
- (when (eq (org-element-property :type table-row) 'standard)
- (concat rowgroup-tag contents "\n")))))
-
-;;; Target
+ (let ((rowgroup-tag
+ (if (and (= 1 (org-export-table-row-group table-row info))
+ (org-export-table-has-header-p
+ (org-export-get-parent-table table-row) info))
+ "@headitem "
+ "@item ")))
+ (concat rowgroup-tag contents "\n"))))
+
+;;;; Target
(defun org-texinfo-target (target contents info)
"Transcode a TARGET object from Org to Texinfo.
@@ -1641,7 +1372,7 @@ information."
(format "@anchor{%s}"
(org-export-solidify-link-text (org-element-property :value target))))
-;;; Timestamp
+;;;; Timestamp
(defun org-texinfo-timestamp (timestamp contents info)
"Transcode a TIMESTAMP object from Org to Texinfo.
@@ -1656,7 +1387,7 @@ information."
(format org-texinfo-inactive-timestamp-format value))
(t (format org-texinfo-diary-timestamp-format value)))))
-;;; Verbatim
+;;;; Verbatim
(defun org-texinfo-verbatim (verbatim contents info)
"Transcode a VERBATIM object from Org to Texinfo.
@@ -1664,26 +1395,13 @@ CONTENTS is nil. INFO is a plist used as a communication
channel."
(org-texinfo--text-markup (org-element-property :value verbatim) 'verbatim))
-;;; Verse Block
+;;;; Verse Block
(defun org-texinfo-verse-block (verse-block contents info)
"Transcode a VERSE-BLOCK element from Org to Texinfo.
CONTENTS is verse block contents. INFO is a plist holding
contextual information."
- ;; In a verse environment, add a line break to each newline
- ;; character and change each white space at beginning of a line
- ;; into a space of 1 em. Also change each blank line with
- ;; a vertical space of 1 em.
- (progn
- (setq contents (replace-regexp-in-string
- "^ *\\\\\\\\$" "\\\\vspace*{1em}"
- (replace-regexp-in-string
- "\\(\\\\\\\\\\)?[ \t]*\n" " \\\\\\\\\n" contents)))
- (while (string-match "^[ \t]+" contents)
- (let ((new-str (format "\\hspace*{%dem}"
- (length (match-string 0 contents)))))
- (setq contents (replace-match new-str nil t contents))))
- (format "\\begin{verse}\n%s\\end{verse}" contents)))
+ (format "@display\n%s@end display" contents))
;;; Interactive functions
@@ -1797,29 +1515,21 @@ Return INFO file name or an error if it couldn't be produced."
errors)
(message (format "Processing Texinfo file %s..." file))
(save-window-excursion
- (cond
- ;; A function is provided: Apply it.
- ((functionp org-texinfo-info-process)
- (funcall org-texinfo-info-process (shell-quote-argument file)))
- ;; A list is provided: Replace %b, %f and %o with appropriate
- ;; values in each command before applying it. Output is
- ;; redirected to "*Org INFO Texinfo Output*" buffer.
- ((consp org-texinfo-info-process)
- (let ((outbuf (get-buffer-create "*Org INFO Texinfo Output*")))
- (mapc
- (lambda (command)
- (shell-command
- (replace-regexp-in-string
- "%b" (shell-quote-argument base-name)
- (replace-regexp-in-string
- "%f" (shell-quote-argument full-name)
- (replace-regexp-in-string
- "%o" (shell-quote-argument out-dir) command t t) t t) t t)
- outbuf))
- org-texinfo-info-process)
- ;; Collect standard errors from output buffer.
- (setq errors (org-texinfo-collect-errors outbuf))))
- (t (error "No valid command to process to Info")))
+ ;; Replace %b, %f and %o with appropriate values in each command
+ ;; before applying it. Output is redirected to "*Org INFO
+ ;; Texinfo Output*" buffer.
+ (let ((outbuf (get-buffer-create "*Org INFO Texinfo Output*")))
+ (dolist (command org-texinfo-info-process)
+ (shell-command
+ (replace-regexp-in-string
+ "%b" (shell-quote-argument base-name)
+ (replace-regexp-in-string
+ "%f" (shell-quote-argument full-name)
+ (replace-regexp-in-string
+ "%o" (shell-quote-argument out-dir) command t t) t t) t t)
+ outbuf))
+ ;; Collect standard errors from output buffer.
+ (setq errors (org-texinfo-collect-errors outbuf)))
(let ((infofile (concat out-dir base-name ".info")))
;; Check for process failure. Provide collected errors if
;; possible.
diff --git a/lisp/ox.el b/lisp/ox.el
index 6d07a2e..1327ae4 100644
--- a/lisp/ox.el
+++ b/lisp/ox.el
@@ -814,7 +814,7 @@ This variable can be either set to `buffer' or `subtree'."
(defcustom org-export-show-temporary-export-buffer t
"Non-nil means show buffer after exporting to temp buffer.
-When Org exports to a file, the buffer visiting that file is ever
+When Org exports to a file, the buffer visiting that file is never
shown, but remains buried. However, when exporting to
a temporary buffer, that buffer is popped up in a second window.
When this variable is nil, the buffer remains buried also in
@@ -1333,6 +1333,10 @@ The back-end could then be called with, for example:
;; - category :: option
;; - type :: string
;;
+;; + `:output-file' :: Full path to output file, if any.
+;; - category :: option
+;; - type :: string or nil
+;;
;; + `:parse-tree' :: Whole parse tree, available at any time during
;; transcoding.
;; - category :: option
@@ -4134,29 +4138,8 @@ objects of the same type."
((funcall predicate el info) (incf counter) nil)))
info 'first-match)))))
-;;;; For Special Blocks
-;;
-;; `org-export-raw-special-block-p' check if current special block is
-;; an "export block", i.e., a block whose contents should be inserted
-;; as-is in the output. This should generally be the first check to
-;; do when handling special blocks in the export back-end.
-
-(defun org-export-raw-special-block-p (element info &optional no-inheritance)
- "Non-nil if ELEMENT is an export block relatively to current back-end.
-An export block is a special block whose contents should be
-included as-is in the final output. Such blocks are defined
-through :export-block property in `org-export-define-backend',
-which see."
- (and (eq (org-element-type element) 'special-block)
- (let ((type (org-element-property :type element))
- (b (plist-get info :back-end)))
- (if no-inheritance (member type (org-export-backend-blocks b))
- (while (and b (not (member type (org-export-backend-blocks b))))
- (setq b (org-export-get-backend (org-export-backend-parent b))))
- b))))
-
-;;;; For Src Blocks
+;;;; For Src-Blocks
;;
;; `org-export-get-loc' counts number of code lines accumulated in
;; src-block or example-block elements with a "+n" switch until
@@ -5496,8 +5479,9 @@ to `:default' encoding. If it fails, return S."
(defmacro org-export-async-start (fun &rest body)
"Call function FUN on the results returned by BODY evaluation.
-BODY evaluation happens in an asynchronous process, from a buffer
-which is an exact copy of the current one.
+FUN is an anonymous function of one argument. BODY evaluation
+happens in an asynchronous process, from a buffer which is an
+exact copy of the current one.
Use `org-export-add-to-stack' in FUN in order to register results
in the stack.
@@ -5674,7 +5658,8 @@ The function returns either a file name returned by POST-PROCESS,
or FILE."
(declare (indent 2))
(if (not (file-writable-p file)) (error "Output file not writable")
- (let ((encoding (or org-export-coding-system buffer-file-coding-system)))
+ (let ((ext-plist (org-combine-plists `(:output-file ,file) ext-plist))
+ (encoding (or org-export-coding-system buffer-file-coding-system)))
(if async
(org-export-async-start
`(lambda (file)
diff --git a/mk/org-fixup.el b/mk/org-fixup.el
index aa7ff09..e57eb65 100644
--- a/mk/org-fixup.el
+++ b/mk/org-fixup.el
@@ -58,8 +58,8 @@ the Git work tree)."
\f\n;; Local Variables:\n;; version-control: never
;; no-byte-compile: t
;; coding: utf-8\n;; End:\n;;; org-version.el ends here\n")
- (toggle-read-only 0)
- (write-file "org-version.el")))
+ (let ((inhibit-read-only t))
+ (write-file "org-version.el"))))
(defun org-make-org-loaddefs ()
"Make the file org-loaddefs.el in the current directory.
@@ -77,8 +77,8 @@ work correctly if this file is not up-to-date."
(insert "\f\n;; Local Variables:\n;; version-control: never\n")
(insert ";; no-byte-compile: t\n;; no-update-autoloads: t\n")
(insert ";; coding: utf-8\n;; End:\n;;; org-loaddefs.el ends here\n")
- (toggle-read-only 0)
- (save-buffer)))
+ (let ((inhibit-read-only t))
+ (save-buffer))))
(defun org-make-autoloads (&optional compile force)
"Make the files org-loaddefs.el and org-version.el in the install directory.
@@ -140,8 +140,8 @@ oldorg: # do what the old Makefile did by default.
(insert "\
# See default.mk for further configuration options.
")
- (toggle-read-only 0)
- (write-file local))
+ (let ((inhibit-read-only t))
+ (write-file local)))
nil)))
(defun org-make-letterformat (a4name lettername)
@@ -152,8 +152,8 @@ oldorg: # do what the old Makefile did by default.
(goto-char (point-min))
(while (search-forward "\\pdflayout=(0l)" nil t)
(replace-match "\\pdflayout=(1l)" nil t))
- (toggle-read-only 0)
- (write-file lettername))
+ (let ((inhibit-read-only t))
+ (write-file lettername)))
nil))
;; redefine version functions
diff --git a/mk/version.mk b/mk/version.mk
index bb6d0fe..d33d8e4 100644
--- a/mk/version.mk
+++ b/mk/version.mk
@@ -1,2 +1,2 @@
-ORGVERSION ?= 8.2.7c
-GITVERSION ?= 8.2.7c-dist
+ORGVERSION ?= 8.2.10
+GITVERSION ?= 8.2.10-dist