Skip to content
David Maus M. A.

Quick'n'dirty: Compile XSL-FO to PDF from Emacs

David Maus, 16. Apr 2018

Execute Apache FOP from within Emacs and compile current file to PDF (or any other supported output formats).

xslfo-mode.el
;;; xslfo-mode.el --- Minor mode for working with XSL-FO files

(defvar xslfo-fop-outspec '(("pdf"    . "pdf")
                            ("rtf"    . "rtf")
                            ("txt"    . "txt")
                            ("at"     . "xml")
                            ("if"     . "xml")
                            ("png"    . "png")
                            ("tiff"   . "tiff")
                            ("ps"     . "ps")
                            ("pcl"    . "pcl")
                            ("pdfa1b" . "pdf"))
  "Apache FOP output formats.")

(define-minor-mode xslfo-mode
  "Minor mode for working with XSL-FO files."
  :init-value nil
  :lighter "XSL-FO"
  :keymap `((,(kbd "C-c C-c") . xslfo-compile)))

(defmacro xslfo-fop-outspec-extension (name)
  `(or (cdr (assoc ,name xslfo-fop-outspec)) "bin"))

(defun xslfo-compile (&optional arg)
  (interactive "P")
  (let* ((outspec (if arg (completing-read "Output format: " (mapcar #'car xslfo-fop-outspec) #'stringp t (caar xslfo-fop-outspec))
                    "pdf"))
         (srcfile (or buffer-file-name (error "Buffer not visiting a file")))
         (outfile (concat (expand-file-name (file-name-sans-extension srcfile)) "." (xslfo-fop-outspec-extension outspec)))
         (bufname (concat "*XSL-FO: " outfile "*")))
    (with-current-buffer (get-buffer-create bufname)
      (erase-buffer)
      (when (= 0 (apply #'call-process (executable-find "fop") nil t t (list (concat "-" outspec) outfile srcfile)))
        (message "Wrote %s" outfile)
        (display-buffer bufname)))))

(provide 'xslfo-mode)

;;; xslfo-mode.el ends here