Beispiel #1
0
def _ts_notify(
    nvim: Nvim,
    stack: Stack,
    session: int,
    buf: int,
    filetype: str,
    reply: Sequence[RawPayload],
    elapsed: float,
) -> None:
    async def cont() -> None:
        global _COND, _SESSION
        _COND = _COND or Condition()

        if session >= _SESSION.uid:
            payload = _Payload(
                buf=buf,
                filetype=filetype,
                payloads=reply,
                elapsed=elapsed,
            )
            _SESSION = _Session(uid=session, done=True, payload=payload)

        async with _COND:
            _COND.notify_all()

    go(nvim, aw=cont())
Beispiel #2
0
def _hl_text(nvim: Nvim, text: str) -> None:
    nvim.funcs.setreg("/", _magic_escape(text))

    def cont() -> None:
        nvim.options["hlsearch"] = True

    go(nvim, aw=async_call(nvim, cont))
Beispiel #3
0
def _ft_changed(nvim: Nvim, stack: Stack) -> None:
    buf = cur_buf(nvim)
    ft = buf_filetype(nvim, buf=buf)

    async def cont() -> None:
        await stack.bdb.ft_update(buf.number, filetype=ft)

    go(nvim, aw=cont())
Beispiel #4
0
def _new_cwd(nvim: Nvim, stack: Stack) -> None:
    cwd = get_cwd(nvim)

    async def cont() -> None:
        s = state(cwd=cwd)
        await stack.ctdb.swap(s.cwd)

    go(nvim, aw=cont())
Beispiel #5
0
def _check_time(nvim: Nvim) -> None:
    check = lambda: nvim.command("silent! checktime")

    async def cont() -> None:
        async for _ in aticker(3, immediately=False):
            go(async_call(nvim, check))

    go(cont())
Beispiel #6
0
 def __init__(self, supervisor: Supervisor, options: BaseClient,
              misc: None) -> None:
     self._lock = Lock()
     self._bin: Optional[PurePath] = None
     self._proc: Optional[Process] = None
     self._cwd: Optional[PurePath] = None
     super().__init__(supervisor, options=options, misc=misc)
     go(supervisor.nvim, aw=self._install())
     go(supervisor.nvim, aw=self._poll())
Beispiel #7
0
def _lsp_notify(nvim: Nvim, stack: Stack, rpayload: _Payload) -> None:
    async def cont() -> None:
        payload = _DECODER(rpayload)
        cond = _CONDS.setdefault(payload.name, Condition())

        acc = _STATE[payload.name]
        if payload.uid >= acc.uid:
            _STATE[payload.name] = _Session(
                uid=payload.uid,
                done=payload.done,
                acc=(*acc.acc, (payload.client, payload.reply)),
            )
        async with cond:
            cond.notify_all()

    go(nvim, aw=cont())
Beispiel #8
0
 def c1() -> None:
     if new_metric.comp.uid in stack.metrics:
         inserted_at = edit(
             nvim,
             stack=stack,
             state=s,
             metric=new_metric,
             synthetic=False,
         )
         ins_pos = inserted_at or (-1, -1)
         state(
             inserted_pos=ins_pos,
             last_edit=new_metric,
             commit_id=uuid4(),
         )
         go(nvim, aw=c2())
     else:
         log.warn("%s", "delayed completion")
Beispiel #9
0
def _listener(nvim: Nvim, stack: Stack) -> None:
    async def cont() -> None:
        while True:
            with with_suppress():
                qmsg: _Qmsg = await to_thread(q.get)
                lo, hi = qmsg.range
                await stack.supervisor.interrupt()

                size = sum(map(len, qmsg.lines))
                heavy_bufs = ({
                    qmsg.buf.number
                } if size > stack.settings.limits.index_cutoff else set())
                os = state()
                s = state(change_id=uuid4(), nono_bufs=heavy_bufs)

                if qmsg.buf.number not in s.nono_bufs:
                    await stack.bdb.set_lines(
                        qmsg.buf.number,
                        filetype=qmsg.filetype,
                        lo=lo,
                        hi=hi,
                        lines=qmsg.lines,
                        unifying_chars=stack.settings.match.unifying_chars,
                    )

                if (qmsg.buf.number in s.nono_bufs
                        and qmsg.buf.number not in os.nono_bufs):
                    msg = LANG(
                        "buf 2 fat",
                        size=size,
                        limit=stack.settings.limits.index_cutoff,
                    )
                    await awrite(nvim, msg)

                if (stack.settings.completion.always and not qmsg.pending
                        and qmsg.mode.startswith("i") and qmsg.comp_mode
                        in {"", "eval", "function", "ctrl_x"}):
                    comp_func(nvim, s=s, manual=False)

    go(nvim, aw=cont())
Beispiel #10
0
def _when_idle(nvim: Nvim, stack: Stack) -> None:
    global _HANDLE
    if _HANDLE:
        _HANDLE.cancel()

    def cont() -> None:
        buf = cur_buf(nvim)
        buf_type: str = buf_get_option(nvim, buf=buf, key="buftype")
        if buf_type == "terminal":
            nvim.api.buf_detach(buf)
            state(nono_bufs={buf.number})

        _insert_enter(nvim, stack=stack)
        stack.supervisor.notify_idle()

    get_running_loop().call_later(
        stack.settings.limits.idle_timeout,
        lambda: go(nvim, aw=async_call(nvim, cont)),
    )
Beispiel #11
0
 def __init__(
     self, supervisor: Supervisor, options: BuffersClient, misc: BDB
 ) -> None:
     super().__init__(supervisor, options=options, misc=misc)
     go(supervisor.nvim, aw=self._poll())
Beispiel #12
0
def _launch_loop(nvim: Nvim, stack: Stack) -> None:
    task: Optional[Task] = None
    incoming: Optional[Tuple[State, bool]] = None

    async def cont() -> None:
        lock, event = Lock(), Event()

        async def c0(s: State, manual: bool) -> None:
            with with_suppress(), timeit("**OVERALL**"):
                if lock.locked():
                    log.warn("%s", "SHOULD NOT BE LOCKED <><> OODA")
                async with lock:
                    ctx = await async_call(
                        nvim,
                        lambda: context(
                            nvim,
                            db=stack.bdb,
                            options=stack.settings.match,
                            state=s,
                            manual=manual,
                        ),
                    )
                    should = _should_cont(s, prev=s.context,
                                          cur=ctx) if ctx else False
                    _, col = ctx.position

                    if should:
                        state(context=ctx)
                        await stack.supervisor.interrupt()
                        metrics, _ = await gather(
                            stack.supervisor.collect(ctx),
                            async_call(
                                nvim,
                                lambda: complete(
                                    nvim, stack=stack, col=col, comps=()),
                            ) if stack.settings.display.pum.fast_close else
                            sleep(0),
                        )
                        s = state()
                        if s.change_id == ctx.change_id:
                            vim_comps = tuple(
                                trans(
                                    stack,
                                    pum_width=s.pum_width,
                                    context=ctx,
                                    metrics=metrics,
                                ))
                            await async_call(
                                nvim,
                                lambda: complete(nvim,
                                                 stack=stack,
                                                 col=col,
                                                 comps=vim_comps),
                            )
                    else:
                        await async_call(
                            nvim, lambda: complete(
                                nvim, stack=stack, col=col, comps=()))
                        state(inserted_pos=(-1, -1))

        async def c1() -> None:
            nonlocal incoming
            while True:
                with with_suppress():
                    incoming = await to_thread(_Q.get)
                    event.set()

        async def c2() -> None:
            nonlocal task
            while True:
                with with_suppress():
                    await event.wait()
                    event.clear()

                    if task:
                        await cancel(task)

                    if incoming:
                        assert isinstance(nvim.loop, AbstractEventLoop)
                        s, manual = incoming
                        task = nvim.loop.create_task(c0(s, manual=manual))

        await gather(c1(), c2())

    go(nvim, aw=cont())
Beispiel #13
0
def _comp_done(nvim: Nvim, stack: Stack, event: Mapping[str, Any]) -> None:
    data = event.get("user_data")
    if data:
        try:
            uid = _UDECODER(data)
        except DecodeError:
            pass
        else:
            s = state()
            if metric := stack.metrics.get(uid):
                row, col = s.context.position
                buf = cur_buf(nvim)
                ns = create_ns(nvim, ns=NS)
                clear_ns(nvim, buf=buf, id=ns)
                before, *_ = buf_get_lines(nvim, buf=buf, lo=row, hi=row + 1)
                e1 = ExtMark(
                    idx=1,
                    begin=(row, 0),
                    end=(row, col),
                    meta={},
                )
                e2 = ExtMark(
                    idx=2,
                    begin=(row, col),
                    end=(row, len(encode(before))),
                    meta={},
                )
                buf_set_extmarks(nvim, buf=buf, id=ns, marks=(e1, e2))

                async def cont() -> None:
                    if metric:
                        new_metric = await _resolve(nvim,
                                                    stack=stack,
                                                    metric=metric)

                        async def c2() -> None:
                            if isinstance((extern := new_metric.comp.extern),
                                          ExternLSP):
                                await cmd(nvim, extern=extern)

                        def c1() -> None:
                            if new_metric.comp.uid in stack.metrics:
                                inserted_at = edit(
                                    nvim,
                                    stack=stack,
                                    state=s,
                                    metric=new_metric,
                                    synthetic=False,
                                )
                                ins_pos = inserted_at or (-1, -1)
                                state(
                                    inserted_pos=ins_pos,
                                    last_edit=new_metric,
                                    commit_id=uuid4(),
                                )
                                go(nvim, aw=c2())
                            else:
                                log.warn("%s", "delayed completion")

                        await async_call(nvim, c1)

                go(nvim, aw=cont())
Beispiel #14
0
        return ()


async def _resolve(nvim: Nvim, stack: Stack, metric: Metric) -> Metric:
    if not isinstance((extern := metric.comp.extern), ExternLSP):
        return metric
    else:
        if comp := stack.lru.get(metric.comp.uid):
            return replace(
                metric,
                comp=replace(metric.comp,
                             secondary_edits=comp.secondary_edits),
            )
        else:
            done, not_done = await wait(
                (go(nvim, aw=resolve(nvim, extern=extern)), ),
                timeout=stack.settings.clients.lsp.resolve_timeout,
            )
            await cancel(gather(*not_done))
            comp = (await done.pop()) if done else None
            if not comp:
                return metric
            else:
                return replace(
                    metric,
                    comp=replace(metric.comp,
                                 secondary_edits=comp.secondary_edits),
                )


_UDECODER = new_decoder[UUID](UUID)
Beispiel #15
0
                                              lines_around=ts.search_context):
                await stack.tdb.populate(
                    payload.buf,
                    filetype=payload.filetype,
                    nodes=payload.payloads,
                )
                if payload.elapsed > ts.slow_threshold:
                    state(nono_bufs={buf.number})
                    msg = LANG(
                        "source slow",
                        source=ts.short_name,
                        elapsed=si_prefixed_smol(payload.elapsed, precision=0),
                    )
                    await awrite(nvim, msg, error=True)

    go(nvim, aw=cont())


autocmd("InsertEnter") << f"lua {NAMESPACE}.{_insert_enter.name}()"


@rpc(blocking=True)
def _on_focus(nvim: Nvim, stack: Stack) -> None:
    async def cont() -> None:
        snap = await snapshot(stack.settings.match.unifying_chars)
        await stack.tmdb.periodical(snap)

    go(nvim, aw=cont())


autocmd("FocusGained") << f"lua {NAMESPACE}.{_on_focus.name}()"
Beispiel #16
0
def _op_rg(nvim: Nvim, visual: VisualTypes) -> None:
    text = _hl_selected(nvim, visual=visual)
    escaped = escape(text).replace(r"\ ", " ")
    cont = lambda: nvim.command(f"Rg {escaped}")
    go(nvim, aw=async_call(nvim, cont))
Beispiel #17
0
 async def cont() -> None:
     async for _ in aticker(3, immediately=False):
         go(async_call(nvim, check))
Beispiel #18
0
def _on_focus(nvim: Nvim, stack: Stack) -> None:
    async def cont() -> None:
        snap = await snapshot(stack.settings.match.unifying_chars)
        await stack.tmdb.periodical(snap)

    go(nvim, aw=cont())
Beispiel #19
0
def _load_snips(nvim: Nvim, stack: Stack) -> None:
    go(nvim,
       aw=_slurp(nvim, stack=stack, warn=stack.settings.clients.snippets.warn))
Beispiel #20
0
 def cont() -> None:
     new_col = col + len(lhs.encode())
     nvim.api.set_vvar("char", lhs + cast(str, rhs))
     set_cur = lambda: win_set_cursor(
         nvim, win=win, row=row, col=new_col)
     go(async_call(nvim, set_cur))
Beispiel #21
0
                assert False

        def cont() -> None:
            if doc:
                _show_preview(
                    nvim,
                    stack=stack,
                    event=event,
                    doc=doc,
                    s=state,
                    preview_id=state.preview_id,
                )

        await async_call(nvim, cont)

    _TASK = cast(Task, go(nvim, aw=cont()))


def _virt_text(nvim: Nvim, ghost: GhostText, text: str) -> None:
    if ghost.enabled:
        lhs, rhs = ghost.context
        overlay, *_ = text.splitlines() or ("", )
        virt_text = lhs + overlay + rhs

        ns = create_ns(nvim, ns=_NS)
        win = cur_win(nvim)
        buf = win_get_buf(nvim, win=win)
        row, col = win_get_cursor(nvim, win=win)
        mark = ExtMark(
            idx=1,
            begin=(row, col),
Beispiel #22
0
def _op_fzf(nvim: Nvim, visual: VisualTypes) -> None:
    text = _hl_selected(nvim, visual=visual)
    cont = lambda: nvim.command(f"BLines {text}")
    go(nvim, aw=async_call(nvim, cont))
Beispiel #23
0
def _op_rg(nvim: Nvim, visual: VisualTypes = None) -> None:
    text = _hl_selected(nvim, visual=visual)
    cont = lambda: nvim.command(f"Rg {text}")
    go(async_call(nvim, cont))
Beispiel #24
0
def snips(nvim: Nvim, stack: Stack, args: Sequence[str]) -> None:
    buf = cur_buf(nvim)
    ft = buf_filetype(nvim, buf=buf)

    try:
        ns = _parse_args(args, filetype=ft or "*")
    except ArgparseError as e:
        write(nvim, e, error=True)

    else:
        if ns.action == "ls":
            cwd = get_cwd(nvim)

            async def c1() -> None:
                _, mtimes = await user_mtimes(
                    nvim, user_path=stack.settings.clients.snippets.user_path
                )
                preview = tuple(
                    fmt_path(cwd, path=path, is_dir=False)
                    for path in sorted(mtimes, key=pathsort_key)
                )

                def cont() -> None:
                    if mtimes:
                        set_preview(nvim, syntax="", preview=preview)
                    else:
                        write(nvim, LANG("no snippets found"))

                await async_call(nvim, cont)

            go(nvim, aw=c1())

        elif ns.action == "cd":

            async def c2() -> None:
                paths = await snippet_paths(
                    nvim, user_path=stack.settings.clients.snippets.user_path
                )
                if paths:
                    path, *_ = paths
                    path.mkdir(parents=True, exist_ok=True)
                    await async_call(nvim, lambda: chdir(nvim, path))
                else:
                    assert False

            go(nvim, aw=c2())

        elif ns.action == "compile":

            async def c3() -> None:
                await awrite(nvim, LANG("waiting..."))
                try:
                    await compile_user_snippets(nvim, stack=stack)
                except (LoadError, ParseError) as e:
                    preview = str(e).splitlines()

                    def cont() -> None:
                        set_preview(nvim, syntax="", preview=preview)
                        write(nvim, LANG("snip parse fail"))

                    await async_call(nvim, cont)
                else:
                    await awrite(nvim, LANG("snip parse succ"))

            go(nvim, aw=c3())

        elif ns.action == "edit":

            async def c4() -> None:
                paths, mtimes = await user_mtimes(
                    nvim, user_path=stack.settings.clients.snippets.user_path
                )
                path, *_ = paths
                exts = {path.stem: path for path in mtimes}
                snip_path = exts.get(ns.filetype, path / f"{ns.filetype}.snip")
                snip_path.parent.mkdir(parents=True, exist_ok=True)

                def cont() -> None:
                    escaped = nvim.funcs.fnameescape(normcase(snip_path))
                    nvim.feedkeys(f":edit {escaped}", "n", False)

                await async_call(nvim, cont)

            go(nvim, aw=c4())

        else:
            assert False
Beispiel #25
0
 def __init__(
     self, supervisor: Supervisor, options: WordbankClient, misc: TMDB
 ) -> None:
     super().__init__(supervisor, options=options, misc=misc)
     go(supervisor.nvim, aw=self._poll())
Beispiel #26
0
 def cont() -> None:
     go(async_call(nvim, nvim.command, "silent! wa!"))
Beispiel #27
0
    def notify_idle(self) -> None:
        async def cont() -> None:
            async with self.idling:
                self.idling.notify_all()

        go(self.nvim, aw=cont())