Closed lukaszkorecki closed 12 months ago
Yes, monroe-input-sender
is intended to be a one-way function to nrepl session, but monroe-send-eval-string
is a low-level call that will receive nrepl session reply through callback.
Can you try to print response
from this expression:
...
(lambda (response)
;;; print here
; (monroe-dbind-response response
monroe-dbind-reponse
will simply destructure decoded message map, like clojure let
does, so I'm not sure that could be the cause
Also, make sure to call comint-output-filter
if you want to display (parsed) response in monroe buffer.
Response looks correct:
response (dict (id . 10) (ns . collie.scratch) (session . ef80b251-4aaf-4756-8ff7-f8ee438ab1da) (value . "http://localhost:61089?4ccd48ba-82c0-46ba-9a2d-1fac9b9bc866"))
response (dict (id . 10) (session . ef80b251-4aaf-4756-8ff7-f8ee438ab1da) (status done))
I started digging more and learned how to catch exceptions 😉 and this is somewhat... unexpected, given this code:
(defun lk/monroe-eval-code-and-callback-with-value (code-str on-value)
(monroe-send-eval-string
code-str
(lambda (response)
(condition-case err
(monroe-dbind-response response
(id info value status)
(when (member "done" status)
(remhash id monroe-requests))
(when value
(message "value %s" value)
(funcall on-value value)))
(error (message "error %s" err))))))
(defun lk/monroe-portal-2 ()
(interactive)
(lk/monroe-eval-code-and-callback-with-value
"(r/portal-start!)"
(lambda (url)
(message "opening portal %s" url)
(xwidget-webkit-browse-url url))))
The messages and error I'm getting are:
value "http://localhost:61089?ef9677c6-5386-46d0-b57a-1dcb9b408fe2"
error (void-variable on-value)
So the value
is correctly extracted from the nREPL eval - but for whatever reason on-value
is somehow void? I tried making the lambda into a function via defun
and passing it as 'lk/open-url
and that didn't work either. Mysterious.
So I tried something like this, as a sanity check:
(defun lk/monroe-eval-code-and-callback-with-value-2 (code-str on-value)
(funcall on-value code-str))
(defun lk/monroe-portal-2 ()
(interactive)
(lk/monroe-eval-code-and-callback-with-value-2
"(r/portal-start!)" (lambda (in ) (message "in %s" in))))
and I'm getting expected result in *Messages*
buffer.
Sorry if this is not quite Monroe related, but it's very weird :-)
This almost works,
(defun lk/open-url (url)
(message "opening portal %s" url)
(xwidget-webkit-browse-url url))
(defun lk/monroe-eval-code-and-callback-with-value (code-str on-value)
(monroe-send-eval-string
code-str
(lambda (response)
(condition-case err
(monroe-dbind-response response
(id info value status)
(when (member "done" status)
(remhash id monroe-requests))
(when value
(message "value %s" value)
;; ignore callback and just open the URL using
;; the wrapper function
(lk/open-url value)))
(error (message "error %s" err))))))
but there are some issues with xwidgets opening Monroe's server url:
event though I see this in Messages:
opening portal "http://localhost:61089?2d9bf3e1-9079-494a-abf6-e63b728483ba"
So not quite sure what's going on 🙃
Do you use lexical binding by any chance? If you don't use it, that might be the reason why on-value
is void inside lambda.
To enable it, put this as the first line in your elisp file:
-*- lexical-binding: t; -*-
Thanks! I'll try that and see what's going on 👍
That was it! Emacs is weird sometimes, (or I'm just confused 😉) seems like when making changes I have to run M-x eval-buffer
rather than just eval-region
when editing my code, otherwise the lexical binding setting gets lost, at least that's how it looks like to me.
So the final code looks like this:
; - *- lexical-binding: t; -*-
;; ^^^^ at the top of the file
;; ....
(defun lk/monroe-eval-code-and-callback-with-value (code-str on-value)
(monroe-send-eval-string
code-str
(lambda (response)
(condition-case err
(monroe-dbind-response response
(value status id)
(when value
(funcall on-value value))
(when (member "done" status)
(remhash id monroe-requests)))
(error (message "Eval callback error %s" err))))))
No I just need to figure out why running Solved, I had to strip the double quote from the value returned in the callback, duh.(xwidget-webkit-browse-url value)
in the callback doesn't actually navigate the browser to the URL, but I think that's a webkit issue, nothing to do with Monroe.
Would you be interested in adding this function as part of Monroe's public API? I can think of other ways of using it to bridge the nREPL process with Emacs. For example, run tests, get location of broken ones and open a buffer formatted for grep-mode
to enable a quick jump to the failing test location. I know it's little code, so maybe it's not worth it.
Thank you for your help!
I'm happy you managed to get it working :)
Would you be interested in adding this function as part of Monroe's public API?
Monroe doesn't use lexical binding globally to support older emacses. If you can come up with a clever patch that will not use lexical binding, I'll be happy to include it :)
I'll close this ticket and if you think it should be re-opened, please do so. Cheers!
Let me think about it, and also see what other functionality emerges while I'm iterating on my config and setup 👍
A bit of background - I'm trying out Portal - it's a web-based Clojure data viewer/visualizer. Think
clojure.inspector
but modern. I want to integrate it with my Monroe-based workflow. Portal comes with a basic Emacs integration but requires running Emacs server and I think it shouldn't be required IMHO.I wrote this Elisp function to start a portal session and open xwidgets-webkit buffer with the Portal URL:
but I'd like to avoid writing the URL to a file and needing to invoke
sleep
- since I can useeval
to get the result. I tried to do it this way using Monroe's internal functions:My debugging shows that everything works until the
funcall
part - when I print out the type ofon-value
callback, rather than function, Emacs reports it ascons
. I assume it's something to do withmonroe-dbind-response
being a macro, but this is where I'm hitting a wall and limit of my Elisp understanding :-) I tried few things (quoting and not quoting) but I couldn't figure out how to make this work. Any pointers would be appreciated and I could add a function as part of a public API to make this sort of integration easier - I think it would be useful to bridge Emacs and the nREPL process together in many ways.Many thanks!