emacs

ag 2024-12-19T17:29:08.782949Z

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?

a13 2024-12-19T18:23:05.997309Z

Doesn't it work out of the box? As I remember ob-clojure used the active cider session the last time I tried it.

ag 2024-12-19T18:26:45.806059Z

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?

ag 2024-12-19T18:29:28.785609Z

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?

a13 2024-12-19T18:32:40.336179Z

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/etc

a13 2024-12-19T18:35:06.354599Z

but 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".

a13 2024-12-19T18:36:57.563349Z

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.

ag 2024-12-19T18:40:33.606849Z

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

a13 2024-12-19T18:42:23.198969Z

C-c ' runs the command org-edit-special (found in org-mode-map), which

ag 2024-12-19T20:50:14.595669Z

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)

👍 1
ag 2024-12-19T20:52:18.392789Z

☝️ 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.

ag 2024-12-20T17:08:55.333429Z

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.

ag 2024-12-20T17:15:57.286119Z

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.

👍 1