Skip to content

Commit 4729e21

Browse files
committed
Fix output order when using pandoc conversion
Fixes #351.
1 parent 57306bf commit 4729e21

File tree

2 files changed

+114
-4
lines changed

2 files changed

+114
-4
lines changed

jupyter-org-client.el

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,10 @@ If PARAMS has non-nil value for key ':pandoc' and TYPE is in
694694
Otherwise, wrap it in an export block."
695695
(if (and (alist-get :pandoc params)
696696
(member type jupyter-org-pandoc-convertable))
697-
(jupyter-org-raw-string (jupyter-pandoc-convert type "org" value))
697+
(list 'pandoc
698+
(list :text "Converting..."
699+
:type type
700+
:value value))
698701
(jupyter-org-export-block type value)))
699702

700703
(defun jupyter-org-export-block (type value)
@@ -1469,6 +1472,43 @@ Assumes `point' is on the #+RESULTS keyword line."
14691472
(set-marker end nil)))
14701473
(jupyter-org--mark-stream-result-newline result))))))
14711474

1475+
(defun jupyter-org--start-pandoc-conversion (el cb)
1476+
(jupyter-pandoc-convert
1477+
(org-element-property :type el) "org"
1478+
(org-element-property :value el)
1479+
cb))
1480+
1481+
(defun jupyter-org-pandoc-placeholder-element (req el)
1482+
"Launch a Pandoc conversion process of EL, return a placeholder string.
1483+
REQ is the `jupyter-org-request' which generated EL as a result.
1484+
1485+
The placeholder string is meant to be inserted into the Org
1486+
buffer and replaced with the result of conversion when ready.
1487+
1488+
EL is an Org element with the properties
1489+
1490+
:text The placeholder text to use.
1491+
:type The type of syntax from which to convert.
1492+
:value The code with the corresponding syntax."
1493+
(letrec ((buf (current-buffer))
1494+
(src-pos (copy-marker (jupyter-org-request-marker req)))
1495+
(cb (lambda ()
1496+
(let ((to-string (buffer-string)))
1497+
(with-current-buffer buf
1498+
(save-excursion
1499+
(goto-char src-pos)
1500+
(set-marker src-pos nil)
1501+
(when (text-property-search-forward 'jupyter-pandoc proc)
1502+
(delete-region (point)
1503+
(1+ (next-single-property-change
1504+
(point) 'jupyter-pandoc)))
1505+
(insert to-string)))))))
1506+
(proc (jupyter-org--start-pandoc-conversion el cb)))
1507+
(jupyter-org-raw-string
1508+
(propertize
1509+
(org-element-property :text el)
1510+
'jupyter-pandoc proc))))
1511+
14721512
(cl-defgeneric jupyter-org--insert-result (req context result)
14731513
"For REQ and given CONTEXT, insert RESULT.
14741514
REQ is a `jupyter-org-request' that contains the context of the
@@ -1479,7 +1519,10 @@ source block associated with REQ.
14791519
14801520
RESULT is the new result, as an org element, to be inserted.")
14811521

1482-
(cl-defmethod jupyter-org--insert-result (_req context result)
1522+
(cl-defmethod jupyter-org--insert-result (req context result)
1523+
(when (eq (org-element-type result) 'pandoc)
1524+
(setq result (jupyter-org-pandoc-placeholder-element req result)))
1525+
14831526
(insert (org-element-interpret-data
14841527
(jupyter-org--wrap-result-maybe
14851528
context (if (jupyter-org--stream-result-p result)
@@ -1513,7 +1556,10 @@ RESULT is the new result, as an org element, to be inserted.")
15131556
(cond
15141557
((jupyter-org-request-silent-p req)
15151558
(unless (equal (jupyter-org-request-silent-p req) "none")
1516-
(message "%s" (org-element-interpret-data result))))
1559+
(if (eq (org-element-type result) 'pandoc)
1560+
(message "[%s] %s" (org-element-property :type result)
1561+
(org-element-property :value result))
1562+
(message "%s" (org-element-interpret-data result)))))
15171563
((jupyter-org-request-async-p req)
15181564
(jupyter-org--clear-request-id req)
15191565
(jupyter-org--do-insert-result req result))
@@ -1573,12 +1619,31 @@ example-block elements."
15731619
results
15741620
:initial-value nil)))))
15751621

1622+
(defun jupyter-org--process-pandoc-results (results)
1623+
(let* ((results (copy-sequence results))
1624+
(head results)
1625+
(procs '()))
1626+
(while head
1627+
(when (eq (org-element-type (car head)) 'pandoc)
1628+
(push
1629+
(jupyter-org--start-pandoc-conversion
1630+
(car head)
1631+
(let ((h head))
1632+
(lambda ()
1633+
(setcar h (jupyter-org-raw-string (buffer-string))))))
1634+
procs))
1635+
(setq head (cdr head)))
1636+
(while (cl-find-if #'process-live-p procs)
1637+
(accept-process-output nil 0.1))
1638+
results))
1639+
15761640
(defun jupyter-org-sync-results (req)
15771641
"Return the result string in org syntax for the results of REQ.
15781642
Meant to be used as the return value of
15791643
`org-babel-execute:jupyter'."
15801644
(when-let* ((results (jupyter-org--coalesce-stream-results
1581-
(nreverse (jupyter-org-request-results req))))
1645+
(jupyter-org--process-pandoc-results
1646+
(nreverse (jupyter-org-request-results req)))))
15821647
(params (jupyter-org-request-block-params req))
15831648
(result-params (alist-get :result-params params)))
15841649
(org-element-interpret-data

test/jupyter-test.el

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2929,6 +2929,51 @@ publish_display_data({'text/plain': \"foo\", 'text/latex': \"$\\alpha$\"});"
29292929
(forward-line)
29302930
(should (looking-at-p ": hello"))))))
29312931

2932+
(ert-deftest org-babel-jupyter-pandoc-output-order ()
2933+
:tags '(org pandoc)
2934+
;; See #351
2935+
(ert-info ("Ensure output order doesn't depend on Pandoc processing time")
2936+
(ert-info ("Async")
2937+
(jupyter-org-test-src-block
2938+
"\
2939+
from IPython.display import HTML, Markdown, Latex
2940+
2941+
print(1)
2942+
display(HTML('<b>bold</b>'),
2943+
Latex('\\\\bf{lbold}'),
2944+
Markdown('**mbold**'))
2945+
print(2)"
2946+
"\
2947+
:RESULTS:
2948+
: 1
2949+
*bold*
2950+
*lbold*
2951+
*mbold*
2952+
: 2
2953+
:END:
2954+
"
2955+
:async "yes"
2956+
:pandoc "t"))
2957+
(ert-info ("Sync")
2958+
(jupyter-org-test-src-block
2959+
"\
2960+
from IPython.display import HTML, Markdown, Latex
2961+
2962+
print(1)
2963+
display(HTML('<b>bold</b>'),
2964+
Latex('\\\\bf{lbold}'),
2965+
Markdown('**mbold**'))
2966+
print(2)"
2967+
"\
2968+
:RESULTS:
2969+
: 1
2970+
*bold*
2971+
*lbold*
2972+
*mbold*
2973+
: 2
2974+
:END:
2975+
"
2976+
:pandoc "t"))))
29322977

29332978
;; Local Variables:
29342979
;; byte-compile-warnings: (unresolved obsolete lexical)

0 commit comments

Comments
 (0)