Closed abo-abo closed 6 years ago
Hi @abo-abo, the equivalent function is called spiral-aux-sync-request
. The signature is different from nrepl-sync-request:eval
, it only needs the input. The connection is taken from a buffer local variable called spiral-conn-id
, which should be a symbol of the form 'localhost:5555
, which should be automatically set if the buffer is already connected/has spiral-mode
on.
Feel free to close this issue if this answers your question and covers what you would need. It'd be cool to know what are you planning to implement :)
Thanks for the pointer. Here's what I've got so far.
Getting the value of the evaluated expr works:
(let* ((r (spiral-aux-sync-request "(range 100)")))
(with-temp-buffer
(spiral-ast-unparse r)
(substring-no-properties
(buffer-string))))
;; => "(0 1 2 3 4 5 6 7 8 9 ...)"
However, the print output is nowhere to be found:
(let* ((r (spiral-aux-sync-request "(do (print \"test\") (+ 1 2))")))
(with-temp-buffer
(spiral-ast-unparse r)
(substring-no-properties
(buffer-string))))
;; => "3"
Looking at how it's handled in the REPL eval, the print output comes in chunks, which makes getting it all in a sync request harder.
With nREPL, I getting the output was as easy as (nrepl-dict-get res "out")
. Is it possible with unREPL?
Right. Sorry I forgot to mention that results came as parseclj
AST data structures and you'd have to unparse them, but you figure it out on your own :)
spiral-aux-sync-request
only returns the evaluation result. In reality, this function is almost never used in the SPIRAL code, since we try to always adapt to the nature of a stream based REPL (different from nREPL RPC messaging system). The only place where spiral-aux-sync-request
is being used is in the completion system, where Emacs needs a sync'd response to completion candidates.
That being said, implementing your own function that returns both eval result and stdout, should be a relatively simple variation of spiral-aux-sync-request
:
(defun spiral-aux-sync-request-2 (str)
(let* ((start (current-time))
(conn-id spiral-conn-id)
(unparse-no-properties (lambda (node) (substring-no-properties
(spiral-ast-unparse-to-string node))))
stdout
result)
(spiral-loop--send conn-id :aux str)
(spiral-pending-eval-add :aux conn-id
:status :sent
:eval-callback (lambda (eval-payload)
(setq result (funcall unparse-no-properties eval-payload)))
:stdout-callback (lambda (stdout-payload &rest _)
(setq stdout
(concat stdout
(funcall unparse-no-properties stdout-payload)))))
(while (and (not result)
(not (input-pending-p)) ;; do not hang UI
(or (not spiral-aux-sync-request-timeout)
(< (cadr (time-subtract (current-time) start))
spiral-aux-sync-request-timeout)))
(accept-process-output nil 0.01))
(list :result result
:stdout stdout)))
(spiral-aux-sync-request-2 "(do (println \"hi\") (println \"another thing\") (+ 1 1))")
This of course will only record stdout strings that happens "synchronously" before the actual result, so for example, prints like: (future (Thread/sleep 5000) (println "delayed 5 secs"))
wouldn't be recorded.
Hope this helps.
Hope this helps.
It does, thanks a lot.
On another topic, is there a good Clojure workflow for dynamically installing and requiring packages into a running REPL without having to restart it? Basically, like load-path
and package.el
for Emacs, or sys.path
and pip
for Python?
I've had a brief look at pomegranate for this purpose, but it's a bit cumbersome; and version 1.0.0
looks to be broken.
It's one of the top things in my TODO list.
I was thinking on using pomegranate for this, but I haven't looked too deep into it yet. clj-refactor
provides this feature but it's tightly coupled to nREPL, so it works with cider
but not with UNREPL. If I remember corrercly, clj-refactor
uses alembic
internally, which could also be an option.
Unfortunately it's abandonware and clj-refactor
is using some forked version of it. Those dynamic loads are always painful with Java/Clojure and that's one of the reasons I didn't want this feature in CIDER initially.
FYI, just made some prograss on the issue. I'm kind of new to Clojure for a while now, since I don't use it at work. Takes me a while to figure out the best practices with things like class paths and package management.
Hi, I just happened upon your project, played around with it a bit; I really like the shorter startup time and the expandable eval results.
I'd like to add some unrepl support to lispy.el to play around with it a bit more. I need just one function for sync eval to get started; it looks like this for CIDER: