summary refs log tree commit diff stats
path: root/ranger/core/actions.py
diff options
context:
space:
mode:
Diffstat (limited to 'ranger/core/actions.py')
-rw-r--r--ranger/core/actions.py255
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()