If I have an Org-mode Clojure source block that I want to use like cider-scratch buffer, how do I make it always connect to an existing nrepl instance? i.e., there's an instance of a remote service (it's always there), after setting up port-forwarding, I can cider-connect to localhost:4009. Is it possible to create source blocks that easily connect to it without too much of ritual dancing around?
Doesn't it work out of the box? As I remember ob-clojure used the active cider session the last time I tried it.
Well, if you have no cider connections (first time you [re]start Emacs) - you have to manually connect.
Then, if you have multiple cider sessions, you have to do something like sesman-link-with-buffer, select the right session etc.
Can this be done in a simpler way? Maybe by setting up some headers?
Imagine having something like:
#+begin_src clojure :nrepl locahost:4009
and then trying to eval it or when you start editing the block in the indirect buffer it automatically tries to connect/link to that nrepl instance?
I see, I can't find anything like that in the code, the only thing that is tunable it's kind of hardcoded to
(let ((connection (cider-current-connection (cdr (assq :target params))))
the :target is clj/cljs/etcbut cider itself looks for the "most recent repl" like this
(let* ((type (or type (cider-repl-type-for-buffer)))
(repls (cider-repls type ensure))
(repl (if (<= (length repls) 1)
(car repls)
;; pick the most recent one
(seq-find (lambda (b)
(member b repls))
(buffer-list)))))
(if (and ensure (null repl))
(cider--no-repls-user-error type)
repl))
So a workaround might be something like "make my connection the recent one".It would be pretty easy to fix ob-clojure itself, but you need to get your FSF paper signed. Btw, I can ask org maintainer if it's possible to implement something like this.
For now, I'm thinking - since I mainly want to use it for editing the src blocks. I can advice org-edit-special (I forgot what Org-mode uses by default for C-c ' - I use org-edit-indirect.el.
I can advise whatever function, check for the headers, find existing/start new session and link the buffer to it so all evaling works as in cider-scratch buffer
C-c ' runs the command org-edit-special (found in org-mode-map), which
Alright. I think it's working:
(defun org-edit-special-for-clojure-a (ofn &optional arg)
"Advising function for editing clojure blocks that respect :nrepl-host header."
(let ((find-matching-session
(lambda (host port sessions)
(let ((rx (format ".*\\:%s\\:%s" host port)))
(seq-find (lambda (x)
(string-match-p rx (car x)))
sessions)))))
(if-let* ((el (org-element-at-point))
(src-p (eq 'src-block (org-element-type (org-element-context el))))
(clj-p (string= "clojure" (org-element-property :language el)))
(nrepl (alist-get
:nrepl-host
(nth 2 (org-babel-get-src-block-info))))
(_ (string-match "\\(.*\\):\\([0-9]+\\)" nrepl))
(host (match-string 1 nrepl))
(port (match-string 2 nrepl)))
(progn
(funcall ofn arg)
(if-let* ((ses (funcall find-matching-session
host port
(sesman-sessions (sesman--system)))))
(sesman-link-with-buffer nil ses)
(cider-connect-clj (list :host host
:port (string-to-number port)))))
(funcall ofn arg))))
(advice-add 'org-edit-special :around #'org-edit-special-for-clojure-a)☝️ If you have something like this:
#+begin_src clojure :nrepl-host localhost:4009
whenever you try to edit the block, it will try to cider-connect to that host. If there's already an active session - it links the indirect buffer to it.Darn. I just wanted to solve a problem of evaling things in the indirect buffer. I showed this to my teammates and now they want it to work for the evaluation as well, so they can have multiple source blocks that on 'C-c C-c' can pass data to each other, while evaling things in different nrepl sessions.
I guess that would be mind-blowingly cool to be able to get data from one service with nrepl-host, then pass it to a babashka piece, transform the data, then pass that to another block connected to another service, etc.