Exemple #1
0
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")
Exemple #2
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()
Exemple #3
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
Exemple #4
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)
Exemple #5
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)
Exemple #6
0
def _open_fm_window(nvim: Nvim, settings: Settings, opts: _Args,
                    width: int) -> None:
    cwin = cur_win(nvim)
    win = next(find_fm_windows_in_tab(nvim), None)
    if win:
        if opts.toggle:
            wins = list_wins(nvim)
            if len(wins) > 1:
                win_close(nvim, win=win)
        else:
            set_cur_win(nvim, win=win)
    else:
        buf = next(find_fm_buffers(nvim), None)
        if buf is None:
            buf = new_fm_buffer(nvim, settings=settings)

        win = new_window(
            nvim,
            win_local=settings.win_actual_opts,
            open_left=settings.open_left,
            width=width,
        )
        for key, val in settings.win_local_opts.items():
            win_set_option(nvim, win=win, key=key, val=val)
        win_set_buf(nvim, win=win, buf=buf)

        _ensure_side_window(nvim, window=win, settings=settings, width=width)
        if not opts.focus:
            set_cur_win(nvim, win=cwin)
Exemple #7
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)
Exemple #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)
Exemple #9
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)
Exemple #10
0
def toggle_floating(nvim: Nvim, *args: str) -> None:
    curr_win = cur_win(nvim)
    float_wins = frozenset(list_floatwins(nvim))
    if curr_win in float_wins:
        for win in float_wins:
            win_close(nvim, win=win)
    else:
        _term_open(nvim, *args)
Exemple #11
0
def _new_window(nvim: Nvim, vertical: bool) -> None:
    nvim.command("vnew" if vertical else "new")
    win = cur_win(nvim)
    buf = create_buf(nvim,
                     listed=False,
                     scratch=True,
                     wipe=True,
                     nofile=True,
                     noswap=True)
    win_set_buf(nvim, win=win, buf=buf)
Exemple #12
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)
Exemple #13
0
def _resize(
    nvim: Nvim, state: State, settings: Settings, direction: Callable[[int, int], int]
) -> Optional[Stage]:
    win = cur_win(nvim)
    if not is_fm_window(nvim, win=win):
        return None
    else:
        w_width = win.width
        width = max(direction(w_width, 10), 1)
        new_state = forward(state, settings=settings, width=width)
        resize_fm_windows(nvim, width=new_state.width)
        return Stage(new_state)
Exemple #14
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)
Exemple #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))
Exemple #16
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"))
Exemple #17
0
def _toggle_preview(nvim: Nvim) -> None:
    tab = cur_tab(nvim)
    wins = tab_list_wins(nvim, tab=tab)
    closed = False
    for win in wins:
        is_preview: bool = win_get_option(nvim, win=win, key="previewwindow")
        if is_preview:
            win_close(nvim, win=win)
            closed = True
    if not closed:
        nvim.command("new")
        win = cur_win(nvim)
        win_set_option(nvim, win=win, key="previewwindow", val=True)
        height = nvim.options["previewheight"]
        nvim.api.win_set_height(win, height)
Exemple #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)
Exemple #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")
Exemple #20
0
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")
Exemple #21
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)
Exemple #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
Exemple #23
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)
Exemple #24
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)
Exemple #25
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))
Exemple #26
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()
Exemple #27
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
Exemple #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, ))
Exemple #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
Exemple #30
0
def redraw(nvim: Nvim, state: State, focus: Optional[str]) -> None:
    derived, current = state.derived, state.current
    focus_row = derived.path_row_lookup.get(focus) if focus else None
    current_row = derived.path_row_lookup.get(current or "")

    cwin = cur_win(nvim)
    ns = nvim.api.create_namespace(FM_NAMESPACE)

    for win, buf in find_fm_windows(nvim):
        p_count = buf_line_count(nvim, buf=buf)
        n_count = len(state.derived.lines)
        row, col = win_get_cursor(nvim, win=win)
        (r1, c1), (r2, c2) = operator_marks(nvim, buf=buf, visual_type=None)

        if focus_row is not None:
            new_row: Optional[int] = focus_row + 1
        elif win != cwin and current_row is not None:
            new_row = current_row + 1
        elif row >= n_count:
            new_row = n_count
        elif p_count != n_count:
            new_row = row + 1
        else:
            new_row = None

        a1 = Atomic()
        a1.buf_set_option(buf, "modifiable", True)

        a2 = _update(nvim, buf=buf, ns=ns, derived=derived)

        a3 = Atomic()
        a3.buf_set_option(buf, "modifiable", False)
        a3.call_function("setpos", ("'<", (buf.number, r1 + 1, c1 + 1, 0)))
        a3.call_function("setpos", ("'>", (buf.number, r2 + 1, c2 + 1, 0)))
        if new_row is not None:
            a3.win_set_cursor(win, (new_row, col))

        (a1 + a2 + a3).commit(nvim)