Beispiel #1
0
def trailing_ws(nvim: Nvim) -> None:
    win = cur_win(nvim)
    buf = win_get_buf(nvim, win=win)
    if not writable(nvim, buf=buf):
        return
    else:
        _set_trimmed(nvim, win=win, buf=buf)
Beispiel #2
0
 def it() -> Iterator[Tuple[Window, Tuple[int, int]]]:
     wins = list_wins(nvim)
     for win in wins:
         buf = win_get_buf(nvim, win=win)
         if buf == ctx.buf:
             row, col = win_get_cursor(nvim, win)
             yield win, (row, col)
Beispiel #3
0
def _word(nvim: Nvim, is_inside: bool) -> None:
    win = cur_win(nvim)
    buf = win_get_buf(nvim, win=win)

    row, c = win_get_cursor(nvim, win=win)
    lines = buf_get_lines(nvim, buf=buf, lo=row, hi=row + 1)
    line = next(iter(lines))
    bline = line.encode()

    # position under cursor
    c = min(len(bline) - 1, c)
    col = len(bline[:c].decode()) + 1
    lhs, rhs = line[:col], line[col:]
    # undo col + 1
    offset = len(next(reversed(lhs), "").encode())

    ctx = gen_split(lhs, rhs, unifying_chars=UNIFIYING_CHARS)
    if not (ctx.word_lhs + ctx.word_rhs):
        words_lhs, words_rhs = ctx.syms_lhs, ctx.syms_rhs
    else:
        words_lhs, words_rhs = ctx.word_lhs, ctx.word_rhs

    c_lhs = c + offset - len(words_lhs.encode())
    c_rhs = c + offset + len(words_rhs.encode()) - 1

    if is_inside:
        mark1 = (row, c_lhs)
        mark2 = (row, c_rhs)
    else:
        mark1 = (row, c_lhs - 1)
        mark2 = (row, c_rhs + 1)

    set_visual_selection(nvim, win=win, mode="v", mark1=mark1, mark2=mark2)
Beispiel #4
0
def new_window(
    nvim: Nvim,
    *,
    last_used: Mapping[int, None],
    win_local: Mapping[str, Union[bool, str]],
    open_left: bool,
    width: Optional[int],
) -> Window:
    split_r = nvim.options["splitright"]

    wins = tuple(
        find_windows_in_tab(nvim, last_used=last_used, no_secondary=False))
    focus_win = wins[0] if open_left else wins[-1]
    direction = False if open_left else True

    nvim.options["splitright"] = direction
    set_cur_win(nvim, win=focus_win)
    nvim.command(f"{width}vnew" if width else "vnew")
    nvim.options["splitright"] = split_r

    win = cur_win(nvim)
    buf = win_get_buf(nvim, win)
    for key, val in win_local.items():
        win_set_option(nvim, win=win, key=key, val=val)
    buf_set_option(nvim, buf=buf, key="bufhidden", val="wipe")
    return win
Beispiel #5
0
def _word(nvim: Nvim, is_inside: bool) -> None:
    win = cur_win(nvim)
    buf = win_get_buf(nvim, win=win)

    row, col = win_get_cursor(nvim, win=win)
    line, *_ = buf_get_lines(nvim, buf=buf, lo=row, hi=row + 1)

    bline = encode(line)
    lhs, rhs = decode(bline[:col]), decode(bline[col:])
    ctx = gen_split(lhs, rhs, unifying_chars=UNIFIYING_CHARS)

    if not (ctx.word_lhs + ctx.word_rhs):
        words_lhs, words_rhs = ctx.syms_lhs, ctx.syms_rhs
    else:
        words_lhs, words_rhs = ctx.word_lhs, ctx.word_rhs

    c_lhs = max(col - len(encode(words_lhs)), 0)
    c_rhs = max(col + len(encode(words_rhs)) - 1, 0)

    if is_inside:
        mark1 = (row, c_lhs)
        mark2 = (row, c_rhs)
    else:
        mark1 = (row, max(0, c_lhs - 1))
        mark2 = (row, min(len(bline), c_rhs + 1))

    set_visual_selection(nvim, win=win, mode="v", mark1=mark1, mark2=mark2)
Beispiel #6
0
def kill_buffers(
    nvim: Nvim,
    last_used: Mapping[int, None],
    paths: AbstractSet[PurePath],
    reopen: Mapping[PurePath, PurePath],
) -> None:
    active = ({
        win_get_buf(nvim, win=win): win
        for win in find_non_fm_windows_in_tab(
            nvim,
            last_used=last_used,
        )
    } if reopen else {})

    for buf in list_bufs(nvim, listed=True):
        name = PurePath(buf_name(nvim, buf=buf))
        buf_paths = ancestors(name) | {name}

        if not buf_paths.isdisjoint(paths):
            win = active.get(buf)
            new_path = reopen.get(name)
            if reopen and win and new_path:
                p = Path(name)
                p.touch()
                with hold_win_pos(nvim):
                    set_cur_win(nvim, win=win)
                    escaped = nvim.funcs.fnameescape(normcase(new_path))
                    nvim.command(f"edit! {escaped}")
                    p.unlink(missing_ok=True)
            buf_close(nvim, buf=buf)
Beispiel #7
0
def _surround(nvim: Nvim) -> None:
    lhs: str = nvim.vvars["char"]
    rhs = _CHAR_PAIRS.get(lhs)

    if rhs:
        win = cur_win(nvim)
        buf = win_get_buf(nvim, win=win)
        row, col = win_get_cursor(nvim, win=win)
        lines = buf_get_lines(nvim, buf=buf, lo=row, hi=row + 1)
        line = next(iter(lines))

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

        if rhs == lhs:
            is_even = line.count(lhs) % 2 == 0
            if is_even:
                cont()
        else:
            counts = Counter(line)
            if counts[lhs] >= counts[rhs]:
                cont()
Beispiel #8
0
def _restore_pos(nvim: Nvim) -> None:
    win = cur_win(nvim)
    buf = win_get_buf(nvim, win=win)
    row, _ = win_get_cursor(nvim, win=win)
    pos: Optional[int] = buf_get_var(nvim, buf=buf, key=BUF_VAR_NAME)

    if pos is not None:
        win_set_cursor(nvim, win=win, row=row, col=pos)
Beispiel #9
0
def find_non_fm_windows_in_tab(
        nvim: Nvim, last_used: Mapping[int, None]) -> Iterator[Window]:
    for win in find_windows_in_tab(nvim,
                                   last_used=last_used,
                                   no_secondary=True):
        buf = win_get_buf(nvim, win=win)
        if not is_fm_buffer(nvim, buf=buf):
            yield win
Beispiel #10
0
def _entire(nvim: Nvim) -> None:
    win = cur_win(nvim)
    buf = win_get_buf(nvim, win=win)
    count = buf_line_count(nvim, buf=buf)
    last_line, *_ = buf_get_lines(nvim, buf=buf, lo=-2, hi=-1)
    mark1 = (0, 0)
    mark2 = (count - 1, len(encode(last_line)))
    set_visual_selection(nvim, win=win, mode="V", mark1=mark1, mark2=mark2)
Beispiel #11
0
def find_window_with_file_in_tab(nvim: Nvim, last_used: Mapping[int, None],
                                 file: PurePath) -> Iterator[Window]:
    for win in find_windows_in_tab(nvim,
                                   last_used=last_used,
                                   no_secondary=True):
        buf = win_get_buf(nvim, win=win)
        name = PurePath(buf_name(nvim, buf=buf))
        if name == file:
            yield win
Beispiel #12
0
def _resize_secondary(nvim: Nvim) -> None:
    tab = cur_tab(nvim)
    wins = tab_list_wins(nvim, tab=tab)
    height = nvim.options["previewheight"]

    for win in wins:
        is_preview: bool = win_get_option(nvim, win=win, key="previewwindow")
        buf = win_get_buf(nvim, win=win)
        ft = buf_filetype(nvim, buf=buf)
        if is_preview or ft == "qf":
            nvim.api.win_set_height(win, height)
Beispiel #13
0
def _comment_single(nvim: Nvim) -> None:
    win = cur_win(nvim)
    buf = win_get_buf(nvim, win=win)
    if not writable(nvim, buf=buf):
        return
    else:
        row, _ = win_get_cursor(nvim, win=win)
        lines = buf_get_lines(nvim, buf=buf, lo=row, hi=row + 1)
        lhs, rhs = buf_commentstr(nvim, buf=buf)
        new_lines = _toggle_comment(lhs, rhs, lines=lines)
        buf_set_lines(nvim, buf=buf, lo=row, hi=row + 1, lines=new_lines)
Beispiel #14
0
def preview_preview(nvim: Nvim, stack: Stack, *_: str) -> str:
    win = next(_ls(nvim), None)
    if win:
        buf = win_get_buf(nvim, win=win)
        syntax = buf_get_option(nvim, buf=buf, key="syntax")
        lines = buf_get_lines(nvim, buf=buf, lo=0, hi=-1)
        nvim.exec_lua(f"{NAMESPACE}.{_bigger_preview.name}(...)",
                      (syntax, lines))

    escaped: str = nvim.api.replace_termcodes("<c-e>", True, False, True)
    return escaped
Beispiel #15
0
def _line(nvim: Nvim, is_inside: bool) -> None:
    win = cur_win(nvim)
    buf = win_get_buf(nvim, win=win)
    row, _ = win_get_cursor(nvim, win=win)
    lines = buf_get_lines(nvim, buf=buf, lo=row, hi=row + 1)
    line = next(iter(lines))
    lhs, rhs = (_p_inside if is_inside else _p_around)(line)

    set_visual_selection(nvim,
                         win=win,
                         mode="v",
                         mark1=(row, lhs),
                         mark2=(row, rhs))
Beispiel #16
0
def _rename(nvim: Nvim) -> None:
    win = cur_win(nvim)
    buf = win_get_buf(nvim, win=win)
    row, col = win_get_cursor(nvim, win=win)
    line, *_ = buf_get_lines(nvim, buf=buf, lo=row, hi=row + 1)
    b_line = encode(line)
    lhs, rhs = decode(b_line[:col]), decode(b_line[col:])
    split = gen_split(lhs=lhs, rhs=rhs, unifying_chars=UNIFIYING_CHARS)
    word = split.word_lhs + split.word_rhs
    ans = ask(nvim, question=LANG("rename: "), default=word)

    if ans:
        nvim.lua.vim.lsp.buf.rename(ans)
Beispiel #17
0
def eval_snips(
    nvim: Nvim,
    stack: Stack,
    visual: bool,
    maybe_grammar: str = REPL_GRAMMAR,
) -> None:
    try:
        grammar = SnippetGrammar[maybe_grammar]
    except KeyError:
        grammar = SnippetGrammar.lsp
        log.warn("%s", "bad snippet grammar -- reverting to LSP")

    win = cur_win(nvim)
    buf = win_get_buf(nvim, win=win)
    line_count = buf_line_count(nvim, buf=buf)
    path = PurePath(normcase(buf_name(nvim, buf=buf)))
    comment_str = buf_commentstr(nvim, buf=buf)
    clipboard = nvim.funcs.getreg()
    info = ParseInfo(visual="", clipboard=clipboard, comment_str=comment_str)

    if visual:
        (lo, _), (hi, _) = operator_marks(nvim, buf=buf, visual_type=None)
        hi = min(line_count, hi + 1)
    else:
        lo, hi = 0, line_count

    lines = buf_get_lines(nvim, buf=buf, lo=lo, hi=hi)

    try:
        compiled = compile_one(
            stack,
            grammar=grammar,
            path=path,
            info=info,
            lines=enumerate(lines, start=lo + 1),
        )
    except (LoadError, ParseError) as e:
        preview = str(e).splitlines()
        with hold_win_pos(nvim, win=win):
            set_preview(nvim, syntax="", preview=preview)
        write(nvim, LANG("snip parse fail"))

    else:
        preview = _pprn(compiled).splitlines()
        with hold_win_pos(nvim, win=win):
            set_preview(nvim, syntax="yaml", preview=preview)
        if preview:
            write(nvim, LANG("snip parse succ"))
        else:
            write(nvim, LANG("no snippets found"))
Beispiel #18
0
def _toggle_qf(nvim: Nvim) -> None:
    tab = cur_tab(nvim)
    wins = tab_list_wins(nvim, tab=tab)
    closed = False
    for win in wins:
        buf = win_get_buf(nvim, win=win)
        ft = buf_filetype(nvim, buf=buf)
        if ft == "qf":
            win_close(nvim, win=win)
            closed = True
    if not closed:
        nvim.command("copen")
        win = cur_win(nvim)
        height = nvim.options["previewheight"]
        nvim.api.win_set_height(win, height)
Beispiel #19
0
def _norm_mv(nvim: Nvim, up: bool) -> None:
    win = cur_win(nvim)
    buf = win_get_buf(nvim, win=win)
    row, _ = win_get_cursor(nvim, win=win)
    lines = buf_line_count(nvim, buf=buf)

    if not writable(nvim, buf=buf):
        return
    else:
        if up:
            if row:
                nvim.command(f"move -2")
        else:
            if row < lines - 1:
                nvim.command(f"move +1")
Beispiel #20
0
def _toggle_case(nvim: Nvim) -> None:
    win = cur_win(nvim)
    row, col = win_get_cursor(nvim, win=win)
    buf = win_get_buf(nvim, win=win)
    if writable(nvim, buf=buf):
        line, *_ = buf_get_lines(nvim, buf=buf, lo=row, hi=row + 1)
        bline = encode(line)
        before, after = bline[:col], bline[col:]
        if after:
            cur, *post = after
            pt = decode(bytes((cur, )))
            swapped = _swap_case(pt)
            new = decode(before) + swapped + decode(bytes(post))
            pos = len(before) + len(encode(swapped))
            buf_set_lines(nvim, buf=buf, lo=row, hi=row + 1, lines=(new, ))
            win_set_cursor(nvim, win=win, row=row, col=pos)
Beispiel #21
0
def _go_replace_line(nvim: Nvim) -> None:
    win = cur_win(nvim)
    buf = win_get_buf(nvim, win=win)
    if not writable(nvim, buf=buf):
        return
    else:
        linefeed = buf_linefeed(nvim, buf=buf)
        row, _ = win_get_cursor(nvim, win=win)
        body: str = nvim.funcs.getreg()
        new_lines = body.split(linefeed)
        if new_lines:
            n = new_lines.pop()
            if n:
                new_lines.append(n)

        buf_set_lines(nvim, buf=buf, lo=row, hi=row + 1, lines=new_lines)
Beispiel #22
0
def new_window(nvim: Nvim, *, open_left: bool, width: Optional[int]) -> Window:
    split_r = nvim.options["splitright"]

    wins = tuple(find_windows_in_tab(nvim, no_secondary=False))
    focus_win = wins[0] if open_left else wins[-1]
    direction = False if open_left else True

    nvim.options["splitright"] = direction
    set_cur_win(nvim, win=focus_win)
    nvim.command(f"{width}vnew" if width else "vnew")
    nvim.options["splitright"] = split_r

    win = cur_win(nvim)
    buf = win_get_buf(nvim, win)
    buf_set_option(nvim, buf=buf, key="bufhidden", val="wipe")
    return win
Beispiel #23
0
def _toggle_case(nvim: Nvim) -> None:
    win = cur_win(nvim)
    row, col = win_get_cursor(nvim, win=win)
    buf = win_get_buf(nvim, win=win)
    if not writable(nvim, buf=buf):
        return
    else:
        line, *_ = buf_get_lines(nvim, buf=buf, lo=row, hi=row + 1)
        bline = line.encode()
        before, after = bline[:col], bline[col:]
        cur, *post = after
        pt = bytes((cur,)).decode()
        swapped = _swap_case(pt)
        new = before.decode() + swapped + bytes(post).decode()
        pos = len(before) + len(swapped.encode())
        buf_set_lines(nvim, buf=buf, lo=row, hi=row + 1, lines=(new,))
        win_set_cursor(nvim, win=win, row=row, col=pos)
Beispiel #24
0
def _indent(nvim: Nvim) -> None:
    win = cur_win(nvim)
    buf = win_get_buf(nvim, win)
    row, _ = win_get_cursor(nvim, win)
    tabsize: int = buf_get_option(nvim, buf=buf, key="tabstop")

    lines = buf_get_lines(nvim, buf=buf, lo=0, hi=-1)
    before, curr, after = lines[:row], lines[row], lines[row + 1:]
    init_lv = p_indent(curr, tabsize=tabsize)

    top = row - _p_inside(init_lv, tabsize=tabsize, lines=reversed(before))
    btm = row + _p_inside(init_lv, tabsize=tabsize, lines=after)

    set_visual_selection(nvim,
                         win=win,
                         mode="V",
                         mark1=(top, 0),
                         mark2=(btm, 0))
Beispiel #25
0
def find_windows_in_tab(nvim: Nvim, no_secondary: bool) -> Iterator[Window]:
    def key_by(win: Window) -> Tuple[int, int]:
        """
        -> sort by row, then col
        """

        row, col = nvim.funcs.win_screenpos(win.number)
        return col, row

    tab = cur_tab(nvim)
    wins = tab_list_wins(nvim, tab=tab)

    for win in sorted(wins, key=key_by):
        is_preview: bool = win_get_option(nvim, win=win, key="previewwindow")
        buf = win_get_buf(nvim, win)
        ft = buf_filetype(nvim, buf=buf)
        is_secondary = is_preview or ft == "qf"
        if not is_secondary or not no_secondary:
            yield win
Beispiel #26
0
def _indent(nvim: Nvim) -> None:
    win = cur_win(nvim)
    buf = win_get_buf(nvim, win)
    row, _ = win_get_cursor(nvim, win)
    tabsize: int = buf_get_option(nvim, buf=buf, key="tabstop")

    lines = buf_get_lines(nvim, buf=buf, lo=0, hi=-1)
    before, curr, after = lines[:row], lines[row], lines[row + 1:]
    init_lv = p_indent(curr, tabsize=tabsize)

    top = row - _p_inside(init_lv, tabsize=tabsize, lines=reversed(before))
    btm = row + _p_inside(init_lv, tabsize=tabsize, lines=after)

    lines = deque(buf_get_lines(nvim, buf=buf, lo=top, hi=btm + 1))
    while lines:
        if line := lines.popleft():
            lines.appendleft(line)
            break
        else:
            top += 1
Beispiel #27
0
def nav_mark(nvim: Nvim, stack: Stack) -> None:
    ns = create_ns(nvim, ns=NS)
    win = cur_win(nvim)
    buf = win_get_buf(nvim, win=win)

    if marks := deque(_marks(nvim, ns=ns, win=win, buf=buf)):
        mark = marks.popleft()

        def single() -> None:
            _single_mark(nvim, mark=mark, marks=marks, ns=ns, win=win, buf=buf)

        if linked := tuple(m for m in marks if m.idx == mark.idx):
            edited = _linked_marks(nvim,
                                   mark=mark,
                                   linked=linked,
                                   ns=ns,
                                   win=win,
                                   buf=buf)
            if not edited:
                single()
Beispiel #28
0
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),
            end=(row, col),
            meta={
                "virt_text_pos": "overlay",
                "hl_mode": "combine",
                "virt_text": ((virt_text, ghost.highlight_group), ),
            },
        )
        clear_ns(nvim, buf=buf, id=ns)
        buf_set_extmarks(nvim, buf=buf, id=ns, marks=(mark, ))
Beispiel #29
0
def indices(nvim: Nvim, state: State, is_visual: bool) -> Iterator[Node]:
    win = cur_win(nvim)
    buf = win_get_buf(nvim, win=win)

    if not is_fm_buffer(nvim, buf=buf):
        return None
    else:
        row, _ = win_get_cursor(nvim, win=win)
        node = _row_index(state, row)
        if node:
            yield node

        if is_visual:
            (row1, _), (row2, _) = operator_marks(nvim,
                                                  buf=buf,
                                                  visual_type=None)

            for r in range(row1, row2 + 1):
                if r != row:
                    node = _row_index(state, r)
                    if node:
                        yield node
Beispiel #30
0
def _visual_mv(nvim: Nvim, up: bool) -> None:
    win = cur_win(nvim)
    buf = win_get_buf(nvim, win=win)
    (row1, col1), (row2, col2) = operator_marks(nvim,
                                                buf=buf,
                                                visual_type=None)
    lines = buf_line_count(nvim, buf=buf)

    if not writable(nvim, buf=buf):
        return
    else:
        if up:
            if row1 <= 0:
                nvim.command("norm! gv")
            else:
                nvim.command(f"{row1+1},{row2+1}move {row1-1}")
                set_visual_selection(
                    nvim,
                    win=win,
                    mode="v",
                    mark1=(row1 - 1, col1),
                    mark2=(row2 - 1, col2),
                    reverse=True,
                )

        else:
            if row2 >= lines - 1:
                nvim.command("norm! gv")
            else:
                nvim.command(f"{row1+1},{row2+1}move {row2+2}")
                set_visual_selection(
                    nvim,
                    win=win,
                    mode="v",
                    mark1=(row1 + 1, col1),
                    mark2=(row2 + 1, col2),
                )