diff options
-rw-r--r-- | ranger/api/commands.py | 1 | ||||
-rw-r--r-- | ranger/core/actions.py | 90 | ||||
-rw-r--r-- | ranger/defaults/commands.py | 2 | ||||
-rw-r--r-- | ranger/gui/widgets/console.py | 10 |
4 files changed, 52 insertions, 51 deletions
diff --git a/ranger/api/commands.py b/ranger/api/commands.py index 74a8ff99..1941de2c 100644 --- a/ranger/api/commands.py +++ b/ranger/api/commands.py @@ -86,6 +86,7 @@ class Command(FileManagerAware): name = None allow_abbrev = True resolve_macros = True + escape_macros_for_shell = False quantifier = None _shifted = 0 diff --git a/ranger/core/actions.py b/ranger/core/actions.py index d0e21fbc..cde80431 100644 --- a/ranger/core/actions.py +++ b/ranger/core/actions.py @@ -98,35 +98,46 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): def execute_console(self, string='', wildcards=[], quantifier=None): """Execute a command for the console""" command_name = string.split()[0] - try: - cmd_class = self.commands.get_command(command_name) - except: + cmd_class = self.commands.get_command(command_name, abbrev=False) + if cmd_class is None: self.notify("Command not found: `%s'" % command_name, bad=True) - else: - 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)) - if 'any0' in macros: - macros['any'] = macros['any0'] - try: - string = self.substitute_macros(string, additional=macros) - except ValueError as e: - if ranger.arg.debug: - raise - else: - return self.notify(e) + return + 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)) + if 'any0' in macros: + macros['any'] = macros['any0'] try: - cmd_class(string, quantifier=quantifier).execute() - except Exception as e: + string = self.substitute_macros(string, additional=macros, + escape=cmd.escape_macros_for_shell) + except ValueError as e: if ranger.arg.debug: raise else: - self.notify(e) - - def substitute_macros(self, string, additional=dict()): - result = _MacroTemplate(string).safe_substitute(self._get_macros(), - **additional) + return self.notify(e) + try: + cmd_class(string, quantifier=quantifier).execute() + except Exception as e: + if ranger.arg.debug: + raise + else: + self.notify(e) + + def substitute_macros(self, string, additional=dict(), escape=False): + macros = self._get_macros() + macros.update(additional) + if escape: + for key, value in macros.items(): + if isinstance(value, list): + macros[key] = " ".join(shell_quote(s) for s in value) + elif value != MACRO_FAIL: + macros[key] = shell_quote(value) + else: + for key, value in macros.items(): + if isinstance(value, list): + macros[key] = " ".join(value) + result = _MacroTemplate(string).safe_substitute(macros) if MACRO_FAIL in result: raise ValueError("Could not apply macros to `%s'" % string) return result @@ -134,25 +145,22 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): def _get_macros(self): macros = {} - macros['rangerdir'] = shell_quote(ranger.RANGERDIR) + macros['rangerdir'] = ranger.RANGERDIR if self.fm.env.cf: - macros['f'] = shell_quote(self.fm.env.cf.basename) + macros['f'] = self.fm.env.cf.basename else: macros['f'] = MACRO_FAIL - macros['s'] = ' '.join(shell_quote(fl.basename) \ - for fl in self.fm.env.get_selection()) + macros['s'] = [fl.basename for fl in self.fm.env.get_selection()] - macros['c'] = ' '.join(shell_quote(fl.path) - for fl in self.fm.env.copy) + macros['c'] = [fl.path for fl in self.fm.env.copy] - macros['t'] = ' '.join(shell_quote(fl.basename) - for fl in self.fm.env.cwd.files - if fl.realpath in self.fm.tags) + macros['t'] = [fl.basename for fl in self.fm.env.cwd.files + if fl.realpath in self.fm.tags] if self.fm.env.cwd: - macros['d'] = shell_quote(self.fm.env.cwd.path) + macros['d'] = self.fm.env.cwd.path else: macros['d'] = '.' @@ -165,11 +173,10 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): continue tab_dir = self.fm.env.get_directory(tab_dir_path) i = str(i) - macros[i + 'd'] = shell_quote(tab_dir_path) - macros[i + 's'] = ' '.join(shell_quote(fl.path) - for fl in tab_dir.get_selection()) + macros[i + 'd'] = tab_dir_path + macros[i + 's'] = [fl.path for fl in tab_dir.get_selection()] if tab_dir.pointed_obj: - macros[i + 'f'] = shell_quote(tab_dir.pointed_obj.path) + macros[i + 'f'] = tab_dir.pointed_obj.path else: macros[i + 'f'] = MACRO_FAIL @@ -189,13 +196,12 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): next_tab_path = self.fm.tabs[first_tab] next_tab = self.fm.env.get_directory(next_tab_path) - macros['D'] = shell_quote(next_tab) + macros['D'] = next_tab if next_tab.pointed_obj: - macros['F'] = shell_quote(next_tab.pointed_obj.path) + macros['F'] = next_tab.pointed_obj.path else: macros['F'] = MACRO_FAIL - macros['S'] = ' '.join(shell_quote(fl.path) - for fl in next_tab.get_selection()) + macros['S'] = [fl.path for fl in next_tab.get_selection()] return macros diff --git a/ranger/defaults/commands.py b/ranger/defaults/commands.py index 55de33c1..cd76896c 100644 --- a/ranger/defaults/commands.py +++ b/ranger/defaults/commands.py @@ -171,6 +171,8 @@ class search_inc(Command): class shell(Command): + escape_macros_for_shell = True + def execute(self): line = parse(self.line) if line.chunk(1) and line.chunk(1)[0] == '-': diff --git a/ranger/gui/widgets/console.py b/ranger/gui/widgets/console.py index 5fcea9d3..ce801a7f 100644 --- a/ranger/gui/widgets/console.py +++ b/ranger/gui/widgets/console.py @@ -294,15 +294,7 @@ class Console(Widget): def execute(self, cmd=None): self.allow_close = True - if cmd is None: - cmd = self._get_cmd() - - if cmd: - try: - cmd.execute() - except Exception as error: - self.fm.notify(error) - + self.fm.execute_console(self.line) if self.allow_close: self.close(trigger_cancel_function=False) |