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?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
Let me see.
i see. that’s used and never defined
Yep.
-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) I think I'll just need to get the stable version.
well short term you can (defvar inf-clojure-custom-repl-name nil)
and it will work
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
I'll do it.
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.
that’s frustrating
and if you also defvar that?
OK that gets me to inf-clojure--prompt-repl-type prompt (previously it failed after host/`port`).
But ... I don't even expect this prompt.
Like the REPL is running, isn't that the point of connect?
have you told inf-clojure what type of repl you are using in some other way?
the doc and source commands (and all of the others) depend on whether its a clojure, cljs, bb, planck, etc. repl
I see, clearly I don't understand the prompt. Let me go with clojure and see...
What is the text of the prompt?
OK so the REPL is running.
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?
inf-clojure does not try to hide stuff from you. It’s meant to be a way to interact with a repl
it doesn’t automatically set the ns when you evaluate
OK, perfect, I'll do some learning on that. Just wanted to check it's behaving how it should.
I believe it was added in https://github.com/clojure-emacs/inf-clojure/pull/210/files
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.I was against this feature for exactly this reason
i think you should just start your repl in a terminal with all of your usual options
Fair enough.
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
and there’s so much documentation around the CLI that i think we should just use that
especially if your startup is so nice:
clj -X:repl-server :port 5000 and then inf-clojure-connect
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
but i think you can use inf-clojure-custom-startup
That's fine. For now I just want to learn how it works. I like Cider, but...no socket REPL, that's the thing.
yeah. i’m a huge socket repl fan.
Exactly 🙂 I'm not yet totally in the know, but I see the reasons and want to learn more!
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
That's pretty cool.
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
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.are you using inf-clojure-socket-repl ?
M-x inf-clojure
inf-clojure-socket-repl is also unaffected by the vars.
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 typeThat's bloody weird!
@dpsutton I evaluated these forms and it didn't work either.
i’m doing some changes locally to make it work. i’m gonna send up a branch soon
(I mean the forms you just sent.)
Thanks, I'd be very grateful.
Thanks @dpsutton! Let me try that now.
There are failing tests, but you've probably seen that.
yeah. those tests have been failing for a while. probably should be removed
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.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
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).Debugger entered--Lisp error: (wrong-type-argument stringp bob)
message(bob)you can’t (message 'bob) . message must take a string
Ah fair enough.
(Totally not used to Elisp.)
(message (symbol-name 'bob))
(no worries. it’s a weird language 🙂 )
I miss prn.
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.
... and I'm still getting that interactive prompt.
not sure i follow
(message "clojure -X:repl-server :port %d")
Makes it fail
Because it expects argument for %d.
(I just wanted to verify it had the right value.)
does startup work?
No.
inf-clojure is gonna call (format cmd port)
to check you can just do
(message (format "clojure -X:repl-server :port %d" 5000))
and use a dummy port
OK checked, the values are 100% right.
Yet it isn't working.
can you tell what the alias repl-server is defined as?
Same interactive prompt on both of inf-clojure and inf-clojure-socket-repl.
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}}}does everything work if you do
clj -X:repl-server :port 4567
and then inf-clojure-connect to localhost and 4567?just start it in a terminal and then connect to it
I can run it like that, yes, it starts on the right port.
And I can rlwrap nc localhost 4567 and it starts and responds.
and what about inf-clojure-connect localhost 4567 or whatever port?
Also responds. It did ask me REPL type, which it shouldn't, since I set the variable, but the REPL itself works, yes.
ok. that’s good to know
is playground.repl public? I’d like to try with your exact setup
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.
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}}}}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.
ok works for me from a terminal. let me try starting it
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
OMG 😆
But are you sure? To me there's no indication it ever tries to start a process.
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
It goes to display the prompt straight away, there's no lag like if it'd be waiting.
no prompt at all:
I see.
Yes.
compare to
It didn't occur to me it'd be necessary haha.
me either.
kinda why i don’t like this stuff
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)
)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
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 readyOK thanks a lot Dan, I really appreciate your help 🙏🏼
my pleasure. Are you up and running now?
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.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
weird it is working for me
I assume you start with inf-clojure-socket-repl, correct?
yup. i get asked zero questions and after a second the repl buffer pops up
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.
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-replare you sure you have my branch?
can you look at inf-clojure.el?
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))Right, that's the new code.
can you open that inf-clojure.el file and tell me what is on line 962?
(created-repl-buffer (inf-clojure-connect host port :suppress-message)))
ok. that’s what i have. I wonder what could be different between our setups
Yeah me too. It looks like a very straightforward thing.
What is the value of inf-clojure-custom-startup you are using?
"clojure -J-Dclojure.server.repl=\"{:port %d :accept clojure.core.server/repl}\" -A:grepl"
OK...so I find something out:
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.)
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.
If I open the actual tangled CLJ source file, it works there.
In the Orgmode narrow buffer, it doesn't.
what doesn’t work?
* 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 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.
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.
no idea. ¯\(ツ)/¯
No don't worry about it, I'll have a look.
Just filling you in.
yeah. step through the code. You’ll need to debug it to see where it goes off the rails
maybe determining the project root
Project root could be a culprit
OK, at least I'll learn some Emacs debugging.
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.