inf-clojure

2023-04-07T16:12:56.778649Z

Hey guys. I just installed inf-clojure and when I do inf-clojure-connect and point it to my local REPL at localhost / 5555, I get this:

Symbol's value as variable is void: inf-clojure-custom-repl-name
What's going on?

dpsutton 2023-04-07T16:30:12.701589Z

that’s annoying. Can you debug it and see what’s going on? You can m-x toggle-debug-on-error and debug or get a stacktrace and see. I’ve got to stash some local changes but i’ll pull it down and see what’s up

2023-04-07T16:30:42.023559Z

Let me see.

dpsutton 2023-04-07T16:31:33.711849Z

i see. that’s used and never defined

2023-04-07T16:32:11.760059Z

Yep.

2023-04-07T16:32:20.478789Z

-UUU:----F1  *Org Src  clojure ]*   All L4    <N>   (Clojure inf-cloj
  1 Debugger entered--Lisp error: (void-variable inf-clojure-$
  2   (or inf-clojure-custom-repl-name (if project-dir (forma$
  3   (let* ((project-dir (clojure-project-dir)) (process-buf$
  4   inf-clojure(("localhost" . 5555))
  5   inf-clojure-connect("localhost" 5555)
  6   funcall-interactively(inf-clojure-connect "localhost" 5$
  7   call-interactively(inf-clojure-connect record nil)
  8   command-execute(inf-clojure-connect record)
  9   execute-extended-command(nil "inf-clojure-connect" "inf$
 10   funcall-interactively(execute-extended-command nil "inf$
 11   call-interactively(execute-extended-command nil nil)
 12   command-execute(execute-extended-command)

2023-04-07T16:32:37.098149Z

I think I'll just need to get the stable version.

dpsutton 2023-04-07T16:32:39.819339Z

well short term you can (defvar inf-clojure-custom-repl-name nil)

dpsutton 2023-04-07T16:32:42.641629Z

and it will work

dpsutton 2023-04-07T16:33:02.818999Z

but we should raise an issue. someone recently committed some socket repl help and there were some changes so i guess this got left in

2023-04-07T16:33:14.212379Z

I'll do it.

💪 1
2023-04-07T16:35:40.697539Z

Anyway that defvar doesn't do it totally, there are more issues: let: Symbol's value as variable is void: inf-clojure-socket-repl-type I'll just report it as a bug and will use stable version.

dpsutton 2023-04-07T16:35:59.238899Z

that’s frustrating

dpsutton 2023-04-07T16:38:19.301989Z

and if you also defvar that?

2023-04-07T16:40:16.335059Z

OK that gets me to inf-clojure--prompt-repl-type prompt (previously it failed after host/`port`).

2023-04-07T16:40:29.639229Z

But ... I don't even expect this prompt.

2023-04-07T16:40:40.665139Z

Like the REPL is running, isn't that the point of connect?

dpsutton 2023-04-07T16:40:50.996789Z

have you told inf-clojure what type of repl you are using in some other way?

dpsutton 2023-04-07T16:41:17.763749Z

the doc and source commands (and all of the others) depend on whether its a clojure, cljs, bb, planck, etc. repl

2023-04-07T16:41:27.154779Z

I see, clearly I don't understand the prompt. Let me go with clojure and see...

dpsutton 2023-04-07T16:41:42.566109Z

What is the text of the prompt?

2023-04-07T16:43:32.042449Z

OK so the REPL is running.

2023-04-07T16:44:20.540459Z

I can do C-x C-e to eval. Strangely it doesn't show the result in the current buffer, I have to switch to the REPL buffer manually. Am I too spoilt?

dpsutton 2023-04-07T16:44:46.276149Z

inf-clojure does not try to hide stuff from you. It’s meant to be a way to interact with a repl

dpsutton 2023-04-07T16:44:57.261589Z

it doesn’t automatically set the ns when you evaluate

2023-04-07T16:45:29.608769Z

OK, perfect, I'll do some learning on that. Just wanted to check it's behaving how it should.

👍 1
2023-04-07T16:14:54.546099Z

I believe it was added in https://github.com/clojure-emacs/inf-clojure/pull/210/files

2023-04-07T16:55:40.254639Z

The other thing, if I want to connect from within Emacs to my custom REPL, I see there's inf-clojure-socket-repl which makes me do that...except it doesn't allow me to connect to a custom REPL (`clojure -X:repl-server` from my deps.edn). Thank God for Emacs patching, I just added it to inf-clojure-socket-repl-startup-forms:

(defvar inf-clojure-socket-repl-startup-forms
  '((custom-repl-server . "clojure -X:repl-server :port %d")
    ...other opts)
But that's clearly not a long-term solution. Is there a way to do this? All I want is that inf-clojure-socket-repl offers me clojure -X:repl-server.

dpsutton 2023-04-07T16:56:27.047409Z

I was against this feature for exactly this reason

dpsutton 2023-04-07T16:56:42.593469Z

i think you should just start your repl in a terminal with all of your usual options

2023-04-07T16:56:58.612719Z

Fair enough.

dpsutton 2023-04-07T16:57:08.088929Z

trying to figure out how to pass this information to inf-clojure so it knows how to pass this information to the CLI is such a pain

dpsutton 2023-04-07T16:57:20.718359Z

and there’s so much documentation around the CLI that i think we should just use that

dpsutton 2023-04-07T16:57:52.925869Z

especially if your startup is so nice: clj -X:repl-server :port 5000 and then inf-clojure-connect

dpsutton 2023-04-07T17:03:21.953239Z

I don’t mean to be overly negative. Making inf-clojure work for everyone is great. I just see lots of downsides that you are immediately running into and no great general solutions

dpsutton 2023-04-07T17:04:40.501419Z

but i think you can use inf-clojure-custom-startup

👍 1
2023-04-07T17:04:47.097939Z

That's fine. For now I just want to learn how it works. I like Cider, but...no socket REPL, that's the thing.

dpsutton 2023-04-07T17:05:10.526109Z

yeah. i’m a huge socket repl fan.

2023-04-07T17:05:54.223549Z

Exactly 🙂 I'm not yet totally in the know, but I see the reasons and want to learn more!

dpsutton 2023-04-07T17:06:36.896989Z

i love it because i can easily connect to a jar running in CI over ssh, a prod jar locally, or my local dev setup. And my tooling remains the same across all instances

2023-04-07T17:07:43.869039Z

That's pretty cool.

dpsutton 2023-04-07T17:08:56.864859Z

java -D<socket-repl-stuff> -jar my-project.jar clj -J-D<socket-repl-stuff> -A|-X|-M … use ssh to port forward and then connect to a jar running elsewhere, etc

2023-04-07T17:36:25.044889Z

Does the inf-clojure-custom-startup actually work?

34 #+begin_src emacs-lisp :tangle .dir-locals.el
 35   ((nil
 36     ;; (inf-clojure-custom-startup . "clojure -X:repl-server")
 37     (inf-clojure-custom-startup . ("localhost" . 5555))
 38     (inf-clojure-custom-repl-type . clojure)))
 39 #+end_src
I have this, load the vars, confirm them being safe, do inf-clojure and it'd still ask me what do I want to connect to. Neither of these two forms "clojure -X:repl-server" or ("localhost" . 5555) seem to work.

dpsutton 2023-04-07T17:41:47.121009Z

are you using inf-clojure-socket-repl ?

2023-04-07T17:42:53.026249Z

M-x inf-clojure

2023-04-07T17:43:24.448889Z

inf-clojure-socket-repl is also unaffected by the vars.

dpsutton 2023-04-07T17:50:42.504789Z

i can do

(setq inf-clojure-custom-startup "clojure -J-Dclojure.server.repl=\"{:port %d :accept clojure.core.server/repl}\" -A:grepl")
(setq inf-clojure-custom-repl-type 'clojure)
and then m-x inf-clojure-socket-repl and it starts up with my custom startup and sets the type

2023-04-07T17:54:08.653189Z

That's bloody weird!

2023-04-07T17:54:26.490979Z

@dpsutton I evaluated these forms and it didn't work either.

dpsutton 2023-04-07T17:54:33.929199Z

i’m doing some changes locally to make it work. i’m gonna send up a branch soon

🙏 1
2023-04-07T17:54:37.143529Z

(I mean the forms you just sent.)

2023-04-07T17:54:58.240089Z

Thanks, I'd be very grateful.

dpsutton 2023-04-07T20:11:26.802419Z

https://github.com/clojure-emacs/inf-clojure/pull/212

2023-04-07T21:23:46.445619Z

Thanks @dpsutton! Let me try that now.

2023-04-07T21:24:00.422209Z

There are failing tests, but you've probably seen that.

dpsutton 2023-04-07T21:24:28.005859Z

yeah. those tests have been failing for a while. probably should be removed

2023-04-07T21:43:03.704139Z

I don't know what's going on. So I have the code from your PR. Verified by ag inf-clojure-custom-repl-name $(find ~/.emacs.d -name inf-clojure.el) -A2, it shows the code from the PR. Quit Emacs. Start Emacs. Nothing interesting in *Messages*. Let's try if my vars are being read:

(message inf-clojure-custom-startup)
; "clojure -X:repl-server"

(message inf-clojure-custom-repl-type)
; "clojure"
All looks good to me. But then I do inf-clojure-socket-repl and I get the interactive prompt Select Clojure socket REPL startup command again.

dpsutton 2023-04-07T21:44:27.576729Z

two things. The custom startup needs to have a "%d" in it for where emacs gives it the port. It needs to assign the port to the startup so it knows what to connect to. And then the custom repl type should be 'clojure a symbol not a string

2023-04-07T21:45:07.593799Z

If I have 'clojure I get this:

Debugger entered--Lisp error: (wrong-type-argument stringp clojure)
When I try to do (message inf-clojure-custom-repl-type).

dpsutton 2023-04-07T21:45:38.732859Z

Debugger entered--Lisp error: (wrong-type-argument stringp bob)
  message(bob)

dpsutton 2023-04-07T21:45:49.438009Z

you can’t (message 'bob) . message must take a string

2023-04-07T21:46:00.396659Z

Ah fair enough.

2023-04-07T21:46:16.229129Z

(Totally not used to Elisp.)

dpsutton 2023-04-07T21:46:25.426419Z

(message (symbol-name 'bob))

dpsutton 2023-04-07T21:46:32.006549Z

(no worries. it’s a weird language 🙂 )

2023-04-07T21:47:33.404959Z

I miss prn.

2023-04-07T21:49:15.915749Z

Now I can't print the command since it has "%d" in it and it expects an arg. But anyway I think I have the right value now.

2023-04-07T21:49:29.593699Z

... and I'm still getting that interactive prompt.

dpsutton 2023-04-07T21:49:32.332109Z

not sure i follow

2023-04-07T21:50:17.562549Z

(message "clojure -X:repl-server :port %d")

2023-04-07T21:50:20.994999Z

Makes it fail

2023-04-07T21:50:31.077359Z

Because it expects argument for %d.

2023-04-07T21:50:58.413009Z

(I just wanted to verify it had the right value.)

dpsutton 2023-04-07T21:51:06.301909Z

does startup work?

2023-04-07T21:51:14.463409Z

No.

dpsutton 2023-04-07T21:51:38.421859Z

inf-clojure is gonna call (format cmd port) to check you can just do (message (format "clojure -X:repl-server :port %d" 5000))

dpsutton 2023-04-07T21:51:42.472209Z

and use a dummy port

2023-04-07T21:52:51.998489Z

OK checked, the values are 100% right.

2023-04-07T21:52:57.642189Z

Yet it isn't working.

dpsutton 2023-04-07T21:53:25.087619Z

can you tell what the alias repl-server is defined as?

2023-04-07T21:54:06.568409Z

Same interactive prompt on both of inf-clojure and inf-clojure-socket-repl.

2023-04-07T21:54:12.910899Z

8    {:repl-server
  9     {:exec-fn playground.repl/start-server
 10      :exec-args {:name "repl-server"
 11                  :port 5555
 12                  :accept playground.repl/repl
 13                  :server-daemon false}}}

dpsutton 2023-04-07T21:55:12.004209Z

does everything work if you do

clj -X:repl-server :port 4567
and then inf-clojure-connect to localhost and 4567?

dpsutton 2023-04-07T21:55:28.344809Z

just start it in a terminal and then connect to it

2023-04-07T21:56:15.405709Z

I can run it like that, yes, it starts on the right port.

2023-04-07T21:56:24.868909Z

And I can rlwrap nc localhost 4567 and it starts and responds.

dpsutton 2023-04-07T21:56:40.696189Z

and what about inf-clojure-connect localhost 4567 or whatever port?

2023-04-07T21:57:43.336539Z

Also responds. It did ask me REPL type, which it shouldn't, since I set the variable, but the REPL itself works, yes.

dpsutton 2023-04-07T21:57:58.553769Z

ok. that’s good to know

dpsutton 2023-04-07T21:58:22.966849Z

is playground.repl public? I’d like to try with your exact setup

2023-04-07T21:59:12.849459Z

Happy to make it public, but I don't think there's anything interesting, because Emacs never even tries to start the command. The issue is before that.

2023-04-07T22:00:17.497789Z

File src/playground/repl.clj

(ns playground.repl
  (:require [clojure.core.server :as s]))

(defn repl []
  (clojure.main/repl
    :init s/repl-init
    :read s/repl-read
    :print prn))

(defn start-server [{:keys [port] :as opts}]
  (println (str "~ Starting socket REPL on port " port "."))
  (println (str "  Connect: rlwrap nc localhost " port))
  (s/start-server opts))
And deps.edn
{:paths ["src"]
 :aliases
 {:repl-server
  {:exec-fn playground.repl/start-server
   :exec-args {:name "repl-server"
               :port 5555
               :accept playground.repl/repl
               :server-daemon false}}}}

2023-04-07T22:02:23.124269Z

Really the wrapper doesn't do anything yet. It's my starting point for exploring socket REPLs that I want to play with once I get this working.

dpsutton 2023-04-07T22:03:29.771019Z

ok works for me from a terminal. let me try starting it

dpsutton 2023-04-07T22:04:46.871459Z

ah i know why. this feature expects to see a repl prompt to know when the repl is ready. and you never print a repl prompt

2023-04-07T22:05:53.879189Z

OMG 😆

2023-04-07T22:06:14.761719Z

But are you sure? To me there's no indication it ever tries to start a process.

dpsutton 2023-04-07T22:06:55.175309Z

yes i’m sure. It has a process filter that waits for startup to complete so it knows the repl is ready. it could be delayed due to downloading dependencies, etc so it needs to know the repl is up and running

2023-04-07T22:06:56.921919Z

It goes to display the prompt straight away, there's no lag like if it'd be waiting.

dpsutton 2023-04-07T22:07:11.036399Z

no prompt at all:

2023-04-07T22:07:14.309659Z

I see.

2023-04-07T22:07:18.149179Z

Yes.

dpsutton 2023-04-07T22:07:28.721609Z

compare to

2023-04-07T22:07:30.606479Z

It didn't occur to me it'd be necessary haha.

dpsutton 2023-04-07T22:07:35.701919Z

me either.

dpsutton 2023-04-07T22:07:40.048179Z

kinda why i don’t like this stuff

dpsutton 2023-04-07T22:10:46.224529Z

change it to this:

(defn start-server [{:keys [port] :as opts}]
  (println (str "~ Starting socket REPL on port " port "."))
  (println (str "  Connect: rlwrap nc localhost " port))
  (future (s/start-server opts))
  (repl)
  )

dpsutton 2023-04-07T22:11:27.859779Z

start-server is a loop looking for connections so the repl never prints as the start-server function never “finishes”. So give it its own thread and then start up a repl

dpsutton 2023-04-07T22:13:05.246189Z

note, it is waaaaaaay easier to let Clojure do this for you. Which is what that default connection string is doing:

"clojure -J-Dclojure.server.repl=\"{:port %d :accept clojure.core.server/repl}\""
that is gonna just start up the normal clojure program (which defaults to a repl, and also starts the server on its own thread listening for socket connections. What you are doing is saying “I’m the main entry point. and you should open up a socket and listen for connections” so it never starts the repl, and therefore emacs never knows it is ready

2023-04-07T22:14:57.431329Z

OK thanks a lot Dan, I really appreciate your help 🙏🏼

dpsutton 2023-04-07T22:15:13.902959Z

my pleasure. Are you up and running now?

2023-04-07T22:16:47.905919Z

It shows the right thing:

~ Starting socket REPL on port 4567.
  Connect: rlwrap nc localhost 4567
user=>
But inf-clojure-socket-repl still doesn't respond to that. I want to try with the default clojure command you pasted first and see.

dpsutton 2023-04-07T22:18:03.033899Z

and this is why that system property way to start a socket repl is so nice: -J-Dclojure.server.repl you can have other entry points. Want reveal to startup and give you that nice interaction? clj -J-D… -M reveal. Have a -X startup? You can start the socket repl and have the entry point you want

dpsutton 2023-04-07T22:18:07.467189Z

dpsutton 2023-04-07T22:18:07.872169Z

weird it is working for me

2023-04-07T22:20:17.574159Z

I assume you start with inf-clojure-socket-repl, correct?

dpsutton 2023-04-07T22:20:38.199709Z

yup. i get asked zero questions and after a second the repl buffer pops up

2023-04-07T22:21:52.745229Z

OK so something else must be going on still. Even with (inf-clojure-custom-startup . "clojure -J-Dclojure.server.repl=\"{:port %d :accept clojure.core.server/repl}\" -A:grepl") property it still doesn't work.

dpsutton 2023-04-07T22:23:11.686749Z

i just restarted emacs, evaled

(setq inf-clojure-custom-startup "clojure -X:repl-server :port %d")
(setq inf-clojure-custom-repl-type 'clojure)
and then inf-clojure-socket-repl

dpsutton 2023-04-07T22:23:16.150999Z

are you sure you have my branch?

dpsutton 2023-04-07T22:23:24.410959Z

can you look at inf-clojure.el?

2023-04-07T22:23:40.784549Z

ag inf-clojure-custom-repl-name $(find ~/.emacs.d -name inf-clojure.el) -A2
521:(defvar inf-clojure-custom-repl-name nil
522-  "A string to be used as the repl buffer name.")
523-
--
831:                               inf-clojure-custom-repl-name
832-                               (if project-dir
833-                                   (format "inf-clojure %s" (inf-clojure--project-name project-dir))

2023-04-07T22:23:49.395629Z

Right, that's the new code.

dpsutton 2023-04-07T22:24:25.980709Z

can you open that inf-clojure.el file and tell me what is on line 962?

2023-04-07T22:25:33.021359Z

(created-repl-buffer (inf-clojure-connect host port :suppress-message)))

dpsutton 2023-04-07T22:26:09.199809Z

ok. that’s what i have. I wonder what could be different between our setups

2023-04-07T22:26:35.882579Z

Yeah me too. It looks like a very straightforward thing.

dpsutton 2023-04-07T22:27:15.937409Z

What is the value of inf-clojure-custom-startup you are using?

2023-04-07T22:27:45.430999Z

"clojure -J-Dclojure.server.repl=\"{:port %d :accept clojure.core.server/repl}\" -A:grepl"

2023-04-07T22:28:28.293269Z

OK...so I find something out:

2023-04-07T22:29:39.685529Z

I use Org-mode for everything. Great for dumb people with loosy memory, I have code and notes together. (Also allows for grouping things logically and other things, which I really appreciate.)

2023-04-07T22:30:53.348709Z

I normally edit code in a Orgmode narrow (`C-C '`). That gives me all that's in the current source block as a new buffer. I edit it, run CLJ stuff there and then when I'm happy, I close it by C-c ' and it saves the update into the main buffer.

2023-04-07T22:31:14.560129Z

If I open the actual tangled CLJ source file, it works there.

2023-04-07T22:31:25.617299Z

In the Orgmode narrow buffer, it doesn't.

dpsutton 2023-04-07T22:31:43.347059Z

what doesn’t work?

2023-04-07T22:32:27.169769Z

* Deps

Ref [[ and CLI guide: socket REPL]].

#+begin_src clojure :tangle deps.edn
  {:paths ["src"]
   :aliases
   {:repl-server
    {:exec-fn playground.repl/start-server
     :exec-args {:name "repl-server"
                 :port 5555
                 :accept playground.repl/repl
                 :server-daemon false}}}} ; How to run as a daemon?
#+end_src

Ref [[.

#+begin_src emacs-lisp
  (setq inf-clojure-custom-startup "clojure -X:repl-server :port %d")
  (setq inf-clojure-custom-repl-type 'clojure)

  (message (format inf-clojure-custom-startup 5000))
  (message (symbol-name inf-clojure-custom-repl-type))
#+end_src

Eval this, then ~inf-clojure-socket-repl~.



Ref [[.
#+begin_src emacs-lisp :tangle .dir-locals.el
  ((nil
    ;(inf-clojure-custom-startup . "clojure -X:repl-server :port %d")
    (inf-clojure-custom-startup . "clojure -J-Dclojure.server.repl=\"{:port %d :accept clojure.core.server/repl}\" -A:grepl")
    ;(inf-clojure-custom-startup . ("localhost" . 5555))
    (inf-clojure-custom-repl-type . clojure)

    ;; (inf-clojure-prompt-read-only t)
    ;; (inf-clojure-repl-use-same-window t)
    ))
#+end_src

#+begin_src clojure :tangle src/playground/repl.clj :mkdirp yes
  (ns playground.repl
    (:require [clojure.core.server :as s]))

  (defn repl []
    (clojure.main/repl
      :init s/repl-init
      :read s/repl-read
      :print prn))

  (defn start-server [{:keys [port] :as opts}]
    (println (str "~ Starting socket REPL on port " port "."))
    (println (str "  Connect: rlwrap nc localhost " port))
    (future (s/start-server opts))
    (repl))
#+end_src

** Usage
#+begin_src sh
  clojure -X:repl-server
  clojure -X:repl-server :port 51234
  rlwrap nc localhost 5555
#+end_src

#+begin_src clojure :tangle src/playground.clj :mkdirp yes
  (filter odd?)
  (range 10)
  (range)
#+end_src

2023-04-07T22:33:50.335059Z

1. If I go to the last code block that tangles into src/playground.clj, open it via C-c ' and try to connect to the REPL there using inf-clojure-socket-repl, no luck. 2. Same thing works fine if I open src/playground.clj manually as its own buffer.

2023-04-07T22:35:33.273959Z

So this is related to that setup. Normally other CLJ tools work in that narrow Orgmode buffer, including Clojure mode, Lispy and Cider as well.

dpsutton 2023-04-07T22:35:56.432609Z

no idea. ¯\(ツ)

2023-04-07T22:36:10.600589Z

No don't worry about it, I'll have a look.

2023-04-07T22:36:15.917349Z

Just filling you in.

dpsutton 2023-04-07T22:36:27.984799Z

yeah. step through the code. You’ll need to debug it to see where it goes off the rails

dpsutton 2023-04-07T22:36:34.260089Z

maybe determining the project root

2023-04-07T22:37:10.503029Z

Project root could be a culprit

2023-04-07T22:37:24.276309Z

OK, at least I'll learn some Emacs debugging.

2023-04-07T22:58:53.012079Z

The workaround is to first open a .clj file, inf-clojure-socket-repl, then close the source file and go back to the normal Org mode literary programming workflow. Will debug it at some point, but this works for now and I'm more interested in socket REPLs than in Emacs, so I'll leave it at that for the time being.