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 _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 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')
def _preview_image(view: View, defx: Defx, context: Context, candidate: Candidate) -> None: has_nvim = view._vim.call('has', 'nvim') filepath = str(candidate['action__path']) if view._previewed_job: # Stop previous job view._vim.call('jobstop' if has_nvim else 'job_stop', view._previewed_job) view._previewed_job = None preview_image_sh = Path(__file__).parent.parent.joinpath( 'preview_image.sh') if has_nvim: jobfunc = 'jobstart' jobopts = {} else: jobfunc = 'job_start' jobopts = {'in_io': 'null', 'out_io': 'null', 'err_io': 'null'} wincol = context.wincol + view._vim.call('winwidth', 0) if wincol + context.preview_width > view._vim.options['columns']: wincol -= 2 * context.preview_width args = ['bash', str(preview_image_sh), filepath, wincol, 1, context.preview_width] # Note: view._previewed_job is None when Vim8. # Because, job_start() returns job object. view._previewed_job = view._vim.call(jobfunc, args, jobopts)
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 _cd(view: View, defx: Defx, context: Context) -> None: """ Change the current directory. """ source_name = defx._source.name is_parent = context.args and context.args[0] == '..' prev_cwd = Path(defx._cwd) if is_parent: path = prev_cwd.parent else: if context.args: if len(context.args) > 1: source_name = context.args[0] path = Path(context.args[1]) else: path = Path(context.args[0]) else: path = Path.home() path = prev_cwd.joinpath(path) if not readable(path): error(view._vim, f'{path} is invalid.') path = path.resolve() if source_name == 'file' and not path.is_dir(): error(view._vim, f'{path} is invalid.') return view.cd(defx, source_name, str(path), context.cursor) if is_parent: view.search_file(prev_cwd, defx._index)
def _yank_path(view: View, defx: Defx, context: Context) -> None: yank = '\n'.join([str(x['action__path']) for x in context.targets]) view._vim.call('setreg', '"', yank) if (view._vim.call('has', 'clipboard') or view._vim.call('has', 'xterm_clipboard')): view._vim.call('setreg', '+', yank) view.print_msg('Yanked:\n' + yank)
def _add_session(self, view: View, defx: Defx, context: Context) -> None: path = context.args[0] if context.args else defx._cwd if path[-1] == '/': # Remove the last slash path = path[:-1] opened_candidates = [] if context.args else list( defx._opened_candidates) opened_candidates.sort() session: Session if path in view._sessions: old_session = view._sessions[path] session = Session(name=old_session.name, path=old_session.path, opened_candidates=opened_candidates) else: name = Path(path).name session = Session(name=name, path=path, opened_candidates=opened_candidates) view.print_msg(f'session "{name}" is created') view._sessions[session.path] = session self._save_session(view, defx, context)
def _drop(view: View, defx: Defx, context: Context) -> None: """ Open like :drop. """ command = context.args[0] if context.args else 'edit' for target in context.targets: path = target['action__path'] if path.is_dir(): view.cd(defx, defx._source.name, str(path), context.cursor) continue bufnr = view._vim.call('bufnr', f'^{path}$') winids = view._vim.call('win_findbuf', bufnr) if winids: view._vim.call('win_gotoid', winids[0]) else: if context.prev_winid != view._winid and view._vim.call( 'win_id2win', context.prev_winid): view._vim.call('win_gotoid', context.prev_winid) else: view._vim.command('wincmd w') view._vim.call('defx#util#execute_path', command, str(path)) view.restore_previous_buffer()
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 _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 _execute_command(view: View, defx: Defx, context: Context) -> None: """ Execute the command. """ command = context.args[0] if context.args else view._vim.call( 'defx#util#input', 'Command: ', '', 'shellcmd') if not command: return view._vim.command('redraw') def parse_argument(arg: str) -> str: if not arg.startswith('%'): return arg arg = arg[1:] m = re.match(r'((:.)*)(.*)', arg) target_path = str(target['action__path']) if not m: return target_path return fnamemodify(view._vim, target_path, m.group(2)) + m.group(3) for target in context.targets: args = [parse_argument(x) for x in shlex.split(command)] output = subprocess.check_output(args, cwd=defx._cwd) if output: view.print_msg(output)
def _drop(view: View, defx: Defx, context: Context) -> None: """ Open like :drop. """ cwd = view._vim.call('getcwd') command = context.args[0] if context.args else 'edit' for target in context.targets: path = target['action__path'] if path.is_dir(): view.cd(defx, str(path), context.cursor) continue bufnr = view._vim.call('bufnr', f'^{path}$') winids = view._vim.call('win_findbuf', bufnr) if winids: view._vim.call('win_gotoid', winids[0]) else: if context.prev_winid != view._winid and view._vim.call( 'win_id2win', context.prev_winid): view._vim.call('win_gotoid', context.prev_winid) else: view._vim.command('wincmd w') try: path = path.relative_to(cwd) except ValueError: pass view._vim.call('defx#util#execute_path', command, str(path))
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 _move(view: View, defx: Defx, context: Context) -> None: message = 'Move to the clipboard: {}'.format( str(context.targets[0]['action__path']) if len(context.targets) == 1 else str(len(context.targets)) + ' files') view.print_msg(message) view._clipboard.action = ClipboardAction.MOVE view._clipboard.candidates = context.targets
def _open_directory(view: View, defx: Defx, context: Context) -> None: """ Open the directory. """ for target in context.targets: path = target['action__path'] if path.is_dir(): view.cd(defx, str(path), context.cursor)
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 _search(self, view: View, defx: Defx, context: Context) -> None: if not context.args or not context.args[0]: return search_path = Path(context.args[0]) if not search_path.is_absolute(): # Use relative directory instead. search_path = Path(Path(defx._cwd).joinpath(context.args[0])) view.search_file(search_path, defx._index)
def _yank_path(self, view: View, defx: Defx, context: Context) -> None: mods = context.args[0] if context.args else '' paths = [str(x['action__path']) for x in context.targets] if mods: paths = [view._vim.call('fnamemodify', x, mods) for x in paths] yank = '\n'.join(paths) view._vim.call('setreg', '"', yank) if (view._vim.call('has', 'clipboard') or view._vim.call('has', 'xterm_clipboard')): view._vim.call('setreg', '+', yank) view.print_msg('Yanked:\n' + yank)
def _copy(view: View, defx: Defx, context: Context) -> None: if not context.targets: return message = 'Copy to the clipboard: {}'.format( str(context.targets[0]['action__path']) if len(context.targets) == 1 else str(len(context.targets)) + ' files') view.print_msg(message) view._clipboard.action = ClipboardAction.COPY view._clipboard.candidates = context.targets
def _open_directory(view: View, defx: Defx, context: Context) -> None: """ Open the directory. """ if context.args: path = Path(context.args[0]) else: for target in context.targets: path = target['action__path'] if path.is_dir(): view.cd(defx, 'file', str(path), context.cursor)
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 _cd(view: View, defx: Defx, context: Context) -> None: """ Change the current directory. """ path = context.args[0] if context.args else expand('~') path = os.path.normpath(os.path.join(defx._cwd, path)) if not os.path.isdir(path): error(view._vim, '{} is not directory'.format(path)) return view.cd(defx, path, context.cursor) view._selected_candidates = []
def _move(self, view: View, defx: Defx, context: Context) -> None: if not context.targets: return message = 'Move to the clipboard: {}'.format( str(context.targets[0]['action__path']) if len(context.targets) == 1 else str(len(context.targets)) + ' files') view.print_msg(message) view._clipboard.action = ClipboardAction.MOVE view._clipboard.candidates = context.targets view._clipboard.source_name = defx._source.name
def _toggle_columns(view: View, defx: Defx, context: Context) -> None: """ Toggle the current columns. """ columns = (context.args[0] if context.args else '').split(':') if not columns: return current_columns = [x.name for x in view._columns] if columns == current_columns: # Use default columns columns = context.columns.split(':') view._init_columns(columns)
class Rplugin: def __init__(self, vim: Nvim) -> None: self._vim = vim def init_channel(self) -> None: self._vim.vars['defx#_channel_id'] = self._vim.channel_id def start(self, args: typing.List) -> None: self._view = View(self._vim, args[0], args[1]) def do_action(self, args: typing.List) -> None: self._view.do_action(args[0], args[1], args[2])
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 _link(view: View, defx: Defx, context: Context) -> None: if not context.targets: return message = 'Link to the clipboard: {}'.format( str(context.targets[0]['action__path']) if len(context.targets) == 1 else str(len(context.targets)) + ' files') view.print_msg(message) view._clipboard.action = ClipboardAction.LINK view._clipboard.candidates = context.targets view._clipboard.source_name = 'file'
def check_overwrite(view: View, dest: Path, src: Path) -> Path: s_stat = src.stat() s_mtime = s_stat.st_mtime view.print_msg(f' src: {src} {s_stat.st_size} bytes') view.print_msg(f' {time.strftime("%c", time.localtime(s_mtime))}') d_stat = dest.stat() d_mtime = d_stat.st_mtime view.print_msg(f'dest: {dest} {d_stat.st_size} bytes') view.print_msg(f' {time.strftime("%c", time.localtime(d_mtime))}') choice: int = view._vim.call('confirm', f'{dest} already exists. Overwrite?', '&Force\n&No\n&Rename\n&Time\n&Underbar', 0) ret: Path = Path('') if choice == 1: ret = src elif choice == 2: ret = Path('') elif choice == 3: ret = Path( view._vim.call('input', f'{src} -> ', str(src), ('dir' if src.is_dir() else 'file'))) elif choice == 4 and d_mtime < s_mtime: ret = src elif choice == 5: ret = Path(str(src) + '_') return ret