Usability improvements to org-lparse-convert and co (First cut)

* contrib/lisp/org-lparse.el (org-lparse-and-open)
(org-lparse-register-backend, org-lparse-format-table)
(org-lparse-begin, org-lparse-end): Checkdoc related fixes.
(org-lparse-get-converter): Added
(org-lparse-get-other-backends, org-lparse-all-backends):
Re-implemented. Also improved docstring.
(org-lparse): Make use of improvements in the converter
routines. Improve the following: a) gathering of
target-backend and native-backend args during interactive
calls b) error handling.
(org-lparse-convert): Introduced prefix arg for opening of
converted files. Make use of improvements in the converter
routines. Improve error handling.
(org-lparse-convert-processes): New customizable variable.
(org-lparse-convert-process): Make it customizable. Set
default value to nil.
(org-lparse-convert-capabilities): New customizable variable.
(org-lparse-use-flashy-warning): Fix group and improve docstring.

* contrib/lisp/org-odt.el (org-odt-get): Don't set
CONVERT-METHOD and OTHER-BACKENDS options. Fallback to the
global converter settings for now.
(org-export-odt-preferred-output-format): New variable
(org-export-as-odt-and-open, org-export-as-odt): Use the
afore-mentioned variable.

* contrib/lisp/org-xhtml.el (org-xhtml-get): Don't set
CONVERT-METHOD and OTHER-BACKENDS options. Fallback to the
global converter settings for now.
This commit is contained in:
Jambunathan K 2011-08-05 02:01:19 +05:30
parent 049c0776ff
commit 44472fa6cf
3 changed files with 236 additions and 76 deletions

View File

@ -57,7 +57,7 @@
;;;###autoload
(defun org-lparse-and-open (target-backend native-backend arg)
"Export the outline to TARGET-BACKEND via NATIVE-BACKEND and open exported file.
"Export outline to TARGET-BACKEND via NATIVE-BACKEND and open exported file.
If there is an active region, export only the region. The prefix
ARG specifies how many levels of the outline should become
headlines. The default is 3. Lower levels will become bulleted
@ -357,7 +357,7 @@ For the sake of illustration, the html backend implements
ENTITY-CONTROL and ENTITY-FORMAT settings.")
(defun org-lparse-register-backend (backend)
"Make BACKEND known to org-lparse library.
"Make BACKEND known to `org-lparse' library.
Add BACKEND to `org-lparse-native-backends'."
(when backend
(setq backend (cond
@ -374,17 +374,41 @@ Add BACKEND to `org-lparse-native-backends'."
org-lparse-native-backends))
(message "Unregistered backend %S" backend))
(defun org-lparse-get-other-backends (native-backend)
(org-lparse-backend-get native-backend 'OTHER-BACKENDS))
(defun org-lparse-get-other-backends (in-fmt)
"Return OUTPUT-FMT-ALIST corresponding to IN-FMT.
See `org-lparse-convert-capabilities' for definition of
OUTPUT-FMT-ALIST."
(when (org-lparse-get-converter in-fmt)
(or (ignore-errors (org-lparse-backend-get in-fmt 'OTHER-BACKENDS) )
(catch 'out-fmts
(dolist (c org-lparse-convert-capabilities)
(when (member in-fmt (nth 1 c))
(throw 'out-fmts (nth 2 c))))))))
(defun org-lparse-get-converter (in-fmt)
"Return converter associated with IN-FMT.
See `org-lparse-convert-capabilities' for further information."
(or (ignore-errors (org-lparse-backend-get in-fmt 'CONVERT-METHOD))
org-lparse-convert-process))
(defun org-lparse-all-backends ()
"Return all formats to which `org-lparse' could export to.
The return value is an alist of the form (TARGET-BACKEND
NATIVE-BACKEND-1 NATIVE-BACKEND-2 ...) with the condition that
the org file can be exported to TARGET-BACKEND via any one of
NATIVE-BACKEND-1, NATIVE-BACKEND-2 etc.
For example, an entry of the form \"(\"pdf\" \"odt\" \"xhtml\")\"
would mean that the org file could be exported to \"pdf\" format
by exporting natively either to \"xhtml\" or \"odt\" backends."
(let (all-backends)
(flet ((add (other native)
(let ((val (assoc-string other all-backends t)))
(if val (setcdr val (nconc (list native) (cdr val)))
(push (cons other (list native)) all-backends)))))
(loop for backend in org-lparse-native-backends
do (loop for other in (org-lparse-get-other-backends backend)
do (loop for other in
(mapcar #'car (org-lparse-get-other-backends backend))
do (add other backend))))
all-backends))
@ -428,97 +452,203 @@ PUB-DIR specifies the publishing directory."
(let* ((input (if (featurep 'ido) 'ido-completing-read 'completing-read))
(all-backends (org-lparse-all-backends))
(target-backend
(funcall input "Export to: " all-backends nil t nil))
(and all-backends
(funcall input "Export to: " all-backends nil t nil)))
(native-backend
(or
;; (and (org-lparse-backend-is-native-p target-backend)
;; target-backend)
(funcall input "Use Native backend: "
(cdr (assoc target-backend all-backends)) nil t nil))))
(let ((choices (if target-backend
(cdr (assoc target-backend all-backends))
(or org-lparse-native-backends
(error "No registered backends")))))
(funcall input "Use Native backend: " choices nil t nil))))
(list target-backend native-backend current-prefix-arg)))
(let* ((org-lparse-backend (intern native-backend))
(org-lparse-other-backend (intern target-backend)))
(org-lparse-other-backend (and target-backend
(intern target-backend))))
(unless (org-lparse-backend-is-native-p native-backend)
(error "Don't know how to export natively to backend %s" native-backend))
(unless (or (not target-backend)
(equal target-backend native-backend)
(member target-backend (org-lparse-get 'OTHER-BACKENDS)))
(assoc target-backend (org-lparse-get-other-backends
native-backend)))
(error "Don't know how to export to backend %s %s" target-backend
(format "via %s" native-backend)))
(run-hooks 'org-export-first-hook)
(org-do-lparse arg hidden ext-plist to-buffer body-only pub-dir)))
(defcustom org-lparse-convert-process
'("soffice" "-norestore" "-invisible" "-headless" "\"macro:///BasicODConverter.Main.Convert(%I,%f,%O)\"")
"Command to covert a Org exported format to other formats.
The variable is an list of the form (PROCESS ARG1 ARG2 ARG3
...). Format specifiers used in the ARGs are replaced as below.
(defcustom org-lparse-convert-processes
'(("BasicODConverter"
("soffice" "-norestore" "-invisible" "-headless"
"\"macro:///BasicODConverter.Main.Convert(%I,%f,%O)\""))
("unoconv"
("unoconv" "-f" "%f" "-o" "%d" "%i")))
"Specify a list of document converters and their usage.
The converters in this list are offered as choices while
customizing `org-lparse-convert-process'.
This variable is an alist where each element is of the
form (CONVERTER-NAME (CONVERTER-PROGRAM ARG1 ARG2 ...)).
CONVERTER-NAME is name of the converter. CONVERTER-PROGRAM is
the name of the executable. ARG1, ARG2 etc are command line
options that are passed to CONVERTER-PROGRAM. Format specifiers
can be used in the ARGs and they are interpreted as below:
%i input file name in full
%I input file name as a URL
%f format of the output file
%o output file name in full
%O output file name as a URL
%d output dir in full
%D output dir as a URL"
:group 'org-lparse)
%D output dir as a URL."
:group 'org-lparse
:type
'(choice
(const :tag "None" nil)
(alist :tag "Converters"
:key-type (string :tag "Converter Name")
:value-type (group (cons (string :tag "Executable")
(repeat (string :tag "Command line args")))))))
(defcustom org-lparse-convert-process nil
"Command to convert from an Org exported format to other formats.
During customization, the list of choices are populated from
`org-lparse-convert-processes'. Refer afore-mentioned variable
for further information."
:group 'org-lparse
:type '(choice :convert-widget
(lambda (w)
(apply 'widget-convert (widget-type w)
(eval (car (widget-get w :args)))))
`((const :tag "None" nil)
,@(mapcar (lambda (c)
`(const :tag ,(car c) ,(cadr c)))
org-lparse-convert-processes))))
(defcustom org-lparse-convert-capabilities
'(("Text"
("odt" "ott" "doc" "rtf")
(("pdf" "pdf") ("odt" "odt") ("xhtml" "html") ("rtf" "rtf")
("ott" "ott") ("doc" "doc") ("ooxml" "xml") ("html" "html")))
("Web"
("html" "xhtml") (("pdf" "pdf") ("odt" "txt") ("html" "html")))
("Spreadsheet"
("ods" "ots" "xls" "csv")
(("pdf" "pdf") ("ots" "ots") ("html" "html") ("csv" "csv")
("ods" "ods") ("xls" "xls") ("xhtml" "xhtml") ("ooxml" "xml")))
("Presentation"
("odp" "otp" "ppt")
(("pdf" "pdf") ("swf" "swf") ("odp" "odp") ("xhtml" "xml")
("otp" "otp") ("ppt" "ppt") ("odg" "odg") ("html" "html"))))
"Specify input and output formats of `org-lparse-convert-process'.
More correctly, specify the set of input and output formats that
the user is actually interested in.
This variable is an alist where each element is of the
form (DOCUMENT-CLASS INPUT-FMT-LIST OUTPUT-FMT-ALIST).
INPUT-FMT-LIST is a list of INPUT-FMTs. OUTPUT-FMT-ALIST is an
alist where each element is of the form (OUTPUT-FMT
OUTPUT-FILE-EXTENSION).
The variable is interpreted as follows:
`org-lparse-convert-process' can take any document that is in
INPUT-FMT-LIST and produce any document that is in the
OUTPUT-FMT-LIST. A document converted to OUTPUT-FMT will have
OUTPUT-FILE-EXTENSION as the file name extension. OUTPUT-FMT
serves dual purposes:
- It is used for populating completion candidates during
`org-lparse' and `org-lparse-convert' commands.
- It is used as the value of \"%f\" specifier in
`org-lparse-convert-process'.
DOCUMENT-CLASS is used to group a set of file formats in
INPUT-FMT-LIST in to a single class.
Note that this variable inherently captures how LibreOffice based
converters work. LibreOffice maps documents of various formats
to classes like Text, Web, Spreadsheet, Presentation etc and
allow document of a given class (irrespective of it's source
format) to be converted to any of the export formats associated
with that class.
See default setting of this variable for an typical
configuration."
:group 'org-lparse
:type
'(choice
(const :tag "None" nil)
(alist :key-type (string :tag "Document Class")
:value-type
(group (repeat :tag "Input formats" (string :tag "Input format"))
(alist :tag "Output formats"
:key-type (string :tag "Output format")
:value-type
(group (string :tag "Output file extension")))))))
(defcustom org-lparse-use-flashy-warning nil
"Use flashy warnings when exporting to ODT."
"Control flashing of messages logged with `org-lparse-warn'.
When non-nil, messages are fontified with warning face and the
exporter lingers for a while to catch user's attention."
:type 'boolean
:group 'org-export)
:group 'org-lparse)
(defun org-lparse-convert (&optional in-file fmt)
"Convert file from one format to another using a converter.
(defun org-lparse-convert (&optional in-file out-fmt prefix-arg)
"Convert IN-FILE to format OUT-FMT using a command line converter.
IN-FILE is the file to be converted. If unspecified, it defaults
to variable `buffer-file-name'. FMT is the desired output format. If the
backend has registered a CONVERT-METHOD via it's get function
then that converter is used. Otherwise
`org-export-conver-process' is used."
to variable `buffer-file-name'. OUT-FMT is the desired output
format. If the backend has registered a CONVERT-METHOD as part
of it's get function then that converter is used. Otherwise
`org-lparse-convert-process' is used. If PREFIX-ARG is non-nil
then the newly converted file is opened using `org-open-file'."
(interactive
(let* ((input (if (featurep 'ido) 'ido-completing-read 'completing-read))
(in-file (read-file-name "File to be converted: "
nil buffer-file-name t))
(fmt (funcall input "Output format: "
(or (ignore-errors
(org-lparse-get-other-backends
(file-name-extension in-file)))
(org-lparse-all-backends))
nil nil nil)))
(list in-file fmt)))
(in-fmt (file-name-extension in-file))
(out-fmt-choices (org-lparse-get-other-backends in-fmt))
(out-fmt
(or (and out-fmt-choices
(funcall input "Output format: "
out-fmt-choices nil nil nil))
(error
"No known converter or no known output formats for %s files"
in-fmt))))
(list in-file out-fmt current-prefix-arg)))
(require 'browse-url)
(let* ((in-file (expand-file-name (or in-file buffer-file-name)))
(fmt (or fmt "doc") )
(out-file (concat (file-name-sans-extension in-file) "." fmt))
(dummy (or (file-readable-p in-file)
(error "Cannot read %s" in-file)))
(in-fmt (file-name-extension in-file))
(out-fmt (or out-fmt (error "Output format unspecified")))
(convert-process (org-lparse-get-converter in-fmt))
(program (car convert-process))
(dummy (and (or program (error "Converter not configured"))
(or (executable-find program)
(error "Cannot find converter %s" program))))
(out-fmt-alist
(or (assoc out-fmt (org-lparse-get-other-backends in-fmt))
(error "Cannot convert from %s to %s format" in-fmt out-fmt)))
(out-file (concat (file-name-sans-extension in-file) "."
(nth 1 out-fmt-alist)))
(out-dir (file-name-directory in-file))
(backend (when (boundp 'org-lparse-backend) org-lparse-backend))
(convert-process
(or (ignore-errors (org-lparse-backend-get backend 'CONVERT-METHOD))
org-lparse-convert-process))
program arglist)
(setq program (and convert-process (consp convert-process)
(car convert-process)))
(unless (executable-find program)
(error "Unable to locate the converter %s" program))
(setq arglist
(mapcar (lambda (arg)
(format-spec arg `((?i . ,in-file)
(?I . ,(browse-url-file-url in-file))
(?f . ,fmt)
(?o . ,out-file)
(?O . ,(browse-url-file-url out-file))
(?d . ,out-dir)
(?D . ,(browse-url-file-url out-dir)))))
(cdr convert-process)))
(ignore-errors (delete-file out-file))
(arglist (mapcar (lambda (arg)
(format-spec
arg `((?i . ,in-file)
(?I . ,(browse-url-file-url in-file))
(?f . ,out-fmt)
(?o . ,out-file)
(?O . ,(browse-url-file-url out-file))
(?d . ,out-dir)
(?D . ,(browse-url-file-url out-dir)))))
(cdr convert-process))))
(when (file-exists-p out-file)
(delete-file out-file))
(message "Executing %s %s" program (mapconcat 'identity arglist " "))
(apply 'call-process program nil nil nil arglist)
(cond
((file-exists-p out-file)
(message "Exported to %s using %s" out-file program)
(when prefix-arg
(message "Opening %s..." out-file)
(org-open-file out-file))
out-file
;; (set-buffer (find-file-noselect out-file))
)
@ -1134,7 +1264,8 @@ version."
(or (when (and (boundp 'org-lparse-other-backend)
org-lparse-other-backend
(not (equal org-lparse-backend org-lparse-other-backend)))
(let ((org-lparse-convert-process (org-lparse-get 'CONVERT-METHOD)))
(let ((org-lparse-convert-process
(org-lparse-get-converter org-lparse-backend)))
(when org-lparse-convert-process
(org-lparse-convert buffer-file-name
(symbol-name org-lparse-other-backend)))))
@ -1145,8 +1276,7 @@ version."
(t (current-buffer))))))
(defun org-lparse-format-table (lines olines)
"Retuns backend-specific code for org-type and table-type
tables."
"Retuns backend-specific code for org-type and table-type tables."
(if (stringp lines)
(setq lines (org-split-string lines "\n")))
(if (string-match "^[ \t]*|" (car lines))
@ -1623,7 +1753,7 @@ t : Log all invocations of `org-lparse-begin', `org-lparse-end'
(const :tag "Format and Control callbacks" t)))
(defun org-lparse-begin (entity &rest args)
"Begin ENTITY in current buffer. ARGS is entity specific.
"Begin ENTITY in current buffer. ARGS is entity specific.
ENTITY can be one of PARAGRAPH, LIST, LIST-ITEM etc.
Use (org-lparse-begin 'LIST \"o\") to begin a list in current
@ -1640,7 +1770,7 @@ information."
(apply f args)))
(defun org-lparse-end (entity &rest args)
"Close ENTITY in current buffer. ARGS is entity specific.
"Close ENTITY in current buffer. ARGS is entity specific.
ENTITY can be one of PARAGRAPH, LIST, LIST-ITEM
etc.

View File

@ -266,6 +266,30 @@ be linked only."
(error "Cannot determine style name for entity %s of type %s"
entity category))))
(defcustom org-export-odt-preferred-output-format nil
"Automatically post-process to this format after exporting to \"odt\".
Interactive commands `org-export-as-odt' and
`org-export-as-odt-and-open' export first to \"odt\" format and
then use an external converter to convert the resulting document
to this format.
The converter used is that specified with CONVERT-METHOD option
in `org-odt-get'. If the above option is unspecified then
`org-lparse-convert-process' is used.
The format specified here should be listed in OTHER-BACKENDS
option of `org-odt-get' or `org-lparse-convert-capabilities' as
appropriate."
:group 'org-odt
:type '(choice :convert-widget
(lambda (w)
(apply 'widget-convert (widget-type w)
(eval (car (widget-get w :args)))))
`((const :tag "None" nil)
,@(mapcar (lambda (c)
`(const :tag ,(car c) ,(car c)))
(org-lparse-get-other-backends "odt")))))
;;;###autoload
(defun org-export-as-odt-and-open (arg)
"Export the outline as ODT and immediately open it with a browser.
@ -273,7 +297,8 @@ If there is an active region, export only the region.
The prefix ARG specifies how many levels of the outline should become
headlines. The default is 3. Lower levels will become bulleted lists."
(interactive "P")
(org-lparse-and-open "odt" "odt" arg))
(org-lparse-and-open
(or org-export-odt-preferred-output-format "odt") "odt" arg))
;;;###autoload
(defun org-export-as-odt-batch ()
@ -338,7 +363,8 @@ the file header and footer, simply return the content of
<body>...</body>, without even the body tags themselves. When
PUB-DIR is set, use this as the publishing directory."
(interactive "P")
(org-lparse "odt" "odt" arg hidden ext-plist to-buffer body-only pub-dir))
(org-lparse (or org-export-odt-preferred-output-format "odt")
"odt" arg hidden ext-plist to-buffer body-only pub-dir))
(defvar org-odt-entity-control-callbacks-alist
`((EXPORT
@ -1436,11 +1462,8 @@ MAY-INLINE-P allows inlining it as an image."
(INIT-METHOD 'org-odt-init-outfile)
(FINAL-METHOD 'org-odt-finalize-outfile)
(SAVE-METHOD 'org-odt-save-as-outfile)
(OTHER-BACKENDS
'("bib" "doc" "doc6" "doc95" "html" "xhtml" "latex" "odt" "ott" "pdf" "rtf"
"sdw" "sdw3" "sdw4" "stw " "sxw" "mediawiki" "text" "txt" "uot" "vor"
"vor3" "vor4" "docbook" "ooxml" "ppt" "odp"))
(CONVERT-METHOD org-lparse-convert-process)
;; (OTHER-BACKENDS) ; see note in `org-xhtml-get'
;; (CONVERT-METHOD) ; see note in `org-xhtml-get'
(TOPLEVEL-HLEVEL 1)
(SPECIAL-STRING-REGEXPS org-export-odt-special-string-regexps)
(INLINE-IMAGES 'maybe)

View File

@ -1659,10 +1659,17 @@ lang=\"%s\" xml:lang=\"%s\">
(INIT-METHOD nil)
(SAVE-METHOD nil)
(CLEANUP-METHOD nil)
(OTHER-BACKENDS
'("xhtml" "etext" "html" "html10" "mediawiki" "pdf" "sdw" "sdw3" "sdw4"
"text" "text10" "odt" "vor" "vor4"))
(CONVERT-METHOD org-lparse-convert-process)
;; (OTHER-BACKENDS
;; ;; There is a provision to register a per-backend converter and
;; ;; output formats. Refer `org-lparse-get-converter' and
;; ;; `org-lparse-get-other-backends'.
;; ;; The default behaviour is to use `org-lparse-convert-process'
;; ;; and `org-lparse-convert-capabilities'.
;; )
;; (CONVERT-METHOD
;; ;; See note above
;; )
(EXPORT-DIR (org-export-directory :html opt-plist))
(FILE-NAME-EXTENSION (plist-get opt-plist :html-extension))
(EXPORT-BUFFER-NAME "*Org HTML Export*")