Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fireplace has problems with the Babashka nREPL #401

Open
robbieh opened this issue Apr 19, 2022 · 16 comments
Open

Fireplace has problems with the Babashka nREPL #401

robbieh opened this issue Apr 19, 2022 · 16 comments

Comments

@robbieh
Copy link

robbieh commented Apr 19, 2022

I can't get fireplace to work with the babashka nrepl.

> bb nrepl
Started nREPL server at 127.0.0.1:32851
For more info visit: https://book.babashka.org/#_nrepl

Fireplace seems to connect OK. I've tried using :Connect. And the nrepl confirms a connection is closed vim exits.

But trying to eval code fails:

Vim(return):E716: Key not present in Dictionary: "response, 'value', [])"
@tpope
Copy link
Owner

tpope commented Apr 19, 2022

Guessing from the error message it's this line:

return get(state.history.response, 'value', [])

You could try putting :echo json_encode(state) right above that line to see what's in that data structure.

@robbieh
Copy link
Author

robbieh commented Apr 19, 2022

Here's what happens:

Vim(echo):E474: Invalid argument

Here's what I did, and wanted to show it just in case I misunderstood:

if get(state, 'ex', '') !=# ''
  let err = 'Clojure: '.state.ex
else
  echo json_encode(state)
  return get(state.history.response, 'value', [])
endif

@tpope
Copy link
Owner

tpope commented Apr 19, 2022

Oh it must have function keys, try :echo state instead.

@robbieh
Copy link
Author

robbieh commented Apr 19, 2022

Woooo! That did it! I hope you can make sense of this :)

{'echo': v:true, 'history': {'messages': [], 'tempfile': '/tmp/ve4jjOI/5.clj', 'ns': 'lochmess-bb-collector.main', 'code': '(ns lochmess-bb-collector.main
  (:require [babashka.fs :as fs]
            [clojure.java.io :as io]))', 'ext': 'clj', 'buffer': 1}, 'code': '(ns lochmess-bb-collector.main
  (:require [babashka.fs :as fs]
            [clojure.java.io :as io]))', 'client': {'ReplNs': function('<SNR>104_CljReplNs'), 'Client': function('129'), 'Eval': function('135'), 'Message': function('132', {'ReplNs': funct
ion('<SNR>104_CljReplNs'), 'Client': function('129'), 'UserNs': function('<SNR>104_CljUserNs'), 'Message': function('132', {...}), 'Query': function('<SNR>104_EvalQuery'), 'requires': {}, '
path': function('131', {...}), 'Done': function('133', {...}), 'preload': function('134'), 'HasOp': function('136'), 'BufferNs': function('<SNR>104_CljBufferNs'), 'eval': function('135', {.
..}), 'message': function('132'), 'user_ns': function('<SNR>104_CljUserNs', {...}), 'Eval': function('135'), 'Path': function('131'), 'done': function('133'), 'Ext': function('<SNR>104_CljE
xt'), 'Session': function('130'), 'Preload': function('134', {...})}), 'cljs_sessions': [], 'requires': {'lochmess-bb-collector.main': 0}, 'path': function('131', {'ReplNs': function('<SNR>
104_CljReplNs'), 'Client': function('129'), 'UserNs': function('<SNR>104_CljUserNs'), 'Message': function('132', {...}), 'Query': function('<SNR>104_EvalQuery'), 'requires': {}, 'path': fun
ction('131', {...}), 'Done': function('133', {...}), 'preload': function('134'), 'HasOp': function('136'), 'BufferNs': function('<SNR>104_CljBufferNs'), 'eval': function('135', {...}), 'mes
sage': function('132'), 'user_ns': function('<SNR>104_CljUserNs', {...}), 'Eval': function('135'), 'Path': function('131'), 'done': function('133'), 'Ext': function('<SNR>104_CljExt'), 'Ses
sion': function('130'), 'Preload': function('134', {...})}), 'Done': function('133', {'ReplNs': function('<SNR>104_CljReplNs'), 'Client': function('129'), 'UserNs': function('<SNR>104_CljUs
erNs'), 'Message': function('132', {...}), 'Query': function('<SNR>104_EvalQuery'), 'requires': {}, 'path': function('131', {...}), 'Done': function('133', {...}), 'preload': function('134'
), 'HasOp': function('136'), 'BufferNs': function('<SNR>104_CljBufferNs'), 'eval': function('135', {...}), 'message': function('132'), 'user_ns': function('<SNR>104_CljUserNs', {...}), 'Eva
l': function('135'), 'Path': function('131'), 'done': function('133'), 'Ext': function('<SNR>104_CljExt'), 'Session': function('130'), 'Preload': function('134', {...})}), 'session': {'Mess
age': function('<SNR>119_session_message'), 'close': function('<SNR>119_session_close'), 'id': '3d7bf619-269c-4768-afaf-fe23a5fce381', 'url': 'nrepl://localhost:37733/#3d7bf619-269c-4768-af
af-fe23a5fce381', 'path': function('<SNR>119_session_path'), 'session': '3d7bf619-269c-4768-afaf-fe23a5fce381', 'HasOp': function('<SNR>119_session_has_op'), 'has_op': function('<SNR>119_se
ssion_has_op'), 'transport': {'alive': function('<SNR>118_transport_alive'), '_path': [], 'job': 'process 403682 run', 'state': {'status': ''}, 'close': function('<SNR>118_transport_close')
, 'clone': function('<SNR>118_transport_clone'), 'url': 'nrepl://localhost:37733/', 'HasOp': function('<SNR>118_transport_has_op'), 'Alive': function('<SNR>118_transport_alive'), 'has_op':
function('<SNR>118_transport_has_op'), 'requests': {'d37a339f-68c4-4873-37f7-069ef088ba50': {'session': 'd0e506b2-7c48-4905-931c-2f6525986262', 'callbacks': [function('add', [[]])]}}, 'mess
age': function('<SNR>118_transport_message'), 'Close': function('<SNR>118_transport_close'), 'sessions': {'d0e506b2-7c48-4905-931c-2f6525986262': function('<SNR>119_session_callback', {'Mes
sage': function('<SNR>119_session_message'), 'close': function('<SNR>119_session_close'), 'id': 'd0e506b2-7c48-4905-931c-2f6525986262', 'url': 'nrepl://localhost:37733/#d0e506b2-7c48-4905-9
31c-2f6525986262', 'path': function('<SNR>119_session_path'), 'session': 'd0e506b2-7c48-4905-931c-2f6525986262', 'HasOp': function('<SNR>119_session_has_op'), 'has_op': function('<SNR>119_s
ession_has_op'), 'transport': {...}, 'clone': function('<SNR>119_session_clone'), 'message': function('<SNR>119_session_message'), 'Close': function('<SNR>119_session_close'), 'callbacks':
[function('<SNR>119_close_on_first_done', [{...}])], 'Clone': function('<SNR>119_session_clone'), 'Path': function('<SNR>119_session_path')}), '3d7bf619-269c-4768-afaf-fe23a5fce381': functi
on('<SNR>119_session_callback', {...})}, 'Clone': function('<SNR>118_transport_clone'), 'Message': function('<SNR>118_transport_message'), 'describe': {'status': ['done'], 'id': '4427c282-a
966-4a70-e26f-67f39a72bf24', 'session': ['none'], 'ops': {'info': {}, 'clone': {}, 'ls-sessions': {}, 'eldoc': {}, 'complete': {}, 'eval': {}, 'load-file': {}, 'close': {}, 'lookup': {}, 'd
escribe': {}}, 'versions': {'babashka.nrepl': '0.0.6-SNAPSHOT', 'babashka': '0.8.1'}}}, 'clone': function('<SNR>119_session_clone'), 'message': function('<SNR>119_session_message'), 'Close'
: function('<SNR>119_session_close'), 'callbacks': [], 'Clone': function('<SNR>119_session_clone'), 'Path': function('<SNR>119_session_path')}, 'preload': function('134'), 'HasOp': function
('136'), 'transport': {...}, 'BufferNs': function('<SNR>104_CljBufferNs'), 'eval': function('135', {'ReplNs': function('<SNR>104_CljReplNs'), 'Client': function('129'), 'UserNs': function('
<SNR>104_CljUserNs'), 'Message': function('132', {...}), 'Query': function('<SNR>104_EvalQuery'), 'requires': {}, 'path': function('131', {...}), 'Done': function('133', {...}), 'preload':
function('134'), 'HasOp': function('136'), 'BufferNs': function('<SNR>104_CljBufferNs'), 'eval': function('135', {...}), 'message': function('132'), 'user_ns': function('<SNR>104_CljUserNs'
, {...}), 'Eval': function('135'), 'Path': function('131'), 'done': function('133'), 'Ext': function('<SNR>104_CljExt'), 'Session': function('130'), 'Preload': function('134', {...})}), 'me
ssage': function('132'), 'user_ns': function('<SNR>104_CljUserNs', {'ReplNs': function('<SNR>104_CljReplNs'), 'Client': function('129'), 'UserNs': function('<SNR>104_CljUserNs'), 'Message':
 function('132', {...}), 'Query': function('<SNR>104_EvalQuery'), 'requires': {}, 'path': function('131', {...}), 'Done': function('133', {...}), 'preload': function('134'), 'HasOp': functi
on('136'), 'BufferNs': function('<SNR>104_CljBufferNs'), 'eval': function('135', {...}), 'message': function('132'), 'user_ns': function('<SNR>104_CljUserNs', {...}), 'Eval': function('135'
), 'Path': function('131'), 'done': function('133'), 'Ext': function('<SNR>104_CljExt'), 'Session': function('130'), 'Preload': function('134', {...})}), 'Query': function('<SNR>104_EvalQue
ry'), 'UserNs': function('<SNR>104_CljUserNs'), 'Path': function('131'), 'done': function('133'), 'Ext': function('<SNR>104_CljExt'), 'Session': function('130'), 'Preload': function('134',
{'ReplNs': function('<SNR>104_CljReplNs'), 'Client': function('129'), 'UserNs': function('<SNR>104_CljUserNs'), 'Message': function('132', {...}), 'Query': function('<SNR>104_EvalQuery'), '
requires': {}, 'path': function('131', {...}), 'Done': function('133', {...}), 'preload': function('134'), 'HasOp': function('136'), 'BufferNs': function('<SNR>104_CljBufferNs'), 'eval': fu
nction('135', {...}), 'message': function('132'), 'user_ns': function('<SNR>104_CljUserNs', {...}), 'Eval': function('135'), 'Path': function('131'), 'done': function('133'), 'Ext': functio
n('<SNR>104_CljExt'), 'Session': function('130'), 'Preload': function('134', {...})})}}

@tpope
Copy link
Owner

tpope commented Apr 19, 2022

The important part is up front:

'history': {'messages': []

It's giving up waiting on a response before receiving a single message. I'm not sure why this would happen. Perhaps it could be a consequence of the connection terminating unexpectedly. You can check for that by looking for a running python child process before and after the eval. No python process, no connection.

@robbieh
Copy link
Author

robbieh commented Apr 19, 2022

I see the python process both before and after the error, retaining the same PID. I'm fairly sure I have the right one because I see the nrepl port on the command line.

And just FYI I did a bundle update yesterday just to be sure I was up to date.

@tpope
Copy link
Owner

tpope commented Apr 19, 2022

Absent a better idea:

  • Make sure it works with another toolchain, like lein.
  • Try both Neovim and Vim. This will help rule out any bugs in the low level code.

@tpope
Copy link
Owner

tpope commented Apr 19, 2022

One other thing you could try is delete the catch at

and see if any errors bubble up.

@robbieh
Copy link
Author

robbieh commented Apr 19, 2022

My setup has been working with lein and clj.

I tried removing the catch, but it didn't show anything new.

I'll try neovim next, but will need to learn how to set it up first.

"Jan K" from the Clojurians slack has the same problem, but noted that adding #!/usr/bin/env bb to the top of the file makes things partially work. cpp is ok but cpr fails.

@tpope
Copy link
Owner

tpope commented Apr 19, 2022

I don't know much about babashka. It wouldn't surprise me if some high level functionality like cpr didn't work right. But this particular error is strange. This while loop is exiting before any messages have been received. You could maybe add a sleep 5 after it and see if the messages eventually show up.

@elzibubble
Copy link

I had this issue, but it's disappeared! My steps as best I can remember them:

  • Opened vim to edit a bb .clj file
  • I started a shell with vim-dispatch (:Shell)
  • Ran bb --nrepl-server
  • :FireplaceConnect 1667
  • Try to eval something, oh it's not working... google...
  • Remove the try/catch, re: Fireplace has problems with the Babashka nREPL #401 (comment)
  • Closed vim entirely, ran bb --brepl-server &
  • Relaunched vim
  • :FireplaceConnect 1667
  • Hey it works now!

After that my memory gets blurry but I tried putting the try/catch back - still works. Tried :Start bb --nrepl-server, still worked. Also tried original :Start shell and run nrepl, also works. Very confused but pleased I guess ^^

@rafd
Copy link
Contributor

rafd commented Dec 6, 2022

Ran into this today, some notes from my explorations:

Some of the previous suggestions in this thread may have "worked" because they were inadvertently evaluating in the user namespace.

When running :Require , fireplace figures out the current namespace by parsing the beginning of the file or defaults to user. Fireplace's logic here could be changed to skip lines that start with #, improving compatibility with babashka.

It may not seem like :Require is failing, because Fireplace will default to user if it can't find the namespace declaration (ex. because it's not there, or because there's a #!/usr/bin/env bb at the top of the file).

Evaluating (identity *ns*) can be useful to debug what namespace the REPL thinks it is currently in.

Informal babashka scripts often skip many Clojure formalities (ex. namespace declarations, namespace-file locations), breaking :Require, because :Require calls clojure.core/require (which assumes that namespaces are in certain files).

For informal babashka scripts, instead of :Require, you can eval the entire namespace in Fireplace with :%Eval.

For more formal babashka scripts (as recommended by Babashka docs):

  • remove #!/usr/bin/env bb at the top of the file
  • add :paths ["src"] to bb.edn (note: appending --classpath "src" is different)
  • put namespace files in the appropriate places (ex. foo in src/foo.clj)
  • use namespace declarations (ie. (ns foo (:require ....)))
  • run repl with bb --nrepl-server and use :Connect 1667 or :Fireplace 1667 to connect

@tpope
Copy link
Owner

tpope commented Dec 8, 2022

This all tracks. Skipping # lines is a bit too broad, but skipping #! would certainly be reasonable. A simple tweak to the blank regexp would work.

@marrs
Copy link

marrs commented Apr 6, 2024

I appear to be having the same issue with Babashka.

I have 2 namespaces that I'm working with. We'll call them a.core and a-core-test, living in src/a/core.clj and test/a/core_test.clj respectively.

The behaviour of this seems to vary, but for the moment I can reproduce the following.
These are the results of running cpp on the following expressions:

(+ 1 2); => 3
(ns a.core); => nil
(defn a.core/foo [bar] ...) => #'a.core/foo
; Moving to a.core-test
(ns a.core-test); => Vim(return):E716: Key not present in Dictionary: "response"
(a.core/foo :bar) => Vim(return):E716: Key not present in Dictionary: "response"

Previously, evaluation of the expressions in src/a/core.clj were also failing with E716, but I cannot reproduce that behaviour now.

It doesn't matter what order I load the files in, the namespace in test never evaluates but the namespace in src does, so I wonder if this is to do with how bb.edn is configured.

my bb.edn is as follows:

{:paths ["src" "test"]
 :tasks
 {test (shell "bb --main a.core-test")}}

Running bb test works as expected, indicating that the namespaces are being found and evaluated without issue.

I'm connected to the nrepl server run by Babashka using the command bb --nrepl-server.

It may be worth looping Borkdude into this conversation.

Further info:

Evaluating (prn *ns*) in the src file prints the namespace of that file
Evaluating (prn *ns*) in the test file returns the E716 error.

@marrs
Copy link

marrs commented Apr 6, 2024

I can confirm that this is definitely a Babashka issue. Running an nrepl through clj works just fine.

@rafd
Copy link
Contributor

rafd commented Apr 9, 2024

@marrs can you publish a minimal repo that reproduces the issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants