Beispiel #1
0
def _toggle_select(view: View, defx: Defx, context: Context) -> None:
    index = context.cursor - 1
    if index in view._selected_candidates:
        view._selected_candidates.remove(index)
    else:
        view._selected_candidates.append(index)
    view.redraw()
Beispiel #2
0
def _new_multiple_files(view: View, defx: Defx, context: Context) -> None:
    """
    Create multiple files.
    """

    save_cwd = view._vim.call('getcwd')
    view._vim.command(f'silent lcd {defx._cwd}')

    str_filenames: str = view._vim.call('input',
                                        'Please input new filenames: ', '',
                                        'file')
    view._vim.command(f'silent lcd {save_cwd}')

    if not str_filenames:
        return None

    for name in str_filenames.split():
        is_dir = name[-1] == '/'

        filename = Path(defx._cwd).joinpath(name).resolve()
        if filename.exists():
            error(view._vim, f'{filename} already exists')
            continue

        if is_dir:
            filename.mkdir(parents=True)
        else:
            if not filename.parent.exists():
                filename.parent.mkdir(parents=True)
            filename.touch()

    view.redraw(True)
    view.search_file(filename, defx._index)
Beispiel #3
0
def _rename(view: View, defx: Defx, context: Context) -> None:
    """
    Rename the file or directory.
    """

    if len(context.targets) > 1:
        # ex rename
        view._vim.call('defx#exrename#create_buffer',
                       [{'action__path': str(x['action__path'])}
                        for x in context.targets],
                       {'buffer_name': 'defx'})
        return

    for target in context.targets:
        old = target['action__path']
        new_filename = cwd_input(
            view._vim, defx._cwd,
            f'Old name: {old}\nNew name: ', str(old), 'file')
        view._vim.command('redraw')
        if not new_filename:
            return
        new = Path(defx._cwd).joinpath(new_filename)
        if not new or new == old:
            continue
        if str(new).lower() != str(old).lower() and new.exists():
            error(view._vim, f'{new} already exists')
            continue

        old.rename(new)

        view.redraw(True)
        view.search_file(new, defx._index)
Beispiel #4
0
def _paste(view: View, defx: Defx, context: Context) -> None:
    action = view._clipboard.action
    dest = None
    for index, candidate in enumerate(view._clipboard.candidates):
        path = candidate['action__path']
        dest = Path(defx._cwd).joinpath(path.name)
        if dest.exists():
            overwrite = check_overwrite(view, dest, path)
            if overwrite == Path(''):
                continue
            dest = Path(defx._cwd).joinpath(overwrite.name)

        if path == dest:
            continue

        view.print_msg(
            f'[{index + 1}/{len(view._clipboard.candidates)}] {path}')
        if action == ClipboardAction.COPY:
            if path.is_dir():
                shutil.copytree(str(path), dest)
            else:
                shutil.copy2(str(path), dest)
        elif action == ClipboardAction.MOVE:
            shutil.move(str(path), defx._cwd)
        view._vim.command('redraw')
    view._vim.command('echo')

    view.redraw(True)
    if dest:
        view.search_file(str(dest), defx._index)
Beispiel #5
0
    def _resize(self, view: View, defx: Defx, context: Context) -> None:
        if not context.args:
            return

        view._context = view._context._replace(winwidth=int(context.args[0]))
        view._init_window()
        view.redraw(True)
Beispiel #6
0
def _check_redraw(view: View, defx: Defx, context: Context) -> None:
    root = defx.get_root_candidate()['action__path']
    if not root.exists():
        return
    mtime = root.stat().st_mtime
    if mtime != defx._mtime:
        view.redraw(True)
Beispiel #7
0
def _new_file(view: View, defx: Defx, context: Context) -> None:
    """
    Create a new file and it's parent directories.
    """
    candidate = view.get_cursor_candidate(context.cursor)
    if not candidate:
        return

    if candidate['is_opened_tree'] or candidate['is_root']:
        cwd = str(candidate['action__path'])
    else:
        cwd = str(Path(candidate['action__path']).parent)

    new_filename = cwd_input(
        view._vim, cwd,
        'Please input a new filename: ', '', 'file')
    if not new_filename:
        return
    isdir = new_filename[-1] == '/'
    filename = Path(cwd).joinpath(new_filename)

    if not filename:
        return
    if filename.exists():
        error(view._vim, f'{filename} already exists')
        return

    if isdir:
        filename.mkdir(parents=True)
    else:
        filename.parent.mkdir(parents=True, exist_ok=True)
        filename.touch()

    view.redraw(True)
    view.search_recursive(filename, defx._index)
Beispiel #8
0
    def _new_directory(self, view: View, defx: Defx, context: Context) -> None:
        """
        Create a new directory.
        """
        candidate = view.get_cursor_candidate(context.cursor)
        if not candidate:
            return

        if candidate['is_opened_tree'] or candidate['is_root']:
            cwd = str(candidate['action__path'])
        else:
            cwd = str(Path(candidate['action__path']).parent)

        new_filename = self.input(view, defx, cwd,
                                  'Please input a new directory name: ', '',
                                  'file')
        if not new_filename:
            return
        filename = self.path_maker(cwd).joinpath(new_filename)

        if not filename:
            return
        if filename.exists():
            error(view._vim, f'{filename} already exists')
            return

        filename.mkdir(parents=True)
        view.redraw(True)
        view.search_recursive(filename, defx._index)
Beispiel #9
0
    def create_open(self, view: View, defx: Defx, context: Context, path: Path,
                    command: str, isdir: bool, isopen: bool) -> None:
        if isdir:
            path.mkdir(parents=True)
        else:
            path.parent.mkdir(parents=True, exist_ok=True)
            path.touch()

        if not isopen:
            view.redraw(True)
            view.search_recursive(path, defx._index)
            return

        # Note: Must be redraw before actions
        view.redraw(True)
        view.search_recursive(path, defx._index)

        if isdir:
            if command == 'open_tree':
                view.open_tree(path, defx._index, False, 0)
            else:
                view.cd(defx, defx._source.name, str(path), context.cursor)
        else:
            if command == 'drop':
                self._drop(
                    view, defx,
                    context._replace(args=[], targets=[{
                        'action__path': path
                    }]))
            else:
                view._vim.call('defx#util#execute_path', command,
                               self.get_buffer_name(str(path)))
Beispiel #10
0
def _toggle_select_all(view: View, defx: Defx, context: Context) -> None:
    for [index, candidate] in enumerate(view._candidates):
        if (not candidate.get('is_root', False) and
                candidate['_defx_index'] == defx._index):
            if index in view._selected_candidates:
                view._selected_candidates.remove(index)
            else:
                view._selected_candidates.append(index)
    view.redraw()
Beispiel #11
0
def test_do_action():
    vim = create_autospec(Nvim)
    vim.channel_id = 0
    vim.vars = {}
    vim.call.return_value = ''
    vim.current = MagicMock()

    defx = View(vim, [], {})
    defx.redraw()
    defx.do_action('open', [], {})
Beispiel #12
0
def _paste(view: View, defx: Defx, context: Context) -> None:
    candidate = view.get_cursor_candidate(context.cursor)
    if not candidate:
        return

    if candidate['is_opened_tree'] or candidate['is_root']:
        cwd = str(candidate['action__path'])
    else:
        cwd = str(Path(candidate['action__path']).parent)

    action = view._clipboard.action
    dest = None
    for index, candidate in enumerate(view._clipboard.candidates):
        path = candidate['action__path']
        dest = Path(cwd).joinpath(path.name)
        if dest.exists():
            overwrite = check_overwrite(view, dest, path)
            if overwrite == Path(''):
                continue
            dest = overwrite

        if not path.exists() or path == dest:
            continue

        view.print_msg(
            f'[{index + 1}/{len(view._clipboard.candidates)}] {path}')
        if action == ClipboardAction.COPY:
            if path.is_dir():
                shutil.copytree(str(path), dest)
            else:
                shutil.copy2(str(path), dest)
        elif action == ClipboardAction.MOVE:
            if dest.exists():
                # Must remove dest before
                if dest.is_dir():
                    shutil.rmtree(str(dest))
                else:
                    dest.unlink()
            shutil.move(str(path), cwd)

            # Check rename
            if not path.is_dir():
                view._vim.call('defx#util#buffer_rename',
                               view._vim.call('bufnr', str(path)), str(dest))

        view._vim.command('redraw')
    if action == ClipboardAction.MOVE:
        # Clear clipboard after move
        view._clipboard.candidates = []
    view._vim.command('echo')

    view.redraw(True)
    if dest:
        view.search_recursive(dest, defx._index)
Beispiel #13
0
def do_action(view: View, defx: Defx,
              action_name: str, context: Context) -> bool:
    """
    Do "action_name" action.
    """
    if action_name not in DEFAULT_ACTIONS:
        return True
    action = DEFAULT_ACTIONS[action_name]
    action.func(view, defx, context)
    if ActionAttr.REDRAW in action.attr:
        view.redraw(True)
    return False
Beispiel #14
0
def _new_directory(view: View, defx: Defx, context: Context) -> None:
    """
    Create a new directory.
    """
    filename = cwd_input(view._vim, defx._cwd,
                         'Please input a new directory: ', '', 'dir')
    if os.path.exists(filename):
        error(view._vim, '{} is already exists'.format(filename))
        return

    os.mkdir(filename)
    view.redraw(True)
    view.search_file(filename, defx._index)
Beispiel #15
0
def do_action(view: View, defx: Defx, action_name: str,
              context: Context) -> bool:
    """
    Do "action_name" action.
    """
    actions: typing.Dict[str, ActionTable] = defx._source.kind.get_actions()

    if action_name not in actions:
        return True

    action = actions[action_name]

    selected_candidates = [x for x in view._candidates if x['is_selected']]
    if ActionAttr.NO_TAGETS not in action.attr and selected_candidates:
        # Clear marks
        for candidate in selected_candidates:
            candidate['is_selected'] = False
        view.redraw()

    action.func(view, defx, context)

    if action_name != 'repeat':
        view._prev_action = action_name

    if ActionAttr.MARK in action.attr:
        # Update marks
        view.redraw()
    elif ActionAttr.TREE in action.attr:
        view.update_opened_candidates()
        view.redraw()
    elif ActionAttr.REDRAW in action.attr:
        # Redraw
        view.redraw(True)
    return False
Beispiel #16
0
    def _rename(self, view: View, defx: Defx, context: Context) -> None:
        """
        Rename the file or directory.
        """

        if len(context.targets) > 1:
            # ex rename
            view._vim.call('defx#exrename#create_buffer',
                           [{
                               'action__path': str(x['action__path'])
                           }
                            for x in context.targets], {'buffer_name': 'defx'})
            return

        mode = '' if not context.args else context.args[0]
        for target in context.targets:
            old = target['action__path']
            default = str(old)
            if mode == 'insert':
                view._vim.call('defx#util#back_cursor_input', len(old.name))
            elif mode == 'append':
                view._vim.call('defx#util#back_cursor_input', len(old.suffix))
            elif mode == 'new':
                default = default[:-len(old.name)]
            new_filename = self.input(view, defx, defx._cwd,
                                      f'Old name: {old}\nNew name: ', default,
                                      'file')
            view._vim.command('redraw')
            if not new_filename:
                return
            new = self.path_maker(defx._cwd).joinpath(new_filename)
            if not new or new == old:
                continue
            if str(new).lower() != str(old).lower() and new.exists():
                error(view._vim, f'{new} already exists')
                continue

            if not new.parent.exists():
                new.parent.mkdir(parents=True)
            old.rename(new)

            # Check rename
            # The old is directory, the path may be matched opened file
            if not new.is_dir() and view._vim.call('bufexists', str(old)):
                view._vim.call('defx#util#buffer_rename',
                               view._vim.call('bufnr', str(old)), str(new))

            view.redraw(True)
            view.search_recursive(new, defx._index)
Beispiel #17
0
def _new_directory(view: View, defx: Defx, context: Context) -> None:
    """
    Create a new directory.
    """
    filename = cwd_input(view._vim, defx._cwd,
                         'Please input a new directory: ', '', 'dir')
    if not filename:
        return
    if filename.exists():
        error(view._vim, f'{filename} already exists')
        return

    filename.mkdir(parents=True)
    view.redraw(True)
    view.search_file(str(filename), defx._index)
Beispiel #18
0
    def _paste(self, view: View, defx: Defx, context: Context) -> None:
        candidate = view.get_cursor_candidate(context.cursor)
        action = view._clipboard.action
        if not candidate or action == ClipboardAction.NONE:
            return

        if candidate['is_opened_tree'] or candidate['is_root']:
            cwd = str(candidate['action__path'])
        else:
            cwd = str(Path(candidate['action__path']).parent)

        dest = None
        for index, candidate in enumerate(view._clipboard.candidates):
            path = candidate['action__path']
            dest = self.path_maker(cwd).joinpath(path.name)
            if dest.exists():
                overwrite = self.check_overwrite(view, dest, path)
                if overwrite == self.path_maker(''):
                    continue
                dest = overwrite

            if not path.exists() or path == dest:
                continue

            view.print_msg(
                f'[{index + 1}/{len(view._clipboard.candidates)}] {path}')

            if dest.exists() and action != ClipboardAction.MOVE:
                # Must remove dest before
                if not dest.is_symlink() and dest.is_dir():
                    self.rmtree(dest)
                else:
                    dest.unlink()

            self.paste(view, path, dest, cwd)
            view._vim.command('redraw')

        if action == ClipboardAction.MOVE:
            # Clear clipboard after action
            view._clipboard.action = ClipboardAction.NONE
            view._clipboard.candidates = []

        view._vim.command('echo')

        view.redraw(True)
        if dest:
            view.search_recursive(dest, defx._index)
Beispiel #19
0
    class DefxHandlers(object):

        def __init__(self, vim: Nvim) -> None:
            self._vim = vim

        @neovim.function('_defx_init')
        def init_channel(self, args: typing.List) -> None:
            self._vim.vars['defx#_channel_id'] = self._vim.channel_id

        @neovim.function('_defx_start')
        def start(self, args: typing.List) -> None:
            self._view = View(self._vim, args[0], args[1])
            self._view.redraw()

        @neovim.function('_defx_do_action')
        def do_action(self, args: typing.List) -> None:
            self._view.do_action(args[0], args[1], args[2])
Beispiel #20
0
def _search(view: View, defx: Defx, context: Context) -> None:
    if not context.args or not context.args[0]:
        return

    search_path = context.args[0]
    path = Path(search_path)
    parents: typing.List[Path] = []
    while view.get_candidate_pos(path,
                                 defx._index) < 0 and path.parent != path:
        path = path.parent
        parents.append(path)

    for parent in reversed(parents):
        view.open_tree(parent, defx._index, 0)

    view.update_opened_candidates()
    view.redraw()
    view.search_file(Path(search_path), defx._index)
Beispiel #21
0
def _new_file(view: View, defx: Defx, context: Context) -> None:
    """
    Create a new file and it's parent directories.
    """
    filename = cwd_input(view._vim, defx._cwd,
                         'Please input a new filename: ', '', 'file')
    if os.path.exists(filename):
        error(view._vim, '{} is already exists'.format(filename))
        return

    dirname = os.path.dirname(filename)
    if not os.path.exists(dirname):
        os.makedirs(dirname)

    with open(filename, 'w') as f:
        f.write('')
    view.redraw(True)
    view.search_file(filename, defx._index)
Beispiel #22
0
def _remove_trash(view: View, defx: Defx, context: Context) -> None:
    """
    Delete the file or directory.
    """
    if not importlib.find_loader('send2trash'):
        error(view._vim, '"Send2Trash" is not installed')
        return

    message = 'Are you sure you want to delete {}?'.format(
        str(context.targets[0]['action__path']) if len(context.targets) ==
        1 else str(len(context.targets)) + ' files')
    if not confirm(view._vim, message):
        return

    import send2trash
    for target in context.targets:
        send2trash.send2trash(str(target['action__path']))
    view.redraw(True)
Beispiel #23
0
def _rename(view: View, defx: Defx, context: Context) -> None:
    """
    Rename the file or directory.
    """
    for target in context.targets:
        old = target['action__path']
        new = cwd_input(view._vim, defx._cwd, f'New name: {old} -> ', str(old),
                        'file')
        if not new or new == old:
            continue
        if new.exists():
            error(view._vim, f'{new} already exists')
            continue

        old.rename(new)

        view.redraw(True)
        view.search_file(str(new), defx._index)
Beispiel #24
0
def _new_directory(view: View, defx: Defx, context: Context) -> None:
    """
    Create a new directory.
    """
    candidate = view.get_cursor_candidate(context.cursor)
    if not candidate:
        return
    filename = cwd_input(view._vim,
                         str(Path(candidate['action__path']).parent),
                         'Please input a new filename: ', '', 'file')
    if not filename:
        return
    if filename.exists():
        error(view._vim, f'{filename} already exists')
        return

    filename.mkdir(parents=True)
    view.redraw(True)
    view.search_file(filename, defx._index)
Beispiel #25
0
def _new_file(view: View, defx: Defx, context: Context) -> None:
    """
    Create a new file and it's parent directories.
    """
    filename = cwd_input(view._vim, defx._cwd, 'Please input a new filename: ',
                         '', 'file')
    if not filename:
        return
    if filename.exists():
        error(view._vim, '{filename} already exists')
        return

    if not filename.parent.exists():
        filename.parent.mkdir(parents=True)

    Path(filename).touch()

    view.redraw(True)
    view.search_file(str(filename), defx._index)
Beispiel #26
0
def _remove(view: View, defx: Defx, context: Context) -> None:
    """
    Delete the file or directory.
    """
    message = 'Are you sure you want to delete {}?'.format(
        context.targets[0]['action__path']
        if len(context.targets) == 1
        else str(len(context.targets)) + ' files')
    if not confirm(view._vim, message):
        return

    for target in context.targets:
        path = target['action__path']

        if os.path.isdir(path):
            shutil.rmtree(path)
        else:
            os.remove(path)
    view.redraw(True)
Beispiel #27
0
def _rename(view: View, defx: Defx, context: Context) -> None:
    """
    Rename the file or directory.
    """
    for target in context.targets:
        path = target['action__path']
        filename = cwd_input(
            view._vim, defx._cwd,
            ('New name: {} -> '.format(path)), path, 'file')
        if not filename or filename == path:
            continue
        if os.path.exists(filename):
            error(view._vim, '{} is already exists'.format(filename))
            continue

        os.rename(path, filename)

        view.redraw(True)
        view.search_file(filename, defx._index)
Beispiel #28
0
def _new_multiple_files(view: View, defx: Defx, context: Context) -> None:
    """
    Create multiple files.
    """
    candidate = view.get_cursor_candidate(context.cursor)
    if not candidate:
        return

    if candidate['is_opened_tree'] or candidate['is_root']:
        cwd = str(candidate['action__path'])
    else:
        cwd = str(Path(candidate['action__path']).parent)

    save_cwd = view._vim.call('getcwd')
    cd(view._vim, cwd)

    str_filenames: str = view._vim.call('input',
                                        'Please input new filenames: ', '',
                                        'file')
    cd(view._vim, save_cwd)

    if not str_filenames:
        return None

    for name in str_filenames.split():
        is_dir = name[-1] == '/'

        filename = Path(cwd).joinpath(name)
        if filename.exists():
            error(view._vim, f'{filename} already exists')
            continue

        if is_dir:
            filename.mkdir(parents=True)
        else:
            if not filename.parent.exists():
                filename.parent.mkdir(parents=True)
            filename.touch()

    view.redraw(True)
    view.search_recursive(filename, defx._index)
Beispiel #29
0
def do_action(view: View, defx: Defx,
              action_name: str, context: Context) -> bool:
    """
    Do "action_name" action.
    """
    actions = DEFAULT_ACTIONS

    if action_name not in actions:
        return True

    action = actions[action_name]

    if ActionAttr.MARK not in action.attr and view._selected_candidates:
        # Clear marks
        view._selected_candidates = []
        view.redraw()

    action.func(view, defx, context)

    if action_name != 'repeat':
        view._prev_action = action_name

    if ActionAttr.MARK in action.attr:
        # Update marks
        view.redraw()
    elif ActionAttr.REDRAW in action.attr:
        # Redraw
        view.redraw(True)
    return False
Beispiel #30
0
def do_action(view: View, defx: Defx, action_name: str,
              context: Context) -> bool:
    """
    Do "action_name" action.
    """
    actions: typing.Dict[str, ActionTable] = defx._source.kind.get_actions()

    if action_name not in actions:
        return True

    action = actions[action_name]

    if ActionAttr.MARK not in action.attr and view._selected_candidates:
        # Clear marks
        view._selected_candidates = []
        view.redraw()

    action.func(view, defx, context)

    if action_name != 'repeat':
        view._prev_action = action_name

    if ActionAttr.MARK in action.attr:
        # Update marks
        view.redraw()
    elif ActionAttr.REDRAW in action.attr:
        # Redraw
        view.redraw(True)
    return False