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()
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)
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)
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)
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)
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)
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)
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)
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)))
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()
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', [], {})
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)
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
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)
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
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)
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)
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)
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])
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)
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)
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)
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)
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)
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)
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)
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)
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)
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
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