diff options
Diffstat (limited to 'ranger/core/actions.py')
-rw-r--r-- | ranger/core/actions.py | 255 |
1 files changed, 136 insertions, 119 deletions
diff --git a/ranger/core/actions.py b/ranger/core/actions.py index 05529000..4f3338d2 100644 --- a/ranger/core/actions.py +++ b/ranger/core/actions.py @@ -1,14 +1,15 @@ # This file is part of ranger, the console file manager. # License: GNU GPL version 3, see the file "AUTHORS" for details. +# pylint: disable=too-many-lines import codecs import os +from os import link, symlink, getcwd, listdir, stat +from os.path import join, isdir, realpath, exists import re import shutil import string import tempfile -from os.path import join, isdir, realpath, exists -from os import link, symlink, getcwd, listdir, stat from inspect import cleandoc from stat import S_IEXEC from hashlib import sha1 @@ -28,11 +29,10 @@ from ranger.container.directory import Directory from ranger.container.file import File from ranger.core.loader import CommandLoader, CopyLoader from ranger.container.settings import ALLOWED_SETTINGS, ALLOWED_VALUES -from ranger.core.linemode import DEFAULT_LINEMODE MACRO_FAIL = "<\x01\x01MACRO_HAS_NO_VALUE\x01\01>" -log = getLogger(__name__) +LOG = getLogger(__name__) class _MacroTemplate(string.Template): @@ -41,12 +41,15 @@ class _MacroTemplate(string.Template): idpattern = r"[_a-z0-9]*" -class Actions(FileManagerAware, SettingsAware): +class Actions( # pylint: disable=too-many-instance-attributes,too-many-public-methods + FileManagerAware, SettingsAware): + # -------------------------- # -- Basic Commands # -------------------------- - def exit(self): + @staticmethod + def exit(): """:exit Exit the program. @@ -105,7 +108,7 @@ class Actions(FileManagerAware, SettingsAware): return False elif value.lower() in ('true', 'on', '1'): return True - if type(None) in types and value.lower() == 'none': + if isinstance(None, types) and value.lower() == 'none': return None if int in types: try: @@ -151,12 +154,12 @@ class Actions(FileManagerAware, SettingsAware): """ if isinstance(text, Exception): if ranger.arg.debug: - raise + raise text bad = True elif bad is True and ranger.arg.debug: raise Exception(str(text)) text = str(text) - log.debug("Command notify invoked: [Bad: {0}, Text: '{1}']".format(bad, text)) + LOG.debug("Command notify invoked: [Bad: %s, Text: '%s']", bad, text) if self.ui and self.ui.is_on: self.ui.status.notify(" ".join(text.split("\n")), duration=duration, bad=bad) @@ -177,8 +180,8 @@ class Actions(FileManagerAware, SettingsAware): self.loader.remove(index=0) def get_cumulative_size(self): - for f in self.thistab.get_selection() or (): - f.look_up_cumulative_size() + for fobj in self.thistab.get_selection() or (): + fobj.look_up_cumulative_size() self.ui.status.request_redraw() self.ui.redraw_main_column() @@ -189,7 +192,8 @@ class Actions(FileManagerAware, SettingsAware): """ self.ui.redraw_window() - def open_console(self, string='', prompt=None, position=None): + def open_console(self, string='', # pylint: disable=redefined-outer-name + prompt=None, position=None): """:open_console [string] Open the console. @@ -197,7 +201,8 @@ class Actions(FileManagerAware, SettingsAware): self.change_mode('normal') self.ui.open_console(string, prompt=prompt, position=position) - def execute_console(self, string='', wildcards=[], quantifier=None): + def execute_console(self, string='', # pylint: disable=redefined-outer-name + wildcards=None, quantifier=None): """:execute_console [string] Execute a command for the console @@ -210,28 +215,30 @@ class Actions(FileManagerAware, SettingsAware): cmd = cmd_class(string) if cmd.resolve_macros and _MacroTemplate.delimiter in string: macros = dict(('any%d' % i, key_to_string(char)) - for i, char in enumerate(wildcards)) + for i, char in enumerate(wildcards if wildcards is not None else [])) if 'any0' in macros: macros['any'] = macros['any0'] try: string = self.substitute_macros(string, additional=macros, escape=cmd.escape_macros_for_shell) - except ValueError as e: + except ValueError as ex: if ranger.arg.debug: raise else: - return self.notify(e) + return self.notify(ex) try: cmd_class(string, quantifier=quantifier).execute() - except Exception as e: + except Exception as ex: if ranger.arg.debug: raise else: - self.notify(e) + self.notify(ex) - def substitute_macros(self, string, additional=dict(), escape=False): + def substitute_macros(self, string, # pylint: disable=redefined-outer-name + additional=None, escape=False): macros = self._get_macros() - macros.update(additional) + if additional: + macros.update(additional) if escape: for key, value in macros.items(): if isinstance(value, list): @@ -247,7 +254,7 @@ class Actions(FileManagerAware, SettingsAware): raise ValueError("Could not apply macros to `%s'" % string) return result - def _get_macros(self): + def _get_macros(self): # pylint: disable=too-many-branches,too-many-statements macros = {} macros['rangerdir'] = ranger.RANGERDIR @@ -274,7 +281,7 @@ class Actions(FileManagerAware, SettingsAware): if self.fm.thisdir.files: macros['t'] = [fl.relative_path for fl in self.fm.thisdir.files - if fl.realpath in (self.fm.tags or [])] + if fl.realpath in self.fm.tags or []] else: macros['t'] = MACRO_FAIL @@ -348,20 +355,20 @@ class Actions(FileManagerAware, SettingsAware): Load a config file. """ filename = os.path.expanduser(filename) - log.debug("Sourcing config file '{0}'".format(filename)) - with open(filename, 'r') as f: - for line in f: + LOG.debug("Sourcing config file '%s'", filename) + with open(filename, 'r') as fobj: + for line in fobj: line = line.strip(" \r\n") if line.startswith("#") or not line.strip(): continue try: self.execute_console(line) - except Exception as e: + except Exception as ex: if ranger.arg.debug: raise else: self.notify('Error in line `%s\':\n %s' % - (line, str(e)), bad=True) + (line, str(ex)), bad=True) def execute_file(self, files, **kw): """Uses the "rifle" module to open/execute a file @@ -385,14 +392,14 @@ class Actions(FileManagerAware, SettingsAware): if ranger.arg.choosefiles: open(ranger.arg.choosefiles, 'w').write("".join( - f.path + "\n" for f in self.fm.thistab.get_selection())) + fobj.path + "\n" for fobj in self.fm.thistab.get_selection())) if ranger.arg.choosefile or ranger.arg.choosefiles: raise SystemExit() if isinstance(files, set): files = list(files) - elif type(files) not in (list, tuple): + elif not isinstance(files, (list, tuple)): files = [files] flags = kw.get('flags', '') @@ -400,7 +407,7 @@ class Actions(FileManagerAware, SettingsAware): files = [self.fm.thisfile] self.signal_emit('execute.before', keywords=kw) - filenames = [f.path for f in files] + filenames = [fobj.path for fobj in files] label = kw.get('label', kw.get('app', None)) try: return self.rifle.execute(filenames, mode, label, flags, None) @@ -411,7 +418,7 @@ class Actions(FileManagerAware, SettingsAware): # -- Moving Around # -------------------------- - def move(self, narg=None, **kw): + def move(self, narg=None, **kw): # pylint: disable=too-many-locals,too-many-branches """A universal movement method. Accepts these parameters: @@ -443,9 +450,9 @@ class Actions(FileManagerAware, SettingsAware): mode = 0 if narg is not None: mode = narg - cf = self.thisfile + tfile = self.thisfile selection = self.thistab.get_selection() - if not self.thistab.enter_dir(cf) and selection: + if not self.thistab.enter_dir(tfile) and selection: result = self.execute_file(selection, mode=mode) if result in (False, ASK_COMMAND): self.open_console('open_with ') @@ -473,15 +480,15 @@ class Actions(FileManagerAware, SettingsAware): # Set theory anyone? if not self._visual_reverse: - for f in targets - current: - cwd.mark_item(f, True) - for f in current - old - targets: - cwd.mark_item(f, False) + for fobj in targets - current: + cwd.mark_item(fobj, True) + for fobj in current - old - targets: + cwd.mark_item(fobj, False) else: - for f in targets & current: - cwd.mark_item(f, False) - for f in old - current - targets: - cwd.mark_item(f, True) + for fobj in targets & current: + cwd.mark_item(fobj, False) + for fobj in old - current - targets: + cwd.mark_item(fobj, True) if self.ui.pager.visible: self.display_file() @@ -521,8 +528,8 @@ class Actions(FileManagerAware, SettingsAware): cdpath = os.environ.get('CDPATH', None) or os.environ.get('cdpath', None) result = self.thistab.enter_dir(path, history=history) if result is False and cdpath: - for p in cdpath.split(':'): - curpath = os.path.join(p, path) + for comp in cdpath.split(':'): + curpath = os.path.join(comp, path) if os.path.isdir(curpath): result = self.thistab.enter_dir(curpath, history=history) break @@ -532,16 +539,16 @@ class Actions(FileManagerAware, SettingsAware): self.change_mode('normal') return result - def cd(self, path, remember=True): + def cd(self, path, remember=True): # pylint: disable=invalid-name """enter the directory at the given path, remember=True""" self.enter_dir(path, remember=remember) def traverse(self): self.change_mode('normal') - cf = self.thisfile + tfile = self.thisfile cwd = self.thisdir - if cf is not None and cf.is_directory: - self.enter_dir(cf.path) + if tfile is not None and tfile.is_directory: + self.enter_dir(tfile.path) elif cwd.pointer >= len(cwd) - 1: while True: self.move(left=1) @@ -594,7 +601,7 @@ class Actions(FileManagerAware, SettingsAware): return self.execute_file(file, label='editor') - def toggle_option(self, string): + def toggle_option(self, string): # pylint: disable=redefined-outer-name """:toggle_option <string> Toggle a boolean option named <string>. @@ -627,7 +634,8 @@ class Actions(FileManagerAware, SettingsAware): if func is not None: self.settings['sort'] = str(func) - def mark_files(self, all=False, toggle=False, val=None, movedown=None, narg=None): + def mark_files(self, all=False, # pylint: disable=redefined-builtin,too-many-arguments + toggle=False, val=None, movedown=None, narg=None): """A wrapper for the directory.mark_xyz functions. Arguments: @@ -714,11 +722,14 @@ class Actions(FileManagerAware, SettingsAware): if arg is None: return False if hasattr(arg, 'search'): - fnc = lambda x: arg.search(x.basename) + def fnc(obj): + return arg.search(obj.basename) else: - fnc = lambda x: arg in x.basename + def fnc(obj): + return arg in obj.basename elif order == 'tag': - fnc = lambda x: x.realpath in self.tags + def fnc(obj): + return obj.realpath in self.tags return self.thisdir.search_fnc(fnc=fnc, offset=offset, forward=forward) @@ -727,22 +738,27 @@ class Actions(FileManagerAware, SettingsAware): if original_order is not None or not cwd.cycle_list: lst = list(cwd.files) if order == 'size': - fnc = lambda item: -item.size + def fnc(item): + return -item.size elif order == 'mimetype': - fnc = lambda item: item.mimetype or '' + def fnc(item): + return item.mimetype or '' elif order == 'ctime': - fnc = lambda item: -int(item.stat and item.stat.st_ctime) + def fnc(item): + return -int(item.stat and item.stat.st_ctime) elif order == 'atime': - fnc = lambda item: -int(item.stat and item.stat.st_atime) + def fnc(item): + return -int(item.stat and item.stat.st_atime) elif order == 'mtime': - fnc = lambda item: -int(item.stat and item.stat.st_mtime) + def fnc(item): + return -int(item.stat and item.stat.st_mtime) lst.sort(key=fnc) cwd.set_cycle_list(lst) return cwd.cycle(forward=None) return cwd.cycle(forward=forward) - def set_search_method(self, order, forward=True): + def set_search_method(self, order, forward=True): # pylint: disable=unused-argument if order in ('search', 'tag', 'size', 'mimetype', 'ctime', 'mtime', 'atime'): self.search_method = order @@ -845,7 +861,7 @@ class Actions(FileManagerAware, SettingsAware): def display_command_help(self, console_widget): try: - command = console_widget._get_cmd_class() + command = console_widget._get_cmd_class() # pylint: disable=protected-access except Exception: self.notify("Feature not available!", bad=True) return @@ -887,11 +903,11 @@ class Actions(FileManagerAware, SettingsAware): return pager = self.ui.open_pager() - f = self.thisfile.get_preview_source(pager.wid, pager.hei) + fobj = self.thisfile.get_preview_source(pager.wid, pager.hei) if self.thisfile.is_image_preview(): - pager.set_image(f) + pager.set_image(fobj) else: - pager.set_source(f) + pager.set_source(fobj) # -------------------------- # -- Previews @@ -903,17 +919,17 @@ class Actions(FileManagerAware, SettingsAware): except Exception: return False - if version_info[0] == 3: - def sha1_encode(self, path): + @staticmethod + def sha1_encode(path): + if version_info[0] < 3: + return os.path.join(ranger.arg.cachedir, + sha1(path).hexdigest()) + '.jpg' + else: 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): + def get_preview(self, file, width, height): # pylint: disable=too-many-return-statements pager = self.ui.get_pager() path = file.realpath @@ -937,8 +953,8 @@ class Actions(FileManagerAware, SettingsAware): if data['loading']: return None - found = data.get((-1, -1), data.get((width, -1), - data.get((-1, height), data.get((width, height), False)))) + found = data.get((-1, -1), data.get( + (width, -1), data.get((-1, height), data.get((width, height), False)))) if found is False: try: stat_ = os.stat(self.settings.preview_script) @@ -962,7 +978,8 @@ class Actions(FileManagerAware, SettingsAware): 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)): + if os.path.isfile(cacheimg) and \ + os.path.getmtime(cacheimg) > os.path.getmtime(path): data['foundpreview'] = True data['imagepreview'] = True pager.set_image(cacheimg) @@ -975,34 +992,34 @@ class Actions(FileManagerAware, SettingsAware): silent=True, descr="Getting preview of %s" % path) def on_after(signal): - exit = signal.process.poll() + rcode = signal.process.poll() content = signal.loader.stdout_buffer data['foundpreview'] = True - if exit == 0: + if rcode == 0: data[(width, height)] = content - elif exit == 3: + elif rcode == 3: data[(-1, height)] = content - elif exit == 4: + elif rcode == 4: data[(width, -1)] = content - elif exit == 5: + elif rcode == 5: data[(-1, -1)] = content - elif exit == 6: + elif rcode == 6: data['imagepreview'] = True - elif exit == 7: + elif rcode == 7: data['directimagepreview'] = True - elif exit == 1: + elif rcode == 1: data[(-1, -1)] = None data['foundpreview'] = False - elif exit == 2: - f = codecs.open(path, 'r', errors='ignore') + elif rcode == 2: + fobj = codecs.open(path, 'r', errors='ignore') try: - data[(-1, -1)] = f.read(1024 * 32) + data[(-1, -1)] = fobj.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() + fobj.close() + fobj = codecs.open(path, 'r', encoding='latin-1', + errors='ignore') + data[(-1, -1)] = fobj.read(1024 * 32) + fobj.close() else: data[(-1, -1)] = None if self.thisfile and self.thisfile.realpath == path: @@ -1020,7 +1037,7 @@ class Actions(FileManagerAware, SettingsAware): pager.set_source(self.thisfile.get_preview_source( pager.wid, pager.hei)) - def on_destroy(signal): + def on_destroy(signal): # pylint: disable=unused-argument try: del self.previews[path] except Exception: @@ -1173,7 +1190,7 @@ class Actions(FileManagerAware, SettingsAware): temporary_file = tempfile.NamedTemporaryFile() - def write(string): + def write(string): # pylint: disable=redefined-outer-name temporary_file.write(string.encode('utf-8')) def recurse(before, pointer): @@ -1199,7 +1216,7 @@ class Actions(FileManagerAware, SettingsAware): def dump_commands(self): temporary_file = tempfile.NamedTemporaryFile() - def write(string): + def write(string): # pylint: disable=redefined-outer-name temporary_file.write(string.encode('utf-8')) undocumented = [] @@ -1225,7 +1242,7 @@ class Actions(FileManagerAware, SettingsAware): def dump_settings(self): temporary_file = tempfile.NamedTemporaryFile() - def write(string): + def write(string): # pylint: disable=redefined-outer-name temporary_file.write(string.encode('utf-8')) for setting in sorted(ALLOWED_SETTINGS): @@ -1257,7 +1274,7 @@ class Actions(FileManagerAware, SettingsAware): 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) + selected = (fobj for fobj in self.thistab.get_selection() if fobj in cwd.files) else: if not dirarg and narg: direction = Direction(down=1) @@ -1293,32 +1310,32 @@ class Actions(FileManagerAware, SettingsAware): def paste_symlink(self, relative=False): copied_files = self.copy_buffer - for f in copied_files: - self.notify(next_available_filename(f.basename)) + for fobj in copied_files: + self.notify(next_available_filename(fobj.basename)) try: - new_name = next_available_filename(f.basename) + new_name = next_available_filename(fobj.basename) if relative: - relative_symlink(f.path, join(getcwd(), new_name)) + relative_symlink(fobj.path, join(getcwd(), new_name)) else: - symlink(f.path, join(getcwd(), new_name)) - except Exception as x: - self.notify(x) + symlink(fobj.path, join(getcwd(), new_name)) + except Exception as ex: + self.notify(ex) def paste_hardlink(self): - for f in self.copy_buffer: + for fobj 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) + new_name = next_available_filename(fobj.basename) + link(fobj.path, join(getcwd(), new_name)) + except Exception as ex: + self.notify(ex) def paste_hardlinked_subtree(self): - for f in self.copy_buffer: + for fobj 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) + target_path = join(getcwd(), fobj.basename) + self._recurse_hardlinked_tree(fobj.path, target_path) + except Exception as ex: + self.notify(ex) def _recurse_hardlinked_tree(self, source_path, target_path): if isdir(source_path): @@ -1348,23 +1365,23 @@ class Actions(FileManagerAware, SettingsAware): 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: + files = (fobj.path for fobj in self.thistab.get_selection()) + files = [os.path.abspath(path) for path in files] + for path in files: # Untag the deleted files. for tag in self.fm.tags.tags: - if str(tag).startswith(f): + if str(tag).startswith(path): 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): + self.copy_buffer = set(filter(lambda fobj: fobj.path not in files, self.copy_buffer)) + for path in files: + if isdir(path) and not os.path.islink(path): try: - shutil.rmtree(f) + shutil.rmtree(path) except OSError as err: self.notify(err) else: try: - os.remove(f) + os.remove(path) except OSError as err: self.notify(err) self.thistab.ensure_correct_pointer() |