Fork me on GitHub

I haven’t used an editor with autocompletion in forever but I guess I’ll have to try this


Deoplete support should be on develop now! All you need is deoplete + conjure(develop) installed and an nREPL connection with CIDER. On the next nREPL update you won't even need the CIDER middleware for basic completion!


I'll take a stab at CoC after some lunch. I've managed to implement this whole thing without an extra JSON RPC server like I had last time, so writing completion clients is a LOT simpler. Relying on Neovim's wait() function and a UUID based ticketing system to get async results across multiple languages.


Deoplete sources are Python, and I can't pass callbacks around between Lua and Python, so I had to come up with a way to do async stuff nicely without blocking nvim and keeping it single threaded. Fun times!


Basically when you start completions you get a ticket (a UUID) that you can check against a pool of results. When it's marked as done you unbox the value which frees up the ticket. Neovim has a mechanism for efficiently checking a VimL expression regularly until it's true, so it fits in nicely.


And it works with shadow-cljs 🤯


I use CoC. I like it.


Terrible name 'tho.


Yeah, wasn't a fan of the name either, I didn't really want a completion AND LSP client in one either, but meh, not so bothered about that. I'm happy with Deoplete.


I love that I can embed Deoplete support within Conjure's repo and it just works. I don't think CoC lets you do that, needs to be a published npm package :/


I should write my own Lua based one so you don't need anything external 😅


I could drop CoC in favour of Deoplete (which I had prior). I'll retry once Conjure is out again.


i'm a big fan of LSP and use it (via CoC) in a bunch of different languages. it's quite nice when doing java, go, etc.


i think there might be something to be said for using deoplete and swapping out CoC for a lighter-weight LSP client plugin that isn't also a completion plugin


best call it "conquerer of completion"


I accidentally refactored that async management code into a generic promise-ish module within Conjure 😬


This is near enough the entirety of the Deoplete integration:

p = self.vim.exec_lua("return require('conjure.eval')['completions-promise'](...)", context["complete_str"])
    self.vim.exec_lua("require('conjure.promise').await(...)", p)
    return self.vim.exec_lua("return require('conjure.promise').close(...)", p) or []


Ah, so where I have the vim.exec_lua calls, it basically just becomes luaeval("...", [args]) in vimscript


Otherwise it's basically identical


There's a few ways to exec the lua from vim script: But the lua code will be the same as my one above

The Continium19:04:29

cheers - I’ll give it a go

The Continium16:04:28

I’ll test is out as I work.


Hmm, you'll need some "return" keywords in your Lua there, it doesn't return by default (unless that function is different)


So like return require...

The Continium16:04:24

didn’t work with them in ?


Oh interesting! Maybe it inserts it for you or something. It's just different to how I've been running the Lua


If that works for you then great!


I could make this even simpler for you so you don't have to touch the promises :thinking_face: it'd just be one function call then.


I have been considering doing that, maybe now's the time.


So you could call luaeval("require('conjure.eval')['completions-sync'](...)", a:typed) and it would return the result.


But you might want to start the completions, do some other calls and then await the results. Which is why I exposed the three steps so you could decide when to await / get the results.

The Continium16:04:24

yes - i just wanted to get it going


Okay, pushed, you can call require('conjure.eval')['completions-sync'](...) and get results right away!


You don't need to worry about the underlying async / waiting system then.


Just swapped the internal deoplete one to it, works well for me

The Continium16:04:19

Yep that works! One thing I am getting is some :messages like (f__prefix__), (d__prefix__) ?

The Continium16:04:00

when it has found matches starting with f,d in this case.


Oh, interesting!


So that prefix is part of the context used by complement to provide lexical completions. Like completing things in your local let bindings.


If it's in messages I bet I left a debug println in 😅

The Continium16:04:25

I think so 😉


Fixed and pushed!


Have you got your plugin in a repo? And what is it building on top of? Just so I can link to them in the help.


I'm touching JavaScript for the first time in a long time. My opinions still hold.


Got coffee though so yay!


Seems to work! Please give coc-conjure-olical a go, I've published it to make it easy to test. PR: The canonical coc-conjure should be updated as and when the rewrite is published on the master branch.


One more thing I need to do: Turn off auto completion when you're in a comment or string. I mean, I don't think you want this? The previous iteration wouldn't bother autocompleting if you were typing in comments or strings and I think it was a decent bet but I'm not sure. Maybe it's not worth the hassle of checking and it could be useful sometimes.


Hm. Interesting. I'll try it out today and see how it looks in comments.


i think it might be useful sometimes. i write a lot of comments and they often refer to vars in the namespace, etc.


although on the other hand, i also get autocompletion of words in any buffer i have open, so i can get the var names autocompleted that way too


i can't imagine that there are a lot of times when the thing i'm trying to type isn't already present in a buffer that i have open


:thinking_face: I'll give it a bit of time and though, let me know how you all feel about it too. Maybe it stays in for release then it gets removed after, or even through config.


I can see reasons for either direction.


just tried it out, and I think leaving it on in comments and strings could be useful


completion via coc works wonderfully


going to try and use this for my work today


thank you @olical!!!


Yay! I hope it works well! If you encounter any issues I'd love to hear about them 😄 (and then fix them)


Just to clarify before I get excited, as I'm not ready to jump over yet, does conjure print background prns? It would make debugging


It handles prints form unknown evaluations that aren't tied to a user initiated eval... so as long as nREPL sends them, yes?


I don't suppose it has any fancy tap> integration too?


    (do (Thread/sleep 5000)
        (println "BAR")))
shows me the stdout


Hmm, I haven't added tap yet, but I think nREPL has a hook for it. It's not on automatically like prepl. I think it'll be trivial though, I'll probably do that tomorrow morning.


Yeah, no tap messages by default. I think you subscribe to them.


Cool. I'm not sure if that's something that would work meaningfully with cljs, but might be cool if you can grab a tapped value and def it, etc.


I suppose if you prn a value, you can def that, so not a problem really.


Normally I just go into the log buffer, wrap the result in a def and then eval it 😅 or use *1 etc


If I ever need to work with the value in some captured way


Hmm not sure where I saw tap mentioned wrt nREPL :thinking_face: thought there was an op for it or something. Can't find it now.


There is no result, it's in the background


(future (prn x))




cljs, technically. Where there's no future, so it's (go (prn x))


I mean, there's a future in cljs, just not a :drum_with_drumsticks:

😂 4

(js/setTimeout (fn []
                 (println "foo"))
this works for me


I see the output


Cool, may motivate a switch this weekend 😄


Well if you give it a go I'd love to have your feedback! Still lots to do but I much prefer this to my older implementation.


or I suppose I could use js/console.log and then click "store as global variable"...


So, what's the feature parity with the current conjure?


I'm looking to switch, but would rather wait until you think it's ready 🙂


(as far as software can ever be ready 🙂 )


For me, as far as parity, it has: - eval root - eval at mark - autocomplete - pretty printing - doc (via K) New things that I really like: - the awesome new HUD/log flow, which is way better (not denigrating previous, but I'm a fan of the new one) - no JVM, so lighter on my VM Things that I've encountered from a morning of using it: - Printing out a lot sometimes gets the output incorrect in the buffer - I have an ,es mapping already, need to move the new conjure one to something else - no folding of multiline results (not too bad, just noticed it on my first exception) None of these are deal breakers for me. I only use tap in one place for debugging, so I can wait on that.


Few questions around here: Printing a lot gets the output wrong? Like... the lines are interleaved? Or parts of some things get cut off? I haven't added any folding just yet, not toooo hard to add. Will add it to my feature list. And sorry about the es conflict! Seemed like the best place to put it, although maybe it shouldn't be under the e prefix. Since it's not quite an eval, maybe there should be a "view" prefix for viewing different things like source and docs :thinking_face:


Going to remap view source to <prefix>vs


Then add more "view" things in there maybe.


I think I'll move "view last exception", "view last result" and the "view 2nd / 3rd result" there too. Just to keep "eval something from my buffer" separate to displaying things from elsewhere.


Also ei for interrupt :thinking_face:


I'll leave interrupt there but make it work a little better.


Found a bug in it while improving it hah


just had an issue. 1. working along just fine 2. had to restart my JVM 3. conjure lost connection, so I ran :ConjureConnect 44499 4. It reconnected and I can eval, but the HUD no longer autohides


don't know what about my series of actions cause it to happen


but it might be nice to have a :ConjureHUDToggle so I can turn it off manually


or something like that


I just restarted neovim and (thanks to sessions) am off and running again


I think I know what can cause this, might even be able to repro through the rest suite!


Can't actually reproduce this one :thinking_face:


Moving your cursor should always hide it unless it's lost track of the window ID, that's the only way I can see this happening. You can turn it off entirely with :ConjureConfig log.hud.enabled? false


:lua require('conjure.log')['close-hud']() will also do it.

The Continium18:04:12

Did a quick test run looking good . One thing I noticed was that setting the prefix by ConjureConfig mapping.prefix "," didn’t change the mapping; <localleader> was still mapped even though ConjureConfig mapping.prefix resulted in mapping.prefix ","


I tried to do some ConjureConfig lines in my vimrc, but the command doesn't seem to be available


how are you running it?


I put this:

ConjureConfig clojure.nrepl/mappings.view-source "ss"
ConjureConfig clojure.nrepl/mappings.session-select "cs"


and get E492: Not an editor command: ConjureConfig clojure.nrepl/mappings.view-source "ss"


I'm surely doing something daft

The Continium20:04:20

I was not setting at the language level; straight from the help


ConjureConfig may be bound to one of the filetypes so it isn't defined yet or it's just not defined because your config is running before the plugin is loaded :thinking_face: will take a look at all of this feedback tomorrow! Thank you all so much!


sweet, thanks


So ConjureConfig is defined when Conjure is loaded, so make sure your config is being run after the plug#end call or whatever you use with your plugin manager to load things. Maybe it needs to be moved to an autoload function wrapper or something but shouldn't be required.


Oh, actually I know what this is! Had you already opened the Clojure buffer when you ran this? If so the mappings have already been set! I would say put this in your vim config just after the plugins have been loaded. But before you open a Clojure file. Once mappings are set buffer local you can't just unset them and reset them easily. They're set from the config at the time the buffer is opened.

The Continium11:04:18

I lazy load plugins. On ft clojure conjure is sourced which then in turn ConjureConfig mapping.prefix "," . This sounds too late from what you are saying ?


Hmm, yeah, that'll do it. I'll have a think about how this could be done + lazy loading :thinking_face:


Maybe I can have Conjure call a function (doesn't have to be defined unless you're in a situation like yours) when it loads.


Probably a VimL function but yeah, not sure.


I'm actually concerned lazy loading will break the filetype autocmds conjure uses on the first file you open. Let me know if you see weirdness although I don't think there's anything I can do about it. When conjure loads all it does is set up a few autocmds, all of that runs in luajit so it'll be fast. The actual language support and clients aren't loaded until they're required.


Thought of a solution, you can set a g:... = {} value before Conjure is initialised then I'll run it through ConjureConfig where the keys are the first argument (path) and values are the second argument.


I've added g:conjure_config which you could set like this let g:conjure_config = {"mapping.prefix": ","} which should work in your case. I hope!


That has to be set before Conjure loads.


This is fantastic, thanks for this configuration option.

The Continium17:04:32

Hi @olical just tried these steps. 1. Conjure not loaded. 2. let g:conjure_config = {"mapping.prefix": ","} 3. Open a clj file

The Continium17:04:58

Conjure is sourced and connects to nrepl; the prefix is still set as the default.


Hmm, interesting! I'll give it a test soon, thought it was fine but I'm obviously missing something

The Continium17:04:51

could be me but I have tried a few ways now


OH, it's ConjureConfig mappings.prefix, not mapping, it's plural!


The helpfile was wrong in one place, which is the one I think you found


So yeah, the ConjureConfig command should work with mappings, not mapping (maybe I could have it throw if there's a typo... introduces issues though when you want to set something new)


There's something wrong with g:conjure_config still, investigating

The Continium10:04:11

bingo! fixed thanks


Awesome! I'm just seeing something weird, when I set the vim dictionary to set mappings.prefix, it ends up being mappings.leader at runtime and I have absolutely no idea how...

The Continium10:04:08

this works for me let g:conjure_config = {"mappings.prefix": ","}


Hopefully that variable and the command (passive and active alternatives) are good enough for everyone!

The Continium10:04:39

with mappings with an ‘s’

The Continium10:04:26

I will start using in earnest now


I'm excited to hear your feedback! Nate reported that he got the log and HUD into a weird state when he had to restart his JVM + there was a lot of output. If you can reproduce anything of the sort I'd be really interested in how you did it!


Cool, g:conjure_config is working for me now, I was doing something dumb, as usual.

Sergiusz Bleja20:04:11

I tried the latest dev branch with a basic clojurescript file. It worked well with the running, but first I tried it without: on every edit it froze for a few seconds with the log popping up with a 'no connection' message, making editing impossible. Let me know if you need more details.


Pushed a change to make completions return nothing silently if there's no connection or the op isn't supported by the server.

👍 4

Ah, that'll be the completion, I need to make it not try if there's no connection!


It would be handy if it tried to establish it, but only in the background


haha, I just used completion in a docstring, and it was useful. don't know how I managed before

💡 4

i'm at the point now where i feel like i'm doing about 50% typing and 50% pressing TAB to choose completion results, lol. it feels just a little bit dirty, like i'm training myself to forget how to spell or something


hehe, I understand


Hah, I know that feeling too! Same as using z= to correct spellings where I've typoed and I'm too lazy to just F back to it and replace or insert


ConjureConfig may be bound to one of the filetypes so it isn't defined yet or it's just not defined because your config is running before the plugin is loaded :thinking_face: will take a look at all of this feedback tomorrow! Thank you all so much!