def view_mime(self): Vim.command('setlocal buftype=nofile') Vim.command('setlocal noswapfile') Vim.command('setlocal nobuflisted') Vim.command('setlocal bufhidden=wipe') Vim.current.buffer[:] = [self.path, self.mime_type] Vim.command('setlocal nomodifiable')
def _set(self, mark): """ The callback for the BookMarkUI/set. """ if mark == '': return if mark not in self.valid_mark: Vim.command('echo "Only a-zA-Z are valid mark!!"') return set_buf = self.bufs['set'] set_buf.options['modifiable'] = True if mark in self.mark_dict: for i, line in enumerate(set_buf): if len(line) > 0 and line[0] == mark: set_buf[i] = f'{mark}:{self.path_to_mark}' break elif self.path_to_mark in self.mark_dict.values(): for i, line in enumerate(set_buf): if len(line) > 0 and line[2:] == self.path_to_mark: set_buf[i] = f'{mark}:{self.path_to_mark}' break else: set_buf.append(f'{mark}:{self.path_to_mark}') set_buf.options['modifiable'] = False self.mark_dict[mark] = self.path_to_mark self.del_buf('go') with open(Vim.Var('NETRBookmarkFile'), 'w') as f: for k, p in self.mark_dict.items(): f.write(f'{k}:{p}\n')
def load_bookmarks(self): self.mark_dict = {} if os.path.isfile(Vim.Var('NETRBookmarkFile')): with open(Vim.Var('NETRBookmarkFile'), 'r') as f: for line in f: kp = line.split(':') if (len(kp) == 2): self.mark_dict[kp[0].strip()] = kp[1].strip()
def map_key_reg(self, key, regval): """ Register a key mapping in a UI buffer. The mapped action is: 1. Store regval into g:NETRRegister, which serves as the argument for netranger buffer's call back after UI buffer quit. 2. Quit the UI buffer. See Netranger.pend_onuiquit for details. """ Vim.command(f'nnoremap <nowait> <silent> <buffer> {key} ' f':let g:NETRRegister=["{regval}"] <cr> :quit <cr>')
def init(self, root_dir, remote_remap): self._flags = Vim.Var("_NETRRcloneFlags", default="") self.rclone_rcd_port = Vim.Var('NETRcloneRcdPort') if root_dir[-1] == '/': root_dir = root_dir[:-1] self.root_dir = root_dir self.rplen = len(root_dir) + 1 self.rcd_started = False for remote, root in remote_remap.items(): if root[-1] != '/': remote_remap[remote] += '/' self.remote_remap = remote_remap Shell.mkdir(root_dir)
def __init__(self, netranger): UI.__init__(self) self.valid_mark = string.ascii_lowercase + string.ascii_uppercase self.netranger = netranger self.mark_dict = {} self.path_to_mark = None # This is to avoid a bug that I can't solve. # If bookmark file is initially empty. The first time # 'm' (set) mapping is trigger, it won't quit the buffer # on user input.. if not os.path.isfile(Vim.Var('NETRBookmarkFile')): with open(Vim.Var('NETRBookmarkFile'), 'w') as f: f.write(f'~:{os.path.expanduser("~")}') self.load_bookmarks()
def list_remotes_in_vim_buffer(self): if not Shell.isinPATH('rclone'): self.install_rclone() remotes = set(self.cmd_listremotes()) local_remotes = set(super(Rclone, self).ls(self.root_dir)) for remote in remotes.difference(local_remotes): Shell.mkdir(os.path.join(self.root_dir, remote)) for remote in local_remotes.difference(remotes): Shell.rm(os.path.join(self.root_dir, remote)) if len(remotes) > 0: Vim.command(f'NETRTabdrop {self.root_dir}') else: Vim.ErrorMsg( "There's no remote now. Run 'rclone config' in a terminal to " "setup remotes and restart vim again.")
def __init__(self, target_path=''): """ This is a help class for separating local files and remote files for mv, cp, rm commands. Though the logic in this class can be done in the caller side, it makes the caller has higher branch number and hard-to-read code. """ self.remote_targets = [] self.local_targets = [] self.remote_root = Vim.Var('NETRemoteCacheDir') self.is_remote = self.is_remote_path(target_path)
def exec_server_cmd(self, cmd, on_exit, arguments, sudo=False): def on_stderr(job_id, err_msg): ind = err_msg.rfind('FSServerException: ') if ind > 0: err_msg = err_msg[ind + 19:] Vim.ErrorMsg(err_msg) fname = tempfile.mkstemp()[1] with open(fname, 'ab') as f: pickle.dump(arguments, f) if sudo: Vim.AsyncRun('sudo {} {} {}'.format(self.ServerCmd, cmd, fname), on_exit=on_exit, term=True) else: Vim.AsyncRun('{} {} {}'.format(self.ServerCmd, cmd, fname), on_stderr=on_stderr, on_exit=on_exit)
def run_async(cls, cmd, on_stdout=None, on_exit=None): def print_error(job_id, err_msg): # Truncate unnecessary message if from fs_server.py ind = err_msg.rfind('FSServerException: ') if ind > 0: err_msg = err_msg[ind + 19:] Vim.ErrorMsg(err_msg) Vim.AsyncRun(cmd, on_stdout=on_stdout, on_exit=on_exit, on_stderr=print_error)
def view_image(self): try: import ueberzug except ModuleNotFoundError: Vim.ErrorMsg('Please install ueberzug for image preview') self.view_mime() return path = self.path if self.path.endswith('gif') and Shell.isinPATH('convert'): if self.path not in self.tempfile_cache: dir = tempfile.TemporaryDirectory().name Shell.mkdir(dir) self.tempfile_cache[self.path] = dir dir = self.tempfile_cache[self.path] path = dir Shell.run(f'convert -deconstruct "{self.path}" {dir}/a.png') Vim.AsyncRun(f'{util.GenNetRangerScriptCmd("image_preview")}\ "{path}" {self.total_width} {self.preview_width}', term=True, termopencmd='') Vim.command('setlocal nocursorline')
def run_cmd(self, cmd): if not self.rcd_started: Vim.AsyncRun( f'rclone {self._flags} rcd --rc-no-auth --rc-addr=localhost:{self.rclone_rcd_port}' ) self.rcd_started = True # Ensure the server running before executing the next command. time.sleep(.1) return json.loads( Shell.run( f'rclone {self._flags} rc --rc-addr=localhost:{self.rclone_rcd_port} {cmd}' ))
def edit(self): """ Show the buffer for editing the bookmark. """ Vim.command(f'belowright split {Vim.Var("NETRBookmarkFile")}') Vim.command('wincmd J') Vim.command('setlocal bufhidden=wipe') self.del_buf('set') self.del_buf('go') self.netranger.pend_onuiquit(self.load_bookmarks)
def install_rclone(self): import platform import zipfile rclone_dir = Vim.UserInput( 'Rclone not in PATH. Install it at (modify/enter)', os.path.expanduser('~/rclone')) Shell.mkdir(rclone_dir) system = platform.system().lower() processor = 'amd64' if '386' in platform.processor(): processor = '386' else: # Should support arm?? pass url = f'https://downloads.rclone.org/rclone-current-{system}-{processor}.zip' zip_fname = os.path.join(rclone_dir, 'rclone.zip') Shell.urldownload(url, zip_fname) zip_ref = zipfile.ZipFile(zip_fname, 'r') zip_ref.extractall(rclone_dir) for entry in zip_ref.NameToInfo: if entry.endswith('rclone'): Shell.cp(os.path.join(rclone_dir, entry), rclone_dir) Shell.chmod(os.path.join(rclone_dir, 'rclone'), 755) zip_ref.close() os.remove(zip_fname) shellrc = Vim.UserInput( 'Update PATH in (leave blank to set manually later)', Shell.shellrc()) if len(shellrc) > 0: with open(shellrc, 'a') as f: f.write(f'PATH={rclone_dir}:$PATH\n') os.environ['PATH'] += ':' + rclone_dir
def ask(self, content, fullpath): self.show() if len(content) > 24: Vim.WarningMsg('Ask only supports up to 24 commands.') content = content[:24] ind = 97 self.options = content[:] self.options.append('vim') self.fullpath = fullpath for i, c in enumerate(content): content[i] = f'{chr(ind)}. {c}' ind += 1 content.append(f'{chr(ind)}. vim') buf = self.bufs['default'] buf.options['modifiable'] = True buf[:] = content buf.options['modifiable'] = False self.netranger.pend_onuiquit(self._ask, num_args=1)
def create_buf(self, content, mappings=None, name='default', map_cr=False): """ Create the UI buffer. """ Vim.command(f'{self.position} new') self.set_buf_common_option() new_buf = Vim.current.buffer self.bufs[name] = new_buf if mappings is not None: for k, v in mappings: self.map_key_reg(k, v) if map_cr: assert mappings is not None ui_internal_vim_dict_name = f'g:_{type(self).__name__}Map' Vim.command(f'let {ui_internal_vim_dict_name}={dict(mappings)}') Vim.command( "nnoremap <nowait> <silent> <buffer> <Cr> " ":let g:NETRRegister=[{}[getline('.')[0]]] <cr> :quit <cr>". format(ui_internal_vim_dict_name)) new_buf.options['modifiable'] = True new_buf[:] = content new_buf.options['modifiable'] = False Vim.command('quit')
def __init__(self, path): self.rules = [] if not os.path.isfile(path): Shell.cp(os.path.join(config_dir, 'rifle.conf'), path) with open(path, 'r') as f: for i, line in enumerate(f): try: # remove things after the first # (including) line = line[:line.index('#')] except ValueError: pass line = line.strip() if len(line) == 0: continue sp = line.split('=') if len(sp) != 2: Vim.ErrorMsg( 'invalid rule: rifle.conf line {}. There should be one' ' and only one "=" for each line'.format(i + 1)) continue tests = [] for test in sp[0].strip().split(','): testSp = [e for e in test.split(' ') if e != ''] tests.append(globals()[testSp[0]](*testSp[1:])) command = sp[1].strip() # simple case, used specify only the command # For sophisicated command like bash -c "command {}" # user should add '{}' themselves if '{}' not in command: command = command + ' {}' self.rules.append((tests, command))
def print_error(job_id, err_msg): # Truncate unnecessary message if from fs_server.py ind = err_msg.rfind('FSServerException: ') if ind > 0: err_msg = err_msg[ind + 19:] Vim.ErrorMsg(err_msg)
def run(cls, cmd): try: return subprocess.check_output( cmd, shell=True, stderr=subprocess.STDOUT).decode('utf-8') except subprocess.CalledProcessError as e: Vim.ErrorMsg(e)
def set_buf_common_option(self, modifiable=False): """ Set common option for a UI buffer. """ Vim.command('setlocal noswapfile') Vim.command('setlocal foldmethod=manual') Vim.command('setlocal foldcolumn=0') Vim.command('setlocal nofoldenable') Vim.command('setlocal nobuflisted') Vim.command('setlocal nospell') Vim.command('setlocal buftype=nofile') Vim.command('setlocal bufhidden=hide') Vim.command('setlocal nomodifiable')
def show(self, name='default'): """ Show the UI buffer. """ Vim.command(f'{self.position} {self.bufs[name].number}sb') Vim.command('wincmd J')
def commit_amend(self): msg = self.cur_repo.commit(amend=True) self.api.render() Vim.Echo(msg)
def position(self): return Vim.Var('NETRSplitOrientation')
def post_commit(self, bufNum): msg = self.cur_repo.commit() self.api.render(bufNum) Vim.Echo(msg)
def unmodify(self, fullpath): ans = Vim.UserInput("This will discard any made changes. Proceed " "anyway? (y/n)") if ans == 'y': self.run_cmd('checkout {}'.format(fullpath))
def on_stderr(job_id, err_msg): ind = err_msg.rfind('FSServerException: ') if ind > 0: err_msg = err_msg[ind + 19:] Vim.ErrorMsg(err_msg)
def RegisterHookerVimFn(self, hooker, fn): self.Hookers[hooker].append( lambda api: Vim.eval(f'function("{fn}")()'))
def mapvimfn(self, key, fn): self.map(key, lambda: Vim.eval(f'function("{fn}")()'))
def view_plaintext(self): bak_shortmess = Vim.options['shortmess'] Vim.options['shortmess'] = 'A' Vim.command(f'silent edit {self.path}') Vim.options['shortmess'] = bak_shortmess Vim.current.window.options['foldenable'] = False