Fork me on GitHub
#conjure
<
2020-04-22
>
martinklepsch08:04:19

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

olical12:04:20

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!

olical12:04:24

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.

olical12:04:11

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!

olical12:04:07

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.

olical12:04:29

And it works with shadow-cljs :exploding_head:

dharrigan12:04:45

I use CoC. I like it.

dharrigan12:04:49

Terrible name 'tho.

olical12:04:32

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.

olical12:04:07

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 :/

olical12:04:31

I should write my own Lua based one so you don't need anything external πŸ˜…

dharrigan13:04:17

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

dave13:04:07

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.

dave13:04:09

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

dominicm13:04:06

best call it "conquerer of completion"

olical14:04:24

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

olical14:04:49

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 []

olical19:04:02

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

olical19:04:23

Otherwise it's basically identical

olical19:04:23

There's a few ways to exec the lua from vim script: https://neovim.io/doc/user/lua.html But the lua code will be the same as my one above

matthew.newland19:04:29

cheers - I’ll give it a go

matthew.newland16:04:28

I’ll test is out as I work.

olical16:04:53

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

olical16:04:00

So like return require...

matthew.newland16:04:24

didn’t work with them in ?

olical16:04:56

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

olical16:04:04

If that works for you then great!

olical16:04:43

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

olical16:04:51

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

olical16:04:15

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

olical16:04:48

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.

matthew.newland16:04:24

yes - i just wanted to get it going

olical16:04:35

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

olical16:04:48

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

olical16:04:08

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

matthew.newland16:04:19

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

matthew.newland16:04:00

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

olical16:04:27

Oh, interesting!

olical16:04:58

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

olical16:04:06

If it's in messages I bet I left a debug println in πŸ˜…

matthew.newland16:04:25

I think so πŸ˜‰

olical16:04:11

Fixed and pushed!

olical16:04:22

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.

olical14:04:53

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

olical14:04:11

Got coffee though so yay!

olical15:04:11

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

olical15:04:34

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.

nate15:04:31

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

dave15:04:38

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

dave15:04:24

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

dave15:04:05

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

olical15:04:44

πŸ€” 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.

olical15:04:57

I can see reasons for either direction.

nate15:04:32

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

nate15:04:38

completion via coc works wonderfully

nate15:04:44

going to try and use this for my work today

nate15:04:49

thank you @olical!!!

olical15:04:20

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

dominicm17:04:10

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 http://core.as

olical17:04:26

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

dominicm17:04:47

Great 😁

dominicm17:04:56

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

olical17:04:04

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

olical17:04:33

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.

olical17:04:35

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

dominicm17:04:39

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.

dominicm17:04:56

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

olical17:04:31

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

olical17:04:40

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

olical17:04:33

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

dominicm17:04:37

There is no result, it's in the background

dominicm17:04:55

(future (prn x))

olical17:04:07

In CLJS or CLJ?

dominicm17:04:23

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

dominicm17:04:08

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

olical17:04:18

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

olical17:04:20

I see the output

dominicm17:04:30

Cool, may motivate a switch this weekend πŸ˜„

olical17:04:54

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.

dominicm17:04:56

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

dharrigan17:04:33

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

dharrigan17:04:47

I'm looking to switch, but would rather wait until you think it's ready πŸ™‚

dharrigan17:04:00

(as far as software can ever be ready πŸ™‚ )

nate18:04:26

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.

olical10:04:53

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 πŸ€”

olical10:04:15

Going to remap view source to <prefix>vs

olical10:04:23

Then add more "view" things in there maybe.

olical10:04:42

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.

olical10:04:24

Also ei for interrupt πŸ€”

olical10:04:26

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

olical10:04:48

Found a bug in it while improving it hah

nate18:04:34

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

nate18:04:47

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

nate18:04:06

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

nate18:04:09

or something like that

nate18:04:51

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

olical10:04:22

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

olical10:04:19

Can't actually reproduce this one πŸ€”

olical10:04:50

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

olical10:04:46

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

matthew.newland18: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 ","

nate19:04:33

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

nate19:04:45

how are you running it?

nate19:04:09

I put this:

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

nate19:04:28

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

nate19:04:41

I'm surely doing something daft

matthew.newland20:04:20

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

olical21:04:52

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 πŸ€” will take a look at all of this feedback tomorrow! Thank you all so much!

nate21:04:59

sweet, thanks

olical10:04:37

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.

olical10:04:31

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.

matthew.newland11: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 ?

olical11:04:00

Hmm, yeah, that'll do it. I'll have a think about how this could be done + lazy loading πŸ€”

olical11:04:37

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.

olical11:04:05

Probably a VimL function but yeah, not sure.

olical12:04:55

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.

olical12:04:00

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.

olical12:04:45

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!

olical12:04:52

That has to be set before Conjure loads.

nate16:04:59

This is fantastic, thanks for this configuration option.

matthew.newland17:04:32

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

matthew.newland17:04:58

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

olical17:04:39

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

matthew.newland17:04:51

could be me but I have tried a few ways now

olical10:04:03

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

olical10:04:32

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

olical10:04:54

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)

olical10:04:11

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

matthew.newland10:04:11

bingo! fixed thanks

olical10:04:02

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...

matthew.newland10:04:08

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

olical10:04:38

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

matthew.newland10:04:39

with mappings with an β€˜s’

matthew.newland10:04:26

I will start using in earnest now

olical10:04:39

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!

olical10:04:58

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

sergiusz20:04:11

I tried the latest dev branch with a basic clojurescript file. It worked well with the nrepl-piggieback-cider.sh 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.

olical10:04:54

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

olical20:04:20

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

dominicm21:04:05

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

nate21:04:19

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

dave23:04:43

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

nate23:04:19

hehe, I understand

olical10:04:30

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