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)
def _rename(nvim: Nvim, state: State, settings: Settings, is_visual: bool) -> Optional[Stage]: """ rename file / folder """ node = next(indices(nvim, state=state, is_visual=is_visual), None) if not node: return None else: child = ask(nvim, question=LANG("pencil"), default=str(node.path.name)) if not child: return None else: new_path = PurePath(abspath(node.path.parent / child)) operations = {node.path: new_path} if exists(new_path, follow=False): write(nvim, LANG("already_exists", name=str(new_path)), error=True) return None else: try: rename(state.pool, operations=operations) except Exception as e: write(nvim, e, error=True) return refresh(nvim, state=state, settings=settings) else: new_state = (maybe_path_above( nvim, state=state, settings=settings, path=new_path) or state) paths = ancestors(new_path) index = state.index | paths next_state = forward(new_state, settings=settings, index=index, paths=paths) kill_buffers( nvim, last_used=new_state.window_order, paths={node.path}, reopen={node.path: new_path}, ) lsp_moved(nvim, paths=operations) return Stage(next_state, focus=new_path)
def _new(nvim: Nvim, state: State, settings: Settings, is_visual: bool) -> Optional[Stage]: """ new file / folder """ node = next(indices(nvim, state=state, is_visual=is_visual), None) if not node: return None else: parent = node.path if is_dir(node) else node.path.parent child = ask(nvim, question=LANG("pencil"), default="") if not child: return None else: path = PurePath(abspath(parent / child)) if exists(path, follow=False): write(nvim, LANG("already_exists", name=str(path)), error=True) return None else: try: if child.endswith(sep): mkdir(state.pool, paths=(path, )) else: new(state.pool, paths=(path, )) except Exception as e: write(nvim, e, error=True) return refresh(nvim, state=state, settings=settings) else: new_state = (maybe_path_above( nvim, state=state, settings=settings, path=path) or state) paths = ancestors(path) index = state.index | paths next_state = forward(new_state, settings=settings, index=index, paths=paths) lsp_created(nvim, paths=(path, )) return Stage(next_state, focus=path)
def _new( nvim: Nvim, state: State, settings: Settings, is_visual: bool ) -> Optional[Stage]: """ new file / folder """ node = next(indices(nvim, state=state, is_visual=is_visual), None) if not node: return None else: parent = node.path if is_dir(node) else dirname(node.path) child = ask(nvim, question=LANG("pencil"), default="") if not child: return None else: path = abspath(join(parent, child)) if exists(path): write(nvim, LANG("already_exists", name=path), error=True) return None else: try: dest = path + sep if child.endswith(sep) else path new((dest,)) except Exception as e: write(nvim, e, error=True) return refresh(nvim, state=state, settings=settings) else: new_state = ( maybe_path_above( nvim, state=state, settings=settings, path=path ) or state ) paths = ancestors(path) index = state.index | paths next_state = forward( new_state, settings=settings, index=index, paths=paths ) return Stage(next_state, focus=path)
def _rename(nvim: Nvim, state: State, settings: Settings, is_visual: bool) -> Optional[Stage]: """ rename file / folder """ node = next(indices(nvim, state=state, is_visual=is_visual), None) if not node: return None else: prev_name = node.path parent = state.root.path rel_path = relpath(prev_name, start=parent) child = ask(nvim, question=LANG("pencil"), default=rel_path) if not child: return None else: new_name = abspath(join(parent, child)) if exists(new_name): write(nvim, LANG("already_exists", name=new_name), error=True) return None else: try: rename({prev_name: new_name}) except Exception as e: write(nvim, e, error=True) return refresh(nvim, state=state, settings=settings) else: new_state = (maybe_path_above( nvim, state=state, settings=settings, path=new_name) or state) paths = ancestors(new_name) index = state.index | paths next_state = forward(new_state, settings=settings, index=index, paths=paths) kill_buffers(nvim, paths={prev_name}) return Stage(next_state, focus=new_name)
def _filter(nvim: Nvim, state: State, settings: Settings, is_visual: bool) -> Optional[Stage]: """ Update filter """ node = next(indices(nvim, state=state, is_visual=is_visual), None) if not node: return None else: focus = node.path old_p = state.filter_pattern.pattern if state.filter_pattern else "" pattern = ask(nvim, question=LANG("new_filter"), default=old_p) filter_pattern = FilterPattern(pattern=pattern) if pattern else None selection: Selection = state.selection if filter_pattern else set() new_state = forward(state, settings=settings, selection=selection, filter_pattern=filter_pattern) return Stage(new_state, focus=focus)
def _linked_marks( nvim: Nvim, mark: ExtMark, linked: Sequence[ExtMark], ns: int, win: Window, buf: Buffer, ) -> bool: marks = tuple(chain((mark, ), linked)) place_holders = tuple( text for _, text in extmarks_text(nvim, buf=buf, marks=marks)) texts = dumps(place_holders, check_circular=False, ensure_ascii=False) resp = ask(nvim, question=LANG("expand marks", texts=texts), default="") if resp is not None: row, col = mark.begin nvim.options["undolevels"] = nvim.options["undolevels"] apply(nvim, buf=buf, instructions=_trans(resp, marks=marks)) _del_marks(nvim, buf=buf, id=ns, marks=marks) win_set_cursor(nvim, win=win, row=row, col=col) nvim.command("startinsert") state(inserted_pos=(row, col - 1)) return True else: return False
def _operation( nvim: Nvim, *, state: State, settings: Settings, is_visual: bool, nono: AbstractSet[str], op_name: str, action: Callable[[Mapping[str, str]], None], ) -> Optional[Stage]: root = state.root.path node = next(indices(nvim, state=state, is_visual=is_visual), None) selection = state.selection unified = unify_ancestors(selection) if not unified or not node: write(nvim, LANG("nothing_select"), error=True) return None elif not unified.isdisjoint(nono): write(nvim, LANG("operation not permitted on root"), error=True) return None else: pre_operations = {src: _find_dest(src, node) for src in unified} pre_existing = {s: d for s, d in pre_operations.items() if exists(d)} new_operations: MutableMapping[str, str] = {} while pre_existing: source, dest = pre_existing.popitem() rel_dest = display_path(dest, state=state) resp = ask(nvim, question=LANG("path_exists_err"), default=rel_dest) new_dest = join(root, resp) if resp else None if not new_dest: pre_existing[source] = dest break elif exists(new_dest): pre_existing[source] = new_dest else: new_operations[source] = new_dest if pre_existing: msg = linesep.join( f"{display_path(s, state=state)} -> {display_path(d, state=state)}" for s, d in sorted(pre_existing.items(), key=lambda t: strxfrm(t[0]))) write( nvim, LANG("paths already exist", operation=op_name, paths=msg), error=True, ) return None else: operations: Mapping[str, str] = { **pre_operations, **new_operations } msg = linesep.join( f"{display_path(s, state=state)} -> {display_path(d, state=state)}" for s, d in sorted(operations.items(), key=lambda t: strxfrm(t[0]))) question = LANG("confirm op", operation=op_name, paths=msg) ans = ask_mc( nvim, question=question, answers=LANG("ask_yesno"), answer_key={ 1: True, 2: False }, ) if not ans: return None else: try: action(operations) except Exception as e: write(nvim, e, error=True) return refresh(nvim, state=state, settings=settings) else: paths = { dirname(p) for p in chain(operations.keys(), operations.values()) } index = state.index | paths new_selection = {*operations.values()} new_state = forward( state, settings=settings, index=index, selection=new_selection, paths=paths, ) kill_buffers(nvim, paths=selection) return Stage(new_state)
def _operation( nvim: Nvim, *, state: State, settings: Settings, is_visual: bool, nono: AbstractSet[PurePath], op_name: str, is_move: bool, action: Callable[[Executor, Mapping[PurePath, PurePath]], None], ) -> Optional[Stage]: node = next(indices(nvim, state=state, is_visual=is_visual), None) selection = state.selection unified = unify_ancestors(selection) if not unified or not node: write(nvim, LANG("nothing_select"), error=True) return None elif not unified.isdisjoint(nono): write(nvim, LANG("operation not permitted on root"), error=True) return None else: pre_operations = {src: _find_dest(src, node) for src in unified} pre_existing = { s: d for s, d in pre_operations.items() if exists(d, follow=False) } new_operations: MutableMapping[PurePath, PurePath] = {} while pre_existing: source, dest = pre_existing.popitem() resp = ask(nvim, question=LANG("path_exists_err"), default=dest.name) new_dest = dest.parent / resp if resp else None if not new_dest: pre_existing[source] = dest break elif exists(new_dest, follow=False): pre_existing[source] = new_dest else: new_operations[source] = new_dest if pre_existing: msg = linesep.join( f"{display_path(s, state=state)} -> {display_path(d, state=state)}" for s, d in sorted(pre_existing.items(), key=lambda t: strxfrm(str(t[0])))) write( nvim, LANG("paths already exist", operation=op_name, paths=msg), error=True, ) return None else: operations = {**pre_operations, **new_operations} msg = linesep.join( f"{display_path(s, state=state)} -> {display_path(d, state=state)}" for s, d in sorted(operations.items(), key=lambda t: strxfrm(str(t[0])))) question = LANG("confirm op", operation=op_name, paths=msg) ans = ask_mc( nvim, question=question, answers=LANG("ask_yesno"), answer_key={ 1: True, 2: False }, ) if not ans: return None else: try: action(state.pool, operations) except Exception as e: write(nvim, e, error=True) return refresh(nvim, state=state, settings=settings) else: paths = { p.parent for p in chain(operations.keys(), operations.values()) } index = state.index | paths new_selection = {*operations.values()} new_state = forward( state, settings=settings, index=index, selection=new_selection, paths=paths, ) focus = next( iter( sorted( new_selection, key=lambda p: tuple(map(strxfrm, p.parts)), ), ), None, ) if is_move: kill_buffers( nvim, last_used=new_state.window_order, paths=selection, reopen={}, ) lsp_moved(nvim, paths=operations) else: lsp_created(nvim, paths=new_selection) return Stage(new_state, focus=focus)