summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ranger/api/commands.py10
-rw-r--r--ranger/config/commands.py36
-rw-r--r--ranger/config/commands_sample.py3
-rw-r--r--ranger/gui/widgets/console.py10
4 files changed, 33 insertions, 26 deletions
diff --git a/ranger/api/commands.py b/ranger/api/commands.py
index ca713d0c..a20adecb 100644
--- a/ranger/api/commands.py
+++ b/ranger/api/commands.py
@@ -6,6 +6,7 @@
 import os
 import ranger
 import re
+import inspect
 from collections import deque
 from ranger.api import *
 from ranger.core.shared import FileManagerAware
@@ -106,7 +107,7 @@ class Command(FileManagerAware):
     def execute(self):
         """Override this"""
 
-    def tab(self):
+    def tab(self, tabnum):
         """Override this"""
 
     def quick(self):
@@ -396,8 +397,11 @@ class AliasCommand(Command):
     def quick(self):
         return self._make_cmd().quick()
 
-    def tab(self):
-        return self._make_cmd().tab()
+    def tab(self, tabnum):
+        cmd = self._make_cmd()
+        args = inspect.signature(cmd.tab).parameters if self.fm.py3 else \
+            inspect.getargspec(cmd.tab).args
+        return cmd.tab(tabnum) if 'tabnum' in args else cmd.tab()
 
     def cancel(self):
         return self._make_cmd().cancel()
diff --git a/ranger/config/commands.py b/ranger/config/commands.py
index a834278d..f5dac9ef 100644
--- a/ranger/config/commands.py
+++ b/ranger/config/commands.py
@@ -21,10 +21,12 @@
 # ===================================================================
 # Every class defined here which is a subclass of `Command' will be used as a
 # command in ranger.  Several methods are defined to interface with ranger:
-#   execute(): called when the command is executed.
-#   cancel():  called when closing the console.
-#   tab():     called when <TAB> is pressed.
-#   quick():   called after each keypress.
+#   execute():   called when the command is executed.
+#   cancel():    called when closing the console.
+#   tab(tabnum): called when <TAB> is pressed.
+#   quick():     called after each keypress.
+#
+# tab() argument tabnum is 1 for <TAB> and -1 for <S-TAB> by default
 #
 # The return values for tab() can be either:
 #   None: There is no tab completion
@@ -135,7 +137,7 @@ class cd(Command):
         else:
             self.fm.cd(destination)
 
-    def tab(self):
+    def tab(self, tabnum):
         import os
         from os.path import dirname, basename, expanduser, join
 
@@ -214,7 +216,7 @@ class shell(Command):
                 command = self.fm.substitute_macros(command, escape=True)
             self.fm.execute_command(command, flags=flags)
 
-    def tab(self):
+    def tab(self, tabnum):
         from ranger.ext.get_executables import get_executables
         if self.arg(1) and self.arg(1)[0] == '-':
             command = self.rest(2)
@@ -248,7 +250,7 @@ class open_with(Command):
                 flags = flags,
                 mode = mode)
 
-    def tab(self):
+    def tab(self, tabnum):
         return self._tab_through_executables()
 
     def _get_app_flags_mode(self, string):
@@ -345,7 +347,7 @@ class set_(Command):
         name, value, _ = self.parse_setting_line()
         self.fm.set_option_from_string(name, value)
 
-    def tab(self):
+    def tab(self, tabnum):
         from ranger.gui.colorscheme import get_all_colorschemes
         name, value, name_done = self.parse_setting_line()
         settings = self.fm.settings
@@ -442,7 +444,7 @@ class default_linemode(Command):
             for col in self.fm.ui.browser.columns:
                 col.need_redraw = True
 
-    def tab(self):
+    def tab(self, tabnum):
         mode = self.arg(1)
         return (self.arg(0) + " " + linemode
                 for linemode in self.fm.thisfile.linemode_dict.keys()
@@ -651,7 +653,7 @@ class mkdir(Command):
         else:
             self.fm.notify("file/directory exists!", bad=True)
 
-    def tab(self):
+    def tab(self, tabnum):
         return self._tab_directory_content()
 
 
@@ -670,7 +672,7 @@ class touch(Command):
         else:
             self.fm.notify("file/directory exists!", bad=True)
 
-    def tab(self):
+    def tab(self, tabnum):
         return self._tab_directory_content()
 
 
@@ -686,7 +688,7 @@ class edit(Command):
         else:
             self.fm.edit_file(self.rest(1))
 
-    def tab(self):
+    def tab(self, tabnum):
         return self._tab_directory_content()
 
 
@@ -766,7 +768,7 @@ class rename(Command):
                 self.fm.tags.tags[t.replace(old_name,new_name)] = tagged[t]
                 self.fm.tags.dump()
 
-    def tab(self):
+    def tab(self, tabnum):
         return self._tab_directory_content()
 
 class rename_append(Command):
@@ -930,7 +932,7 @@ class relink(Command):
         self.fm.thisdir.pointed_obj = cf
         self.fm.thisfile = cf
 
-    def tab(self):
+    def tab(self, tabnum):
         if not self.rest(1):
             return self.line+os.readlink(self.fm.thisfile.path)
         else:
@@ -1186,8 +1188,8 @@ class scout(Command):
             return True
         return False
 
-    def tab(self):
-        self._count(move=True, offset=1)
+    def tab(self, tabnum):
+        self._count(move=True, offset=tabnum)
 
     def _build_regex(self):
         if self._regex is not None:
@@ -1477,7 +1479,7 @@ class meta(prompt_metadata):
             self.fm.metadata.set_metadata(f.path, update_dict)
         self._process_command_stack()
 
-    def tab(self):
+    def tab(self, tabnum):
         key = self.arg(1)
         metadata = self.fm.metadata.get_metadata(self.fm.thisfile.path)
         if key in metadata and metadata[key]:
diff --git a/ranger/config/commands_sample.py b/ranger/config/commands_sample.py
index 2df405f1..4f74019b 100644
--- a/ranger/config/commands_sample.py
+++ b/ranger/config/commands_sample.py
@@ -52,7 +52,8 @@ class my_edit(Command):
 
     # The tab method is called when you press tab, and should return a list of
     # suggestions that the user will tab through.
-    def tab(self):
+    # tabnum is 1 for <TAB> and -1 for <S-TAB> by default
+    def tab(self, tabnum):
         # This is a generic tab-completion function that iterates through the
         # content of the current directory.
         return self._tab_directory_content()
diff --git a/ranger/gui/widgets/console.py b/ranger/gui/widgets/console.py
index 5b9dbf3f..159b8f1e 100644
--- a/ranger/gui/widgets/console.py
+++ b/ranger/gui/widgets/console.py
@@ -382,19 +382,19 @@ class Console(Widget):
     def _get_cmd_class(self):
         return self.fm.commands.get_command(self.line.split()[0])
 
-    def _get_tab(self):
+    def _get_tab(self, tabnum):
         if ' ' in self.line:
             cmd = self._get_cmd()
             if cmd:
-                return cmd.tab()
+                return cmd.tab(tabnum)
             else:
                 return None
 
         return self.fm.commands.command_generator(self.line)
 
-    def tab(self, n=1):
+    def tab(self, tabnum=1):
         if self.tab_deque is None:
-            tab_result = self._get_tab()
+            tab_result = self._get_tab(tabnum)
 
             if isinstance(tab_result, str):
                 self.line = tab_result
@@ -409,7 +409,7 @@ class Console(Widget):
                 self.tab_deque.appendleft(self.line)
 
         if self.tab_deque is not None:
-            self.tab_deque.rotate(-n)
+            self.tab_deque.rotate(-tabnum)
             self.line = self.tab_deque[0]
             self.pos = len(self.line)
             self.on_line_change()