sanel / monroe

Clojure nREPL client for Emacs
161 stars 21 forks source link

getting autocomplete to work with Monroe #38

Closed zcaudate closed 3 years ago

zcaudate commented 3 years ago

I'm trying to move off cider but the autocomplete and el-doc features are stopping me from doing so.

Is there a configuration add-on for Monroe that can work with compliment and company-mode?

lukaszkorecki commented 3 years ago

This is most likely out of Monroe's scope, but I've been using Monroe and clojure-lsp together and it's a pretty good combo.

sanel commented 3 years ago

There is no add-on and (as @lukaszkorecki mentioned) it is out of the project's scope, but you should be able to integrate it easily with lsp or other completion systems.

zcaudate commented 3 years ago

I don't think static analysis is going to help me much. thanks anyways!

technomancy commented 3 years ago

Things have changed a bit with nrepl recently on this front.

It used to be that completion was handled by 3rd-party middleware. However, now it's considered a built-in op for the reference nrepl server:

https://nrepl.org/nrepl/0.8/ops.html#completions

I think because of this it might be a good idea to reconsider Monroe's stance. We can now offer completion without requiring any extra server-side configuration as a protocol-level operation; no need to send code to the server to evaluate to calculate the completions.

zcaudate commented 3 years ago

It's frustrating that there's such a gap with Cider and the rest of the Emacs tooling while Neovim tooling seems to be getting really good and actually fills a middle ground between spartan and kitchen sink - though switching to vim is just not an option for me.

Cider is too bloated for what I need - eldoc, autocomplete, overlays, and error popups - but it works so I'll stick to it until it gets really slow and I'm forced to get better at Elisp.

zcaudate commented 3 years ago

@technomancy What is Monroe's stance and what cause is it standing for?


I'm not sure how good the static analysis will be. I've got a bunch of top level macros that do a lot of rewriting. It's clojure compatible but it's not really clojure any more.

(defn.pg ^{:- [:text]
           :props [:immutable :parallel-safe]}
  base64-decode
  "decodes form web base64"
  {:added "4.0"}
  [:text data]
  (let [(:text trans) (pg/translate data "-_" "+/")
        (:int rem)    (mod (pg/length trans)
                           4)
        (:bytea out)  (pg/decode (|| trans
                                     (pg/case (> rem 0)
                                              (pg/repeat "="
                                                         (- 4 rem))

                                              :else (% "")))
                               "base64")]
    (return (pg/encode out "escape"))))
technomancy commented 3 years ago

What is Monroe's stance and what cause is it standing for?

I can't speak with authority but my interpretation of Monroe is that it is an nrepl client designed to operate on a bare nrepl server without any additional server-side support. Because of this, it can support operations like eval and doc, which are part of the stock nrepl server, but not things like tracing or test runners.

There is limited support for operations which aren't supported server-side, but only if they can be implemented using pure-elisp, or by sending small amounts of Clojure from Emacs over the wire. For instance, the implementation of M-. to jump to a var's definition involves sending three lines of Clojure to the remote side to be evaluated, and since Clojure vars are so great, that's all it needs to find definitions:

  (monroe-send-eval-string
   (format "%s" `((juxt (comp str clojure.java.io/resource :file) :line)
                  (meta ,(if ns `(ns-resolve ',(intern ns) ',(intern var))
                           `(resolve ',(intern var))))))

Before completion became implemented server-side, we could have done this from elisp->clojure, but it would have been a lot more than three lines, so it was reasonable to say that it was out of scope for Monroe. But now it's just sending {:op "completion" :prefix "foo" :ns "whatever"} as an nrepl op, and that's a lot simpler!

zcaudate commented 3 years ago

Oh. That's really good to know. I'm actually more partial to the Monroe philosophy having just discovered that it's possible to send anything over the repl https://github.com/scicloj/notespace/blob/master/emacs-config.el. I can definitely see the advantage of having more op codes vs having a simpler client - middleware being a huge bonus.

But the way I see it - if it were easier to work with elisp, then some of the nrepl middleware would probably move onto the client. Having a richer set of codes means that more client and server code must be maintained and synced up which adds to the complexity.

I'm a bit biased though because I've been getting good mileage purely out of sending raw code over stdio, and having it print back json. It's not pretty but it's trivial to get a working client up and running.

The clojure var thing is pretty cool. I'm actually doing quite a bit of code generation of vars and and sometimes the cider-find-var command gets a little bit too smart and misses on the jump-to whereas it just works with monroe. Now I know why.