2

Are there any libraries out there that can take the markdown code fence block and execute it via org babel? Ie, something like

'''js
var a = 1
var b = 2

return a + b
'''

Reasoning:

I don't see not too much difference between a #+BEGIN_SRC .... #+END_SRC block and a '''...''' block. I know that it's ultimately possible to be able to convert back and forth between a markdown file and an org file (via pandoc) but I'd like to have the code execution functionality of org-babel within a markdown file. I'm wondering if anyone has extracted that functionality from org-babel and if not, maybe a guide to how to go about it.

1
  • Please clarify the question along the lines requested in the extended comment in my "answer".
    – NickD
    Dec 15, 2020 at 17:44

2 Answers 2

3

[More of a comment than an answer, but too long anyway - if you clarify your question, I will either edit the answer or delete it altogether, depending on wht exactly you want.]

Yes, if you translate it to the form that Org babel wants:

#+begin_src js
var a = 1
var b = 2

return a + b
#+end_src

#+RESULTS:
: 3

and you load the ob-js library. I suspect you want something else, but it is not clear to me what exactly that is from your question. Maybe you can clarify your question and specify what the Org mode file should contain and then what you'd like to accomplish.

EDIT (in response to the added information in the question): The transformations that pandoc does between Org mode files and Markdown files are purely textual. You need an underlying execution engine in order to execute code blocks: that is provided by Org babel and Emacs for Org mode files, but there is nothing similar for Markdown files (even if you open them in Emacs). It is conceivable that an MD babel implementation could be made (e.g. code blocks are used in both cases for pretty-printing purposes, fontification, coloring etc.) but the details are sufficiently different to make it a non-trivial pursuit (e.g. there is a whole slew of header arguments that can be passed to an Org mode code block: there is nothing like that in any Markdown syntax that I know of), and although you might be able to extend MD syntax to cover some or all of what MD code blocks are missing, then you'd have to port Org babel to "MD babel" to provide the execution engine (and only in Emacs, remember). So, I think the answer to your question is: No, there is nothing like that currently.

As for how to do it in the above context (while editing the MD file in Emacs), I think the simplest thing is to keep the Org mode syntax for code blocks as is. The MD code block would be:

``` js <header-args>

code

```

where everything after the opening triple-backtick and before the closing one is just an Org mode code block without the #+BEGIN_SRC and #+END_SRC markers. The "MD babel engine" would just replace the triple backticks with #+BEGIN_SRC ... #+END_SRC, write the code block to a temporary file foo.org and then open the file in Org mode and run the code block using Org babel, and then copy the #+RESULTS block and paste it into the MD file after the code block.That should not be too difficult, but the major mode used for the MD file would have to be taught how to deal with the extra stuff (e.g. the header args and the #+RESULTS: block) if it cared.

But then the question becomes: why do all that in MD mode? Why not do the whole thing in Org mode and export the file to MD at the end and be done with it?

1
  • Thanks for that. Please see my further explanation.
    – zcaudate
    Dec 16, 2020 at 2:11
2

I am interested in this functionality and believe we are looking for the same thing. I didn't find a ready-made one so here's a quick-and-dirty take. It only supports sh now, and requires cl and magnar's s

(defun markdown-eval-current-code-block ()
  (interactive)
  (save-excursion
    (forward-paragraph)
    (let ((start (progn
                   (backward-paragraph)
                   (point))))
      (forward-paragraph)
      (let ((region-string
             (s-trim (buffer-substring start (point)))))
        (when (and (s-starts-with? "```" region-string)
                   (s-ends-with? "\n```" region-string))
          (let* ((split-1 (s-split-up-to
                           "\n"
                           (substring region-string
                                      0
                                      (- (length region-string) 4))
                           1))
                 (language (substring (car split-1) 3))
                 (code-body (cadr split-1)))
            (cond ((string= language "sh")
                   (insert
                    (format "```\n%s\n```"
                            (org-babel-sh-evaluate
                             nil ;; session
                             code-body
                             ;; params
                             '((:colname-names)
                               (:rowname-names)
                               (:result-params . ("replace" "output"))
                               (:result-type . "output")
                               (:exports . code)
                               (:session . none)
                               (:cache . no)
                               (:noweb . no)
                               (:hlines . no)
                               (:tangle . no))))))
                  (t (progn
                       (message "I can only process sh blocks now. Improve me please."))))))))))

Assuming your cursor is inside a code fence, it

  • searches upwards for the start of the current paragraph
  • downwards for the end of the current paragraph
  • checks if it's a code fence
  • detects if it understands the code fence's language marker (i.e. "sh")
  • passes the code body into org-babel-sh-evaluate and spits the result into a new fenced block

to improve this:

  • needs better inside-code-fence detection
  • better language detection and code body extraction
  • integrate the language marker directly with the enabled org-babel-*-evaulate dynamically loaded functions

Also note the params association list (colname-names etc) is almost certainly a bad one as it was captured from playing with org-babel-sh-evaluate. The alist cons values (like code, none, no) should probably be strings, but for this example they don't matter.

There is one association (:results . replace output) which is removed here, because with it the function errors on call, possibly due to lacking a real org-mode context.

3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.