about summary refs log blame commit diff stats
path: root/cpp/011load.cc
blob: cee2c4935e16443c1e48ab3a8d7a34badcb436dc (plain) (tree)
def unset_bookmark(self, key): """Delete the bookmark with the name <key>""" self.bookmarks.update_if_outdated() del self.bookmarks[str(key)] def draw_bookmarks(self): self.ui.browser.draw_bookmarks = True def hide_bookmarks(self): self.ui.browser.draw_bookmarks = False def draw_possible_programs(self): try: target = self.thistab.get_selection()[0] except: self.ui.browser.draw_info = [] return programs = [program for program in self.rifle.list_commands([target.path], None)] if programs: num_digits = max((len(str(program[0])) for program in programs)) program_info = ['%s | %s' % (str(program[0]).rjust(num_digits), program[1]) for program in programs] self.ui.browser.draw_info = program_info def hide_console_info(self): self.ui.browser.draw_info = False # -------------------------- # -- Pager # -------------------------- # These commands open the built-in pager and set specific sources. def display_command_help(self, console_widget): try: command = console_widget._get_cmd_class() except: self.notify("Feature not available!", bad=True) return if not command: self.notify("Command not found!", bad=True) return if not command.__doc__: self.notify("Command has no docstring. Try using python without -OO", bad=True) return pager = self.ui.open_pager() lines = cleandoc(command.__doc__).split('\n') pager.set_source(lines) def display_help(self): manualpath = self.relpath('../doc/ranger.1') if os.path.exists(manualpath): process = self.run(['man', manualpath]) if process.poll() != 16: return process = self.run(['man', 'ranger']) if process.poll() == 16: self.notify("Could not find manpage.", bad=True) def display_log(self): pager = self.ui.open_pager() if self.log: pager.set_source(["Message Log:"] + list(self.log)) else: pager.set_source(["Message Log:", "No messages!"]) def display_file(self): if not self.thisfile or not self.thisfile.is_file: return pager = self.ui.open_pager() f = self.thisfile.get_preview_source(pager.wid, pager.hei) if self.thisfile.is_image_preview(): pager.set_image(f) else: pager.set_source(f) # -------------------------- # -- Previews # -------------------------- def update_preview(self, path): try: del self.previews[path] self.ui.need_redraw = True except: return False if version_info[0] == 3: def sha1_encode(self, path): return os.path.join(ranger.arg.cachedir, sha1(path.encode('utf-8', 'backslashreplace')) \ .hexdigest()) + '.jpg' else: def sha1_encode(self, path): return os.path.join(ranger.arg.cachedir, sha1(path).hexdigest()) + '.jpg' def get_preview(self, file, width, height): pager = self.ui.get_pager() path = file.realpath if not path or not os.path.exists(path): return None if self.settings.preview_script and self.settings.use_preview_script: # self.previews is a 2 dimensional dict: # self.previews['/tmp/foo.jpg'][(80, 24)] = "the content..." # self.previews['/tmp/foo.jpg']['loading'] = False # A -1 in tuples means "any"; (80, -1) = wid. of 80 and any hei. # The key 'foundpreview' is added later. Values in (True, False) # XXX: Previews can break when collapse_preview is on and the # preview column is popping out as you move the cursor on e.g. a # PDF file. try: data = self.previews[path] except: data = self.previews[path] = {'loading': False} else: if data['loading']: return None found = data.get((-1, -1), data.get((width, -1), data.get((-1, height), data.get((width, height), False)))) if found == False: try: stat_ = os.stat(self.settings.preview_script) except: self.fm.notify("Preview Script `%s' doesn't exist!" % self.settings.preview_script, bad=True) return None if not stat_.st_mode & S_IEXEC: self.fm.notify("Preview Script `%s' is not executable!" % self.settings.preview_script, bad=True) return None data['loading'] = True if 'directimagepreview' in data: data['foundpreview'] = True data['imagepreview'] = True pager.set_image(path) data['loading'] = False return path cacheimg = os.path.join(ranger.arg.cachedir, self.sha1_encode(path)) if (os.path.isfile(cacheimg) and os.path.getmtime(cacheimg) > os.path.getmtime(path)): data['foundpreview'] = True data['imagepreview'] = True pager.set_image(cacheimg) data['loading'] = False return cacheimg loadable = CommandLoader(args=[self.settings.preview_script, path, str(width), str(height), cacheimg, str(self.settings.preview_images)], read=True, silent=True, descr="Getting preview of %s" % path) def on_after(signal): exit = signal.process.poll() content = signal.loader.stdout_buffer data['foundpreview'] = True if exit == 0: data[(width, height)] = content elif exit == 3: data[(-1, height)] = content elif exit == 4: data[(width, -1)] = content elif exit == 5: data[(-1, -1)] = content elif exit == 6: data['imagepreview'] = True elif exit == 7: data['directimagepreview'] = True elif exit == 1: data[(-1, -1)] = None data['foundpreview'] = False elif exit == 2: f = codecs.open(path, 'r', errors='ignore') try: data[(-1, -1)] = f.read(1024 * 32) except UnicodeDecodeError: f.close() f = codecs.open(path, 'r', encoding='latin-1', errors='ignore') data[(-1, -1)] = f.read(1024 * 32) f.close() else: data[(-1, -1)] = None if self.thisfile and self.thisfile.realpath == path: self.ui.browser.need_redraw = True data['loading'] = False pager = self.ui.get_pager() if self.thisfile and self.thisfile.is_file: if 'imagepreview' in data: pager.set_image(cacheimg) return cacheimg elif 'directimagepreview' in data: pager.set_image(path) return path else: pager.set_source(self.thisfile.get_preview_source( pager.wid, pager.hei)) def on_destroy(signal): try: del self.previews[path] except: pass loadable.signal_bind('after', on_after) loadable.signal_bind('destroy', on_destroy) self.loader.add(loadable) return None else: return found else: try: return codecs.open(path, 'r', errors='ignore') except: return None # -------------------------- # -- Tabs # -------------------------- def tab_open(self, name, path=None): tab_has_changed = (name != self.current_tab) self.current_tab = name previous_tab = self.thistab try: tab = self.tabs[name] except KeyError: # create a new tab tab = Tab(self.thistab.path) self.tabs[name] = tab self.thistab = tab tab.enter_dir(tab.path, history=False) if path: tab.enter_dir(path, history=True) if previous_tab: tab.inherit_history(previous_tab.history) else: self.thistab = tab if path: tab.enter_dir(path, history=True) else: tab.enter_dir(tab.path, history=False) if tab_has_changed: self.change_mode('normal') self.signal_emit('tab.change', old=previous_tab, new=self.thistab) self.signal_emit('tab.layoutchange') def tab_close(self, name=None): if name is None: name = self.current_tab tab = self.tabs[name] if name == self.current_tab: direction = -1 if name == self._get_tab_list()[-1] else 1 previous = self.current_tab self.tab_move(direction) if previous == self.current_tab: return # can't close last tab if name in self.tabs: del self.tabs[name] self.restorable_tabs.append(tab) self.signal_emit('tab.layoutchange') def tab_restore(self): # NOTE: The name of the tab is not restored. previous_tab = self.thistab if self.restorable_tabs: tab = self.restorable_tabs.pop() for name in range(1, len(self.tabs) + 2): if not name in self.tabs: self.current_tab = name self.tabs[name] = tab tab.enter_dir(tab.path, history=False) self.thistab = tab self.change_mode('normal') self.signal_emit('tab.change', old=previous_tab, new=self.thistab) break def tab_move(self, offset, narg=None): if narg: return self.tab_open(narg) assert isinstance(offset, int) tablist = self._get_tab_list() current_index = tablist.index(self.current_tab) newtab = tablist[(current_index + offset) % len(tablist)] if newtab != self.current_tab: self.tab_open(newtab) def tab_new(self, path=None, narg=None): if narg: return self.tab_open(narg, path) for i in range(1, 10): if not i in self.tabs: return self.tab_open(i, path) def tab_switch(self, path, create_directory=False): """Switches to tab of given path, opening a new tab as necessary. If path does not exist, it is treated as a directory. """ path = realpath(path) if not os.path.exists(path): file_selection = None if create_directory: try: os.makedirs(path, exist_ok=True) except OSError as err: self.fm.notify(err, bad=True) return target_directory = path else: # Give benefit of the doubt. potential_parent = os.path.dirname(path) if os.path.exists(potential_parent) and os.path.isdir(potential_parent): target_directory = potential_parent else: self.fm.notify("Unable to resolve given path.", bad=True) return elif os.path.isdir(path): file_selection = None target_directory = path else: file_selection = path target_directory = os.path.dirname(path) for name in self.fm.tabs: tab = self.fm.tabs[name] # Is a tab already open? if tab.path == target_directory: self.fm.tab_open(name=name) if file_selection: self.fm.select_file(file_selection) return self.fm.tab_new(path=target_directory) if file_selection: self.fm.select_file(file_selection) def _get_tab_list(self): assert len(self.tabs) > 0, "There must be >=1 tabs at all times" return sorted(self.tabs) # -------------------------- # -- Overview of internals # -------------------------- def dump_keybindings(self, *contexts): if not contexts: contexts = 'browser', 'console', 'pager', 'taskview' temporary_file = tempfile.NamedTemporaryFile() def write(string): temporary_file.write(string.encode('utf-8')) def recurse(before, pointer): for key, value in pointer.items(): keys = before + [key] if isinstance(value, dict): recurse(keys, value) else: write("%12s %s\n" % (construct_keybinding(keys), value)) for context in contexts: write("Keybindings in `%s'\n" % context) if context in self.fm.ui.keymaps: recurse([], self.fm.ui.keymaps[context]) else: write(" None\n") write("\n") temporary_file.flush() pager = os.environ.get('PAGER', ranger.DEFAULT_PAGER) self.run([pager, temporary_file.name]) def dump_commands(self): temporary_file = tempfile.NamedTemporaryFile() def write(string): temporary_file.write(string.encode('utf-8')) undocumented = [] for cmd_name in sorted(self.commands.commands): cmd = self.commands.commands[cmd_name] if hasattr(cmd, '__doc__') and cmd.__doc__: doc = cleandoc(cmd.__doc__) if doc[0] == ':': write(doc) write("\n\n" + "-" * 60 + "\n") else: undocumented.append(cmd) if undocumented: write("Undocumented commands:\n\n") for cmd in undocumented: write(" :%s\n" % cmd.get_name()) temporary_file.flush() pager = os.environ.get('PAGER', ranger.DEFAULT_PAGER) self.run([pager, temporary_file.name]) def dump_settings(self): temporary_file = tempfile.NamedTemporaryFile() def write(string): temporary_file.write(string.encode('utf-8')) for setting in sorted(ALLOWED_SETTINGS): write("%30s = %s\n" % (setting, getattr(self.settings, setting))) temporary_file.flush() pager = os.environ.get('PAGER', ranger.DEFAULT_PAGER) self.run([pager, temporary_file.name]) # -------------------------- # -- File System Operations # -------------------------- def uncut(self): """:uncut Empty the copy buffer. """ self.copy_buffer = set() self.do_cut = False self.ui.browser.main_column.request_redraw() def copy(self, mode='set', narg=None, dirarg=None): """:copy [mode=set] Copy the selected items. Modes are: 'set', 'add', 'remove'. """ assert mode in ('set', 'add', 'remove', 'toggle') cwd = self.thisdir if not narg and not dirarg: selected = (f for f in self.thistab.get_selection() if f in cwd.files) else: if not dirarg and narg: direction = Direction(down=1) offset = 0 else: direction = Direction(dirarg) offset = 1 pos, selected = direction.select( override=narg, lst=cwd.files, current=cwd.pointer, pagesize=self.ui.termsize[0], offset=offset) cwd.pointer = pos cwd.correct_pointer() if mode == 'set': self.copy_buffer = set(selected) elif mode == 'add': self.copy_buffer.update(set(selected)) elif mode == 'remove': self.copy_buffer.difference_update(set(selected)) elif mode == 'toggle': self.copy_buffer.symmetric_difference_update(set(selected)) self.do_cut = False self.ui.browser.main_column.request_redraw() def cut(self, mode='set', narg=None, dirarg=None): """:cut [mode=set] Cut the selected items. Modes are: 'set, 'add, 'remove. """ self.copy(mode=mode, narg=narg, dirarg=dirarg) self.do_cut = True self.ui.browser.main_column.request_redraw() def paste_symlink(self, relative=False): copied_files = self.copy_buffer for f in copied_files: self.notify(next_available_filename(f.basename)) try: new_name = next_available_filename(f.basename) if relative: relative_symlink(f.path, join(getcwd(), new_name)) else: symlink(f.path, join(getcwd(), new_name)) except Exception as x: self.notify(x) def paste_hardlink(self): for f in self.copy_buffer: try: new_name = next_available_filename(f.basename) link(f.path, join(getcwd(), new_name)) except Exception as x: self.notify(x) def paste_hardlinked_subtree(self): for f in self.copy_buffer: try: target_path = join(getcwd(), f.basename) self._recurse_hardlinked_tree(f.path, target_path) except Exception as x: self.notify(x) def _recurse_hardlinked_tree(self, source_path, target_path): if isdir(source_path): if not exists(target_path): os.mkdir(target_path, stat(source_path).st_mode) for item in listdir(source_path): self._recurse_hardlinked_tree( join(source_path, item), join(target_path, item)) else: if not exists(target_path) \ or stat(source_path).st_ino != stat(target_path).st_ino: link(source_path, next_available_filename(target_path)) def paste(self, overwrite=False, append=False): """:paste Paste the selected items into the current directory. """ loadable = CopyLoader(self.copy_buffer, self.do_cut, overwrite) self.loader.add(loadable, append=append) self.do_cut = False def delete(self, files=None): # XXX: warn when deleting mount points/unseen marked files? self.notify("Deleting!") # COMPAT: old command.py use fm.delete() without arguments if files is None: files = (f.path for f in self.thistab.get_selection()) files = [os.path.abspath(f) for f in files] for f in files: # Untag the deleted files. for tag in self.fm.tags.tags: if str(tag).startswith(f): self.fm.tags.remove(tag) self.copy_buffer = set(filter(lambda f: f.path not in files, self.copy_buffer)) for f in files: if isdir(f) and not os.path.islink(f): try: shutil.rmtree(f) except OSError as err: self.notify(err) else: try: os.remove(f) except OSError as err: self.notify(err) self.thistab.ensure_correct_pointer() def mkdir(self, name): try: os.makedirs(os.path.join(self.thisdir.path, name)) except OSError as err: self.notify(err) def rename(self, src, dest): if hasattr(src, 'path'): src = src.path try: os.makedirs(os.path.dirname(dest)) except OSError: pass try: os.rename(src, dest) except OSError as err: self.notify(err) return False return True