diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 74646d4a7..c75b373b8 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -35,6 +35,7 @@ Changed - `:bookmark-load` now has a `--delete` flag which deletes the bookmark after loading it. - `:open` now also accepts quickmark names instead of URLs +- `:tab-move` now optionally takes an index for absolute moving. Fixed ----- diff --git a/doc/help/commands.asciidoc b/doc/help/commands.asciidoc index 5f4e9da03..8724feaee 100644 --- a/doc/help/commands.asciidoc +++ b/doc/help/commands.asciidoc @@ -58,7 +58,7 @@ |<>|Close the current/[count]th tab. |<>|Detach the current tab to its own window. |<>|Select the tab given as argument/[count]. -|<>|Move the current tab. +|<>|Move the current tab according to the argument and [count]. |<>|Switch to the next tab, or switch [count] tabs forward. |<>|Close all tabs except for the current one. |<>|Switch to the previous tab, or switch [count] tabs back. @@ -767,16 +767,20 @@ The tab index to focus, starting with 1. [[tab-move]] === tab-move -Syntax: +:tab-move ['direction']+ +Syntax: +:tab-move ['index']+ -Move the current tab. +Move the current tab according to the argument and [count]. + +If neither is given, move it to the first position. ==== positional arguments -* +'direction'+: `+` or `-` for relative moving, not given for absolute moving. +* +'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 absolutely: New position (default: 0) If moving relatively: Offset. +If moving relatively: Offset. If moving absolutely: New position (default: 0). This + overrides the index argument, if given. [[tab-next]] diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 2ee2bf9d4..f47bcb00b 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -932,32 +932,40 @@ class CommandDispatcher: 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( diff --git a/tests/end2end/features/tabs.feature b/tests/end2end/features/tabs.feature index c4e137fe3..1fe667b46 100644 --- 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