Fork me on GitHub
#conjure
<
2020-09-17
>
Aleh Atsman08:09:36

Hey guys, does anyone has an idea how hard is it to make competition source for https://github.com/nvim-lua/completion-nvim from conjure?

Olical08:09:19

There's essentially a sort of promise implementation in Conjure to make the async work a little easier, you can use a sync complete function that blocks or the true async promise based one (highly recommended!). I would imagine asyncomplete is similar to completion-nvim?

Aleh Atsman08:09:30

I think yes they are similar, will figure it out and see if I can make minimal working solution

Aleh Atsman08:09:45

really want to have it with nvim-completition

Olical08:09:56

Sweet! If you do get it working (feel free to ask me some questions if you're really stuck but I think those examples should be enough) let me know and I'll add it to the lists of completion tools.

Aleh Atsman12:09:34

function M.get_completions(prefix)
  local p = eval["completions-promise"](prefix)
  while not promise["done?"](p)
  do
    print("i am waiting") -- **what is the equivalent of time.sleep?**
  end

  result = promise["close"](p)

  local complete_items = {}
  for _, item in ipairs(result) do
    if item ~= "^" .. prefix then
      table.insert(complete_items, {
          word = item,
          kind = 'conjure',
          icase = 1,
          dup = 0,
          empty = 0,
        })
    end
  end

  print(vim.inspect(complete_items))
  return complete_items
end

Aleh Atsman12:09:45

what is the equivalent of time sleep?

Aleh Atsman12:09:11

for lua code, or what is the proper way of handling async code?

Olical12:09:54

so you set up a timer then periodically check if the completions are done

Olical12:09:04

Any other method (like sleeping) will block the editor

Olical12:09:25

The reason the deoplete and coc implementations can sleep is because they're run in a separate process so they don't block nvim's ui.

Olical12:09:25

You could actually use the conjure.timer module or maybe just copy parts of it that you need

(module conjure.timer
  {require {a conjure.aniseed.core
            nvim conjure.aniseed.nvim}})

(defn defer [f ms]
  (let [t (vim.loop.new_timer)]
    (t:start ms 0 (vim.schedule_wrap f))
    t))

(defn destroy [t]
  (when t
    (t:stop)
    (t:close))
  nil)

Olical12:09:06

This uses the vim.loop.* functions which don't seem to be documented but actually map to libuv functions, so I just googled for "lib uv api" then guessed my way through to using new_timer, start, stop and close.

Olical12:09:19

libuv is great for anything like this

Olical12:09:45

So a combination of using / taking and modifying Conjure's timer module + the lib uv docs should be enough to get a repeating timer running where you can check if the promise is done.

Olical12:09:34

Oh you have to return the results :thinking_face: that's not great, it's not really async in that way then, it's a sync function that they somehow run in an async way? You could try calling eval.completions-sync or using promise.await like that function does. I just think this will block neovim's ui which isn't great https://github.com/Olical/conjure/blob/566915cc545edd68bab2ad76eb59dfa43648a8b3/fnl/conjure/eval.fnl#L200-L203

Olical12:09:12

Or maybe there's a way to sleep the process from libuv that I don't really know about.

Aleh Atsman13:09:01

well yes looks like probably I can use sync api for my code, it is used later using timer, could that be the case

Olical08:09:24

:thinking_face: maybe? I don't really understand the completion-nvim plugin right now, but it's worth checking what sort of APIs they give you. If you can write a callback based async completer (so you call a function when you're done) it'll be easier to check the promise every 5ms or something then call the callback with the results when it's done.