def _show_file(nvim: Nvim, *, state: State, settings: Settings, click_type: ClickType) -> None: if click_type is ClickType.tertiary: nvim.api.command("tabnew") win = cur_win(nvim) for key, val in settings.win_actual_opts.items(): win_set_option(nvim, win=win, key=key, val=val) path = state.current if path: hold = click_type is ClickType.secondary mgr = hold_win_pos(nvim) if hold else nullcontext() with mgr: non_fm_windows = tuple( find_non_fm_windows_in_tab(nvim, last_used=state.window_order)) buf = next(find_buffers_with_file(nvim, file=path), None) win = next( chain( find_window_with_file_in_tab( nvim, last_used=state.window_order, file=path), non_fm_windows, ), None, ) or new_window( nvim, last_used=state.window_order, win_local=settings.win_actual_opts, open_left=not settings.open_left, width=None if len(non_fm_windows) else nvim.options["columns"] - state.width - 1, ) set_cur_win(nvim, win=win) non_fm_count = len(non_fm_windows) if click_type is ClickType.v_split and non_fm_count: nvim.api.command("vnew") temp_buf = cur_buf(nvim) buf_set_option(nvim, buf=temp_buf, key="bufhidden", val="wipe") elif click_type is ClickType.h_split and non_fm_count: nvim.api.command("new") temp_buf = cur_buf(nvim) buf_set_option(nvim, buf=temp_buf, key="bufhidden", val="wipe") win = cur_win(nvim) if buf is None: escaped = nvim.funcs.fnameescape(normcase(path)) nvim.command(f"edit! {escaped}") else: win_set_buf(nvim, win=win, buf=buf) resize_fm_windows(nvim, last_used=state.window_order, width=state.width) nvim.api.command("filetype detect")
def _show_file( nvim: Nvim, *, state: State, settings: Settings, click_type: ClickType ) -> None: if click_type is ClickType.tertiary: nvim.api.command("tabnew") path = state.current if path: hold = click_type is ClickType.secondary mgr = hold_win_pos(nvim) if hold else nullcontext() with mgr: non_fm_windows = tuple(find_non_fm_windows_in_tab(nvim)) buf = next(find_buffers_with_file(nvim, file=path), None) win = next( chain( find_window_with_file_in_tab(nvim, file=path), (win for win in non_fm_windows if _win_nochange(nvim, win=win)), ), None, ) or new_window( nvim, open_left=not settings.open_left, width=None if len(non_fm_windows) else nvim.options["columns"] - state.width - 1, ) set_cur_win(nvim, win=win) non_fm_count = len(non_fm_windows) if click_type is ClickType.v_split and non_fm_count: nvim.api.command("vnew") temp_buf = cur_buf(nvim) buf_set_option(nvim, buf=temp_buf, key="bufhidden", val="wipe") elif click_type is ClickType.h_split and non_fm_count: nvim.api.command("new") temp_buf = cur_buf(nvim) buf_set_option(nvim, buf=temp_buf, key="bufhidden", val="wipe") win = cur_win(nvim) if buf is None: nvim.command(f"edit {path}") else: win_set_buf(nvim, win=win, buf=buf) resize_fm_windows(nvim, state.width) nvim.api.command("filetype detect")
def _detect_tabs(nvim: Nvim) -> None: buf = cur_buf(nvim) count = buf_line_count(nvim, buf=buf) rows = min(count, 100) lines = buf_get_lines(nvim, buf=buf, lo=0, hi=rows) _set_tabsize(nvim, buf=buf, lines=lines) _set_usetab(nvim, buf=buf, lines=lines)
def _go_replace(nvim: Nvim, visual: VisualTypes) -> None: buf = cur_buf(nvim) if not writable(nvim, buf=buf): return else: linefeed = buf_linefeed(nvim, buf=buf) (r1, c1), (r2, c2) = operator_marks(nvim, buf=buf, visual_type=visual) lines = buf_get_lines(nvim, buf=buf, lo=r1, hi=r2 + 1) if len(lines) > 1: h, *_, t = lines else: h, *_ = t, *_ = lines begin = (r1, min(c1, max(0, len(encode(h)) - 1))) end = (r2, min(len(encode(t)), c2 + 1)) text: str = nvim.funcs.getreg() new_lines = text.split(linefeed) if new_lines: n = new_lines.pop() if n: new_lines.append(n) nvim.options["undolevels"] = nvim.options["undolevels"] buf_set_text(nvim, buf=buf, begin=begin, end=end, text=new_lines)
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 _buf_enter(nvim: Nvim, stack: Stack) -> None: state(commit_id=uuid4()) with suppress(NvimError): buf = cur_buf(nvim) listed = buf_get_option(nvim, buf=buf, key="buflisted") buf_type: str = buf_get_option(nvim, buf=buf, key="buftype") if listed and buf_type != "terminal": nvim.api.buf_attach(buf, True, {})
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()
def current_ctx(nvim: Nvim) -> Tuple[str, BufContext]: cwd = get_cwd(nvim) buf = cur_buf(nvim) filename = buf_name(nvim, buf=buf) filetype = buf_filetype(nvim, buf=buf) tabsize: int = buf_get_option(nvim, buf=buf, key="tabstop") lines: Sequence[str] = buf_get_lines(nvim, buf=buf, lo=0, hi=-1) return cwd, BufContext( buf=buf, filename=filename, filetype=filetype, tabsize=tabsize, lines=lines )
def _kill_win(nvim: Nvim, stack: Stack, reset: bool) -> None: if reset: state(pum_location=None, preview_id=uuid4()) buf = cur_buf(nvim) ns = create_ns(nvim, ns=_NS) clear_ns(nvim, buf=buf, id=ns) for win in _ls(nvim): win_close(nvim, win=win)
def _sort_lines(nvim: Nvim, visual: VisualTypes) -> None: buf = cur_buf(nvim) if not writable(nvim, buf=buf): return else: (row1, _), (row2, _) = operator_marks(nvim, buf=buf, visual_type=visual) lines = buf_get_lines(nvim, buf=buf, lo=row1, hi=row2 + 1) new_lines = sorted(lines, key=strxfrm) buf_set_lines(nvim, buf=buf, lo=row1, hi=row2 + 1, lines=new_lines)
def _comment(nvim: Nvim, visual: VisualTypes) -> None: buf = cur_buf(nvim) if not writable(nvim, buf=buf): return else: (row1, _), (row2, _) = operator_marks(nvim, buf=buf, visual_type=visual) lines = buf_get_lines(nvim, buf=buf, lo=row1, hi=row2 + 1) lhs, rhs = buf_commentstr(nvim, buf=buf) new_lines = _toggle_comment(lhs, rhs, lines=lines) buf_set_lines(nvim, buf=buf, lo=row1, hi=row2 + 1, lines=new_lines)
def _insert_enter(nvim: Nvim, stack: Stack) -> None: ts = stack.settings.clients.tree_sitter nono_bufs = state().nono_bufs buf = cur_buf(nvim) async def cont() -> None: if ts.enabled and buf.number not in nono_bufs: if payload := await async_request(nvim, 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)
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())
def find_current_buffer_path(nvim: Nvim) -> Optional[PurePath]: buf = cur_buf(nvim) name = buf_name(nvim, buf=buf) return resolve_path(None, path=name)
def _new_tab(nvim: Nvim) -> None: nvim.command("tabnew") buf = cur_buf(nvim) buf_set_var(nvim, buf=buf, key="buftype", val="nofile")
def _op_sd(nvim: Nvim, visual: VisualTypes) -> None: buf = cur_buf(nvim) selected = _get_selected(nvim, buf=buf, visual_type=visual) escaped = _magic_escape(selected) instruction = rf":%s/\V{escaped}//g<left><left>" nvim.api.input(instruction)
def _hl_selected(nvim: Nvim, visual: VisualTypes) -> str: buf = cur_buf(nvim) selected = _get_selected(nvim, buf=buf, visual_type=visual) _hl_text(nvim, text=selected) return selected
def _detect_tabs(nvim: Nvim) -> None: buf = cur_buf(nvim) detect_tabs(nvim, buf=buf)
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 find_current_buffer_name(nvim: Nvim) -> str: buf = cur_buf(nvim) name = buf_name(nvim, buf=buf) return name