summary refs log tree commit diff stats
diff options
context:
space:
mode:
authornfnty <git@nfnty.se>2017-02-04 11:40:58 +0100
committernfnty <git@nfnty.se>2017-02-04 11:42:38 +0100
commitb108f821d0838aaa5fea11a52c3620aec33a5340 (patch)
treec9ba4701e841a9007cc2facfa943f3b1544a10e9
parent8e8493e93ec705b5296684d5884794dd446d9116 (diff)
downloadranger-b108f821d0838aaa5fea11a52c3620aec33a5340.tar.gz
api.commands: Refactor function and alias commands
-rw-r--r--ranger/api/commands.py124
-rw-r--r--ranger/core/actions.py9
2 files changed, 64 insertions, 69 deletions
diff --git a/ranger/api/commands.py b/ranger/api/commands.py
index f5011232..763e2fef 100644
--- a/ranger/api/commands.py
+++ b/ranger/api/commands.py
@@ -16,6 +16,8 @@ import ranger
 from ranger.core.shared import FileManagerAware
 from ranger.ext.lazy_property import lazy_property
 
+__all__ = ['Command']
+
 _SETTINGS_RE = re.compile(r'^\s*([^\s]+?)=(.*)$')
 _ALIAS_LINE_RE = re.compile(r'(\s+)')
 
@@ -35,18 +37,12 @@ class CommandContainer(FileManagerAware):
         except KeyError:
             self.fm.notify('alias failed: No such command: {0}'.format(cmd_name), bad=True)
             return None
-
-        class CommandAlias(cmd):   # pylint: disable=too-few-public-methods
-            def __init__(self, line, *args, **kwargs):
-                super(CommandAlias, self).__init__(
-                    (self.full_command + ''.join(_ALIAS_LINE_RE.split(line)[1:])), *args, **kwargs)
-        self.commands[name] = type(name, (CommandAlias,), dict(full_command=full_command))
+        self.commands[name] = command_alias_factory(name, cmd, full_command)
 
     def load_commands_from_module(self, module):
         for var in vars(module).values():
             try:
-                if issubclass(var, Command) and var != Command \
-                        and var != FunctionCommand:
+                if issubclass(var, Command) and var != Command:
                     self.commands[var.get_name()] = var
             except TypeError:
                 pass
@@ -57,11 +53,7 @@ class CommandContainer(FileManagerAware):
                 continue
             attribute = getattr(obj, attribute_name)
             if hasattr(attribute, '__call__'):
-                cmd = type(attribute_name, (FunctionCommand,), dict(__doc__=attribute.__doc__))
-                cmd.based_function = attribute
-                cmd.function_name = attribute.__name__
-                cmd.object_name = obj.__class__.__name__
-                self.commands[attribute_name] = cmd
+                self.commands[attribute_name] = command_function_factory(attribute)
 
     def get_command(self, name, abbrev=True):
         if abbrev:
@@ -371,62 +363,68 @@ class Command(FileManagerAware):
         return (self.start(1) + program for program in programs)
 
 
-class FunctionCommand(Command):
-    based_function = None
-    object_name = ""
-    function_name = "unknown"
-
-    def execute(self):  # pylint: disable=too-many-branches
-        if not self.based_function:
-            return
-        if len(self.args) == 1:
-            try:
-                return self.based_function(  # pylint: disable=not-callable
-                    **{'narg': self.quantifier})
-            except TypeError:
-                return self.based_function()  # pylint: disable=not-callable
+def command_alias_factory(name, cls, full_command):
+    class CommandAlias(cls):   # pylint: disable=too-few-public-methods
+        __name__ = name
 
-        args, keywords = list(), dict()
-        for arg in self.args[1:]:
-            equal_sign = arg.find("=")
-            value = arg if equal_sign == -1 else arg[equal_sign + 1:]
-            try:
-                value = int(value)
-            except ValueError:
-                if value in ('True', 'False'):
-                    value = (value == 'True')
-                else:
-                    try:
-                        value = float(value)
-                    except ValueError:
-                        pass
+        def __init__(self, line, *args, **kwargs):
+            super(CommandAlias, self).__init__(
+                (full_command + ''.join(_ALIAS_LINE_RE.split(line)[1:])), *args, **kwargs)
+    return CommandAlias
 
-            if equal_sign == -1:
-                args.append(value)
-            else:
-                keywords[arg[:equal_sign]] = value
 
-        if self.quantifier is not None:
-            keywords['narg'] = self.quantifier
+def command_function_factory(func):
+    class CommandFunction(Command):
+        __name__ = func.__name__
+        __doc__ = func.__doc__
 
-        try:
-            if self.quantifier is None:
-                return self.based_function(*args, **keywords)  # pylint: disable=not-callable
-            else:
+        def execute(self):  # pylint: disable=too-many-branches
+            if not func:
+                return
+            if len(self.args) == 1:
                 try:
-                    return self.based_function(*args, **keywords)  # pylint: disable=not-callable
+                    return func(**{'narg': self.quantifier})
                 except TypeError:
-                    del keywords['narg']
-                    return self.based_function(*args, **keywords)  # pylint: disable=not-callable
-        except TypeError:
-            if ranger.args.debug:
-                raise
-            else:
-                self.fm.notify(
-                    "Bad arguments for %s.%s: %s, %s" % (
-                        self.object_name, self.function_name, repr(args), repr(keywords)),
-                    bad=True,
-                )
+                    return func()
+
+            args, kwargs = list(), dict()
+            for arg in self.args[1:]:
+                equal_sign = arg.find("=")
+                value = arg if equal_sign == -1 else arg[equal_sign + 1:]
+                try:
+                    value = int(value)
+                except ValueError:
+                    if value in ('True', 'False'):
+                        value = (value == 'True')
+                    else:
+                        try:
+                            value = float(value)
+                        except ValueError:
+                            pass
+
+                if equal_sign == -1:
+                    args.append(value)
+                else:
+                    kwargs[arg[:equal_sign]] = value
+
+            if self.quantifier is not None:
+                kwargs['narg'] = self.quantifier
+
+            try:
+                if self.quantifier is None:
+                    return func(*args, **kwargs)
+                else:
+                    try:
+                        return func(*args, **kwargs)
+                    except TypeError:
+                        del kwargs['narg']
+                        return func(*args, **kwargs)
+            except TypeError:
+                if ranger.args.debug:
+                    raise
+                self.fm.notify("Bad arguments for %s: %s, %s" % (func.__name__, args, kwargs),
+                               bad=True)
+    return CommandFunction
 
 
 if __name__ == '__main__':
diff --git a/ranger/core/actions.py b/ranger/core/actions.py
index 29e1f69f..c78f61e2 100644
--- a/ranger/core/actions.py
+++ b/ranger/core/actions.py
@@ -239,8 +239,7 @@ class Actions(  # pylint: disable=too-many-instance-attributes,too-many-public-m
             except ValueError as ex:
                 if ranger.args.debug:
                     raise
-                else:
-                    return self.notify(ex)
+                return self.notify(ex)
             cmd.init_line(line)
 
         try:
@@ -248,8 +247,7 @@ class Actions(  # pylint: disable=too-many-instance-attributes,too-many-public-m
         except Exception as ex:  # pylint: disable=broad-except
             if ranger.args.debug:
                 raise
-            else:
-                self.notify(ex)
+            self.notify(ex)
 
     def substitute_macros(self, string,  # pylint: disable=redefined-outer-name
                           additional=None, escape=False):
@@ -384,8 +382,7 @@ class Actions(  # pylint: disable=too-many-instance-attributes,too-many-public-m
                 except Exception as ex:  # pylint: disable=broad-except
                     if ranger.args.debug:
                         raise
-                    else:
-                        self.notify('Error in line `%s\':\n  %s' % (line, str(ex)), bad=True)
+                    self.notify('Error in line `%s\':\n  %s' % (line, str(ex)), bad=True)
 
     def execute_file(self, files, **kw):
         """Uses the "rifle" module to open/execute a file