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())
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))
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())
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())
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())
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())
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())
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")
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())
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)), )
def __init__( self, supervisor: Supervisor, options: BuffersClient, misc: BDB ) -> None: super().__init__(supervisor, options=options, misc=misc) go(supervisor.nvim, aw=self._poll())
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())
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())
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)
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}()"
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))
async def cont() -> None: async for _ in aticker(3, immediately=False): go(async_call(nvim, check))
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())
def _load_snips(nvim: Nvim, stack: Stack) -> None: go(nvim, aw=_slurp(nvim, stack=stack, warn=stack.settings.clients.snippets.warn))
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))
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),
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))
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))
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
def __init__( self, supervisor: Supervisor, options: WordbankClient, misc: TMDB ) -> None: super().__init__(supervisor, options=options, misc=misc) go(supervisor.nvim, aw=self._poll())
def cont() -> None: go(async_call(nvim, nvim.command, "silent! wa!"))
def notify_idle(self) -> None: async def cont() -> None: async with self.idling: self.idling.notify_all() go(self.nvim, aw=cont())