Repository: qutebrowser/qutebrowser

Issue:
Move current tab to the end
Currently it's possible with `:tab-move ;; tab-move -`, provided `wrap` is set. But one or both of the following would be much better:
- An option to change `tab-move`'s default to the last tab, or
- Some way to get a negative argument to `tab-move`, like `tab-focus`.

For the second, the most feasible way seems to be an explicit direction for "absolute", plus an `index` argument like `tab-focus` has. It's also possible to split up `tab-move`.

I'll implement the changes but would like to know if anyone has thoughts on how to do this.



Discussion:
What about `:tab-move` just taking an `index` (rather than `direction`), and describe that the index can be `-` or `+` for relative moving? Then the count would just override that index if given, like with `:tab-focus`.

That seems the most consistent for me.

That's better. It also removes the need for a `tab-move-default` option, since `:tab-move -1` bound to a key would work the same as `:tab-move` defaulting to the last tab.

Currently `:tab-focus` works opposite to the way you described, with the index overriding the count. This seems much less useful than the other way around. Is it correct?


Resolving patch:
diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py
--- a/qutebrowser/browser/commands.py
+++ b/qutebrowser/browser/commands.py
@@ -932,32 +932,40 @@ def tab_focus(self, index: typing.Union[str, int]=None, count=None):
                 idx))
 
     @cmdutils.register(instance='command-dispatcher', scope='window')
-    @cmdutils.argument('direction', choices=['+', '-'])
+    @cmdutils.argument('index', choices=['+', '-'])
     @cmdutils.argument('count', count=True)
-    def tab_move(self, direction: str=None, count=None):
-        """Move the current tab.
+    def tab_move(self, index: typing.Union[str, int]=None, count=None):
+        """Move the current tab according to the argument and [count].
+
+        If neither is given, move it to the first position.
 
         Args:
-            direction: `+` or `-` for relative moving, not given for absolute
-                       moving.
-            count: If moving absolutely: New position (default: 0)
-                   If moving relatively: Offset.
+            index: `+` or `-` to move relative to the current tab by
+                   count, or a default of 1 space.
+                   A tab index to move to that index.
+            count: If moving relatively: Offset.
+                   If moving absolutely: New position (default: 0). This
+                   overrides the index argument, if given.
         """
-        if direction is None:
-            # absolute moving
-            new_idx = 0 if count is None else count - 1
-        elif direction in '+-':
+        if index in ['+', '-']:
             # relative moving
+            new_idx = self._current_index()
             delta = 1 if count is None else count
-            if direction == '-':
-                new_idx = self._current_index() - delta
-            elif direction == '+':  # pragma: no branch
-                new_idx = self._current_index() + delta
+            if index == '-':
+                new_idx -= delta
+            elif index == '+':  # pragma: no branch
+                new_idx += delta
 
             if config.get('tabs', 'wrap'):
                 new_idx %= self._count()
-        else:  # pragma: no cover
-            raise ValueError("Invalid direction '{}'!".format(direction))
+        else:
+            # absolute moving
+            if count is not None:
+                new_idx = count - 1
+            elif index is not None:
+                new_idx = index - 1 if index >= 0 else index + self._count()
+            else:
+                new_idx = 0
 
         if not 0 <= new_idx < self._count():
             raise cmdexc.CommandError("Can't move tab to position {}!".format(


Test patch:
diff --git a/tests/end2end/features/tabs.feature b/tests/end2end/features/tabs.feature
--- a/tests/end2end/features/tabs.feature
+++ b/tests/end2end/features/tabs.feature
@@ -380,6 +380,58 @@ Feature: Tab management
             - data/numbers/2.txt
             - data/numbers/3.txt (active)
 
+    Scenario: :tab-move with index.
+        When I open data/numbers/1.txt
+        And I open data/numbers/2.txt in a new tab
+        And I open data/numbers/3.txt in a new tab
+        And I run :tab-move 2
+        Then the following tabs should be open:
+            - data/numbers/1.txt
+            - data/numbers/3.txt (active)
+            - data/numbers/2.txt
+
+    Scenario: :tab-move with negative index.
+        When I open data/numbers/1.txt
+        And I open data/numbers/2.txt in a new tab
+        And I open data/numbers/3.txt in a new tab
+        And I run :tab-move -3
+        Then the following tabs should be open:
+            - data/numbers/3.txt (active)
+            - data/numbers/1.txt
+            - data/numbers/2.txt
+
+    Scenario: :tab-move with invalid index.
+        When I open data/numbers/1.txt
+        And I open data/numbers/2.txt in a new tab
+        And I open data/numbers/3.txt in a new tab
+        And I run :tab-move -5
+        Then the error "Can't move tab to position -1!" should be shown.
+        And the following tabs should be open:
+            - data/numbers/1.txt
+            - data/numbers/2.txt
+            - data/numbers/3.txt (active)
+
+    Scenario: :tab-move with index and count.
+        When I open data/numbers/1.txt
+        And I open data/numbers/2.txt in a new tab
+        And I open data/numbers/3.txt in a new tab
+        And I run :tab-move 1 with count 2
+        Then the following tabs should be open:
+            - data/numbers/1.txt
+            - data/numbers/3.txt (active)
+            - data/numbers/2.txt
+
+    Scenario: :tab-move with index and invalid count.
+        When I open data/numbers/1.txt
+        And I open data/numbers/2.txt in a new tab
+        And I open data/numbers/3.txt in a new tab
+        And I run :tab-move -2 with count 4
+        Then the error "Can't move tab to position 4!" should be shown.
+        And the following tabs should be open:
+            - data/numbers/1.txt
+            - data/numbers/2.txt
+            - data/numbers/3.txt (active)
+
     Scenario: :tab-move with relative position (negative).
         When I open data/numbers/1.txt
         And I open data/numbers/2.txt in a new tab