5

What I'm trying to achieve is very simple: take a source block, write it to a temp file, pass the file name as an argument to an executable which will run it, and then include the output in the #RESULTS block. The snippet below seems close, but when I try to execute the code block the executable (nim) complains that it expected a file name so I guess it passes the block body via stdin instead of temp file:

(defun org-babel-execute:nim (body params)
 "Execute a block of Nim code with org-babel."
 (message "executing Nim source code block")
    (org-babel-eval "nim r " body))

Second attempt, based on @NickD's comment and org-babel-execute:dot:

  (defun org-babel-execute:nim (body params)
    "Execute a block of Nim code with org-babel."
    (message "executing Nim source code block")
    (let* (in-file (org-babel-temp-file "nim-")))
    (with-temp-file in-file
      (insert body))
    (org-babel-eval (format "nim r %s" (org-babel-process-file-name in-file))))

When trying to execute a code block, getting "Symbol's value as variable is void: in-file"

3
  • 1
    Your guess may be correct. As one example, check out org-babel-execute:dot which does something very similar to what you are trying to do.
    – NickD
    Oct 26, 2020 at 23:57
  • thanks @NickD, tried cobbling something together based on that but getting a differetn error; I updated the question Oct 27, 2020 at 7:25
  • 1
    The let* is wrong, it doesn't bind in-file to anything and the following code should be in its body instead. This is absolutely not Org's fault.
    – wasamasa
    Oct 27, 2020 at 7:37

1 Answer 1

10

You need to define org-babel-execute:nim:

(defun org-babel-execute:nim (body params)
  "Execute a block of Nim code with org-babel."

While we could use nim via STDIN, it will clutter the current working directory. Therefore, let us use a temporary file instead. nim also needs files to start with a letter and end with .nim, so we adjust the arguments to org-babel-temp-file. For some less noise, let's also change the default verbosity, but make it adjustable:

(let ((in-file (org-babel-temp-file "n" ".nim"))
      (verbosity (or (cdr (assq :verbosity params)) 0)))
  (with-temp-file in-file
    (insert body))

Last but not least, we call org-babel-eval. Since we supplied the original body in our in-file, we can keep the body argument of org-babel-eval empty. One could probably also change the working directory to a temporary directory instead, but I'm not familiar with nim, at all.

(org-babel-eval
 (format "nim compile --verbosity=%d --run %s" verbosity
         (org-babel-process-file-name in-file))
 "")))

Here's all at once:

(defun org-babel-execute:nim (body params)
  "Execute a block of Nim code with org-babel."
  (let ((in-file (org-babel-temp-file "n" ".nim"))
        (verbosity (or (cdr (assq :verbosity params)) 0)))
    (with-temp-file in-file
      (insert body))
    (org-babel-eval
     (format "nim compile --verbosity=%d --run %s" verbosity
             (org-babel-process-file-name in-file))
     "")))

And here's an example:

#+begin_src nim
var name : string = "Woof"
echo "Hi, ", name, "!"
#+end_src

#+RESULTS:
: Hi, Woof!
1

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.