Re: [O] [PATCH] new :async feature for org-babel-clojure
Hi Nicolas, Right now, async is really more about "feedback" than "asynchronous". However it has never been clear is it was possible or not, and if so, how :) Any pointers on how this could be done in emacs? You could start a new Emacs evaluating some code in a subprocess, with `start-process' and collect return value. You may want to have a look at `org-export-async-start' or "async.el" library in ELPA. Unfortunately, it is not yet possible to re-use the latter in Org code, since it is unavailable in vanilla Emacs. The hard part, IMO, is to bring the right context in the subprocess (e.g., the environment should be the same, other blocks may be needed, etc.). Yeah, will have to take some more time to check that, I probably have much to learn regarding Elisp itself first. Rethinking about that, would it not be better to remove the confusion by changing the terminology I used: ":async"? What it really is is to have feedback of the underlying process, and not really an asynchronous process. I thought about two possibilities: (1) creating two new results options: :output-process and :value-process. Which means that we output the underlying process of a :output or :value :results (2) renaming :async by :show-process or something similar. Then we take the time to check how a real asynchronous system can be put in place. Thoughts? Thanks, Fred Regards,
Re: [O] [PATCH] new :async feature for org-babel-clojure
Hello, Frederick Giasson writes: > Right now, async is really more about "feedback" than "asynchronous". > However it has never been clear is it was possible or not, and if so, > how :) > > Any pointers on how this could be done in emacs? You could start a new Emacs evaluating some code in a subprocess, with `start-process' and collect return value. You may want to have a look at `org-export-async-start' or "async.el" library in ELPA. Unfortunately, it is not yet possible to re-use the latter in Org code, since it is unavailable in vanilla Emacs. The hard part, IMO, is to bring the right context in the subprocess (e.g., the environment should be the same, other blocks may be needed, etc.). Regards, -- Nicolas Goaziou
Re: [O] [PATCH] new :async feature for org-babel-clojure
Hi Nicolas, As for 3 and 4, I think a more general mechanism for asynchrnous eval'ing would be preferable. Besides, AFAIU, because of ; Wait until the nREPL code finished to be processed (while (not (member "done" status)) (nrepl-dict-put response "status" (remove "need-input" status)) (accept-process-output nil 0.01) (redisplay)) `org-babel-execute:clojure' is still somewhat synchronous, isn't it? Yes, and this is what I was mentioning initially (here, I think, and on my blogpost about it). I just don't know how all this processing could be handled in a different thread. That way it would free the current threads and we could continue to work with the current instance while the processing is happening because as I mentioned, everything is still stuck during the processing. Right now, async is really more about "feedback" than "asynchronous". However it has never been clear is it was possible or not, and if so, how :) Any pointers on how this could be done in emacs? Thanks, Fred Regards,
Re: [O] [PATCH] new :async feature for org-babel-clojure
Hello, Frederick Giasson writes: > Any news regarding these latest fixes to that patch? They look good. Thank you for the heads-up. Could you merge patches 1 2 and 5 (Org series) into a single one for inclusion? As for 3 and 4, I think a more general mechanism for asynchrnous eval'ing would be preferable. Besides, AFAIU, because of ; Wait until the nREPL code finished to be processed (while (not (member "done" status)) (nrepl-dict-put response "status" (remove "need-input" status)) (accept-process-output nil 0.01) (redisplay)) `org-babel-execute:clojure' is still somewhat synchronous, isn't it? Regards, -- Nicolas Goaziou
Re: [O] [PATCH] new :async feature for org-babel-clojure
Hi Nicolas, Any news regarding these latest fixes to that patch? Thanks, Fred Here is my proposal to create a new :async feature for Org-babel-clojure. This is discussed at length in this blog post: http://fgiasson.com/blog/index.php/2016/04/05/using-clojure-in-org-mode-and-implementing-asynchronous-processing/ I added the commit of the changes, the commit for the ORG-NEWS file and the commit for the Worg documentation. IMPORTANT NOTE: this includes the patches for the new :async feature *AND* the new org-babel-clojure-sync-nrepl-timeout setting (for consistency's sake) Thanks, Fred
[O] [PATCH] new :async feature for org-babel-clojure
Hi, Here is my proposal to create a new :async feature for Org-babel-clojure. This is discussed at length in this blog post: http://fgiasson.com/blog/index.php/2016/04/05/using-clojure-in-org-mode-and-implementing-asynchronous-processing/ I added the commit of the changes, the commit for the ORG-NEWS file and the commit for the Worg documentation. IMPORTANT NOTE: this includes the patches for the new :async feature *AND* the new org-babel-clojure-sync-nrepl-timeout setting (for consistency's sake) Thanks, Fred >From 2fe515d1fb89ba1ea160711d10f2f68fe0287246 Mon Sep 17 00:00:00 2001 From: Frederick Giasson Date: Wed, 6 Apr 2016 12:18:21 -0400 Subject: [PATCH 3/4] Adding information about the new org-babel-clojure :async feature. --- etc/ORG-NEWS | 9 + 1 file changed, 9 insertions(+) diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index e684587..fad0679 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -110,6 +110,15 @@ becomes This new option tells the =org-babel-clojure= module the length of the timeout of a synchronous call to the nREPL. This value is in seconds. If =nil= then no timeout will occur. +*** New code block option =:async= for =org-babel-clojure= +This new option gives the possibility to =org-babel-clojure= user to run +a block code asynchronously using a new code block parameter =:async=. +If =:async= is specified in the code block, then it will be processed +asynchronously by Org-mode. This means that everything that will be +output to the REPL by the code will appear in a new window when it will +be output. Once the processing is finalized, then the window will be closed +and the output will be added to the results section (if =:results output= is +specified). *** New org-protocol key=value syntax Org-protocol can now handle query-style parameters such as: -- 1.9.5.msysgit.0 >From e218aaef38f6dc0f9affa516aafa18b77c2a3a1e Mon Sep 17 00:00:00 2001 From: Frederick Giasson Date: Wed, 6 Apr 2016 12:19:11 -0400 Subject: [PATCH 4/4] Adding a new feature :async feature to org-babel-clojure. With this new feature, someone can evaluate Clojure code in Org-mode code blocks asynchronously. --- lisp/ob-clojure.el | 78 ++ 1 file changed, 61 insertions(+), 17 deletions(-) diff --git a/lisp/ob-clojure.el b/lisp/ob-clojure.el index 86f1cff..6059d7d 100644 --- a/lisp/ob-clojure.el +++ b/lisp/ob-clojure.el @@ -91,35 +91,79 @@ body))) (defun org-babel-execute:clojure (body params) - "Execute a block of Clojure code with Babel." + "Execute a block of Clojure code with Babel. The block can be executed + synchenously by default or asynchronously with the :async parameter" (let ((expanded (org-babel-expand-body:clojure body params)) + (sbuffer "*Clojure Sub Buffer*") + (async (if (assoc :async params) t nil)) + (response (cons 'dict nil)) + status result) (case org-babel-clojure-backend (cider (require 'cider) (let ((result-params (cdr (assoc :result-params params -(setq result - (nrepl-dict-get - (let ((nrepl-sync-request-timeout org-babel-clojure-sync-nrepl-timeout)) - (nrepl-sync-request:eval - expanded (cider-current-connection) (cider-current-session))) - (if (or (member "output" result-params) - (member "pp" result-params)) - "out" - "value") + ; Check if the user want to run code asynchronously + (when async + ; Create a new window with the async output buffer + (switch-to-buffer-other-window sbuffer) + + ; Run the Clojure code asynchronously in nREPL + (nrepl-request:eval +expanded +(lambda (resp) + (when (member "out" resp) +; Print the output of the nREPL in the asyn output buffer +(princ (nrepl-dict-get resp "out") (get-buffer sbuffer))) + (nrepl--merge response resp) + ; Update the status of the nREPL output session + (setq status (nrepl-dict-get response "status"))) +(cider-current-connection) +(cider-current-session)) + + ; Wait until the nREPL code finished to be processed + (while (not (member "done" status)) + (nrepl-dict-put response "status" (remove "need-input" status)) + (accept-process-output nil 0.01) + (redisplay)) + + ; Delete the async buffer & window when the processing is finalized + (let ((wins (get-buffer-window-list sbuffer nil t))) + (dolist (win wins) + (delete-window win)) + (kill-buffer sbuffer)) + + ; Put the output or the value in the result section of the code block + (setq result (nrepl-dict-get response +