Add pandoc conversion of rich outputs (#97)

This commit is contained in:
jackkamm 2019-04-28 13:17:19 -07:00 committed by Nathaniel Nicandro
parent 18a3a27139
commit 748598b7be
3 changed files with 60 additions and 5 deletions

View file

@ -490,6 +490,13 @@ generated image file names.
Whenever you run a code block multiple times and replace its results, before Whenever you run a code block multiple times and replace its results, before
the results are replaced, any generated files will be deleted to reduce the the results are replaced, any generated files will be deleted to reduce the
clutter in =org-babel-jupyter-resource-directory=. clutter in =org-babel-jupyter-resource-directory=.
**** Convert rich kernel output with the =:pandoc= header argument
By default html, markdown, and latex results are wrapped in a =BEGIN_EXPORT=
block. If the header argument =:pandoc t= is set, they are instead
converted to org-mode format with [[https://pandoc.org/][pandoc]]. You can control which outputs get
converted with the custom variable =jupyter-org-pandoc-convertable=.
*** Editing the contents of a code block *** Editing the contents of a code block
When editing a Jupyter code block's contents, i.e. by pressing =C-c '= when at When editing a Jupyter code block's contents, i.e. by pressing =C-c '= when at

View file

@ -625,6 +625,38 @@ message."
(when (= (point) (point-min)) (when (= (point) (point-min))
(error "No display matching id (%s)" id))))) (error "No display matching id (%s)" id)))))
;;; Pandoc
(defun jupyter-pandoc-convert (from to from-string &optional callback)
"Use pandoc to convert a string in FROM format to TO format.
Starts a process and converts FROM-STRING, assumed to be in FROM
format, to a string in TO format and returns the converted
string.
If CALLBACK is specified, return the process object. When the
process exits, call CALLBACK with zero arguments and with the
buffer containing the converted string current."
(cl-assert (executable-find "pandoc"))
(let* ((process-connection-type nil)
(proc (start-process
"jupyter-pandoc"
(generate-new-buffer " *jupyter-pandoc*")
"pandoc" "-f" from "-t" to "--")))
(set-process-sentinel
proc (lambda (proc _)
(when (memq (process-status proc) '(exit signal))
(with-current-buffer (process-buffer proc)
(funcall callback)
(kill-buffer (process-buffer proc))))))
(process-send-string proc from-string)
(process-send-eof proc)
(if callback proc
(let ((to-string ""))
(setq callback (lambda () (setq to-string (buffer-string))))
(while (zerop (length to-string))
(accept-process-output nil 1))
to-string))))
(provide 'jupyter-mime) (provide 'jupyter-mime)
;;; jupyter-mime.el ends here ;;; jupyter-mime.el ends here

View file

@ -66,6 +66,12 @@ automatically be shown if this is non-nil."
:group 'ob-jupyter :group 'ob-jupyter
:type 'boolean) :type 'boolean)
(defcustom jupyter-org-pandoc-convertable
'("html" "markdown" "latex")
"Export blocks to convert to org-mode when ':pandoc t' header is set."
:group 'ob-jupyter
:type 'string)
(defconst jupyter-org-mime-types '(:text/org (defconst jupyter-org-mime-types '(:text/org
;; Prioritize images over html ;; Prioritize images over html
:image/svg+xml :image/jpeg :image/png :image/svg+xml :image/jpeg :image/png
@ -648,6 +654,16 @@ inserted without modification as the result of a code block."
"Return a comment `org-element' with VALUE." "Return a comment `org-element' with VALUE."
(list 'comment (list :value value))) (list 'comment (list :value value)))
(defun jupyter-org-export-block-or-pandoc (type value params)
"Returns VALUE, either converted with pandoc or in an export block.
If PARAMS has non-nil value for key ':pandoc' and TYPE is in
`jupyter-org-pandoc-convertable', convert the result with pandoc.
Otherwise, wrap it in an export block."
(if (and (alist-get :pandoc params)
(member type jupyter-org-pandoc-convertable))
(jupyter-org-raw-string (jupyter-pandoc-convert type "org" value))
(jupyter-org-export-block type value)))
(defun jupyter-org-export-block (type value) (defun jupyter-org-export-block (type value)
"Return an export-block `org-element'. "Return an export-block `org-element'.
The block will export TYPE and the contents of the block will be The block will export TYPE and the contents of the block will be
@ -955,9 +971,9 @@ passed to Jupyter org-mode source blocks."
&optional metadata) &optional metadata)
(jupyter-org--image-result mime params nil data metadata)) (jupyter-org--image-result mime params nil data metadata))
(cl-defmethod jupyter-org-result ((_mime (eql :text/markdown)) _params data (cl-defmethod jupyter-org-result ((_mime (eql :text/markdown)) params data
&optional _metadata) &optional _metadata)
(jupyter-org-export-block "markdown" data)) (jupyter-org-export-block-or-pandoc "markdown" data params))
(defun jupyter-org--parse-latex-element (data) (defun jupyter-org--parse-latex-element (data)
"Return a latex-fragment or latex-environment org-element obtained from DATA. "Return a latex-fragment or latex-environment org-element obtained from DATA.
@ -989,11 +1005,11 @@ parsed, wrap DATA in a minipage environment and return it."
&optional _metadata) &optional _metadata)
(if (member "raw" (alist-get :result-params params)) (if (member "raw" (alist-get :result-params params))
(jupyter-org--parse-latex-element data) (jupyter-org--parse-latex-element data)
(jupyter-org-export-block "latex" data))) (jupyter-org-export-block-or-pandoc "latex" data params)))
(cl-defmethod jupyter-org-result ((_mime (eql :text/html)) _params data (cl-defmethod jupyter-org-result ((_mime (eql :text/html)) params data
&optional _metadata) &optional _metadata)
(jupyter-org-export-block "html" data)) (jupyter-org-export-block-or-pandoc "html" data params))
;; NOTE: The order of :around methods is that the more specialized wraps the ;; NOTE: The order of :around methods is that the more specialized wraps the
;; more general, this makes sense since it is how the primary methods work as ;; more general, this makes sense since it is how the primary methods work as