From 67437a0d5d78736e279927b195f27ceed23230a2 Mon Sep 17 00:00:00 2001 From: Michael Hoang Date: Wed, 4 Oct 2017 05:05:00 +1100 Subject: [PATCH] Add :tab-give and :tab-take commands and tests --- doc/help/commands.asciidoc | 21 +++++++++ qutebrowser/browser/commands.py | 33 ++++++++++++++ qutebrowser/completion/models/miscmodels.py | 19 ++++++++ tests/end2end/features/tabs.feature | 50 +++++++++++++++++++++ 4 files changed, 123 insertions(+) diff --git a/doc/help/commands.asciidoc b/doc/help/commands.asciidoc index 137bf3ef8..e166e51eb 100644 --- a/doc/help/commands.asciidoc +++ b/doc/help/commands.asciidoc @@ -85,11 +85,13 @@ It is possible to run or bind multiple commands by separating them with `;;`. |<>|Close the current/[count]th tab. |<>|Detach the current tab to its own window. |<>|Select the tab given as argument/[count]. +|<>|Give the current tab to another window. |<>|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. |<>|Pin/Unpin the current/[count]th tab. |<>|Switch to the previous tab, or switch [count] tabs back. +|<>|Take a tab from another window. |<>|Unbind a keychain. |<>|Re-open a closed tab. |<>|Show version information. @@ -967,6 +969,15 @@ If neither count nor index are given, it behaves like tab-next. If both are give ==== count The tab index to focus, starting with 1. +[[tab-give]] +=== tab-give +Syntax: +:tab-give 'win-id'+ + +Give the current tab to another window. + +==== positional arguments +* +'win-id'+: The window ID of the window to give the current tab to. + [[tab-move]] === tab-move Syntax: +:tab-move ['index']+ @@ -1019,6 +1030,16 @@ Switch to the previous tab, or switch [count] tabs back. ==== count How many tabs to switch back. +[[tab-take]] +=== tab-take +Syntax: +:tab-take 'index'+ + +Take a tab from another window. + +==== positional arguments +* +'index'+: The [win_id/]index of the tab to take. Or a substring in which case the closest match will be taken. + + [[unbind]] === unbind Syntax: +:unbind [*--mode* 'mode'] 'key'+ diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 7a3bbe159..b7ed82af9 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -523,6 +523,39 @@ class CommandDispatcher: cur_widget = self._current_widget() self._tabbed_browser.close_tab(cur_widget, add_undo=False) + @cmdutils.register(instance='command-dispatcher', scope='window') + @cmdutils.argument('index', completion=miscmodels.buffer) + def tab_take(self, index): + """Take a tab from another window. + + Args: + index: The [win_id/]index of the tab to take. Or a substring + in which case the closest match will be taken. + """ + tabbed_browser, tab = self._resolve_buffer_index(index) + + if tabbed_browser is self._tabbed_browser: + raise cmdexc.CommandError("Can't take a tab from the same window") + + self._open(tab.url(), tab=True) + tabbed_browser.close_tab(tab, add_undo=False) + + @cmdutils.register(instance='command-dispatcher', scope='window') + @cmdutils.argument('win_id', completion=miscmodels.window) + def tab_give(self, win_id: int): + """Give the current tab to another window. + + Args: + win_id: The window ID of the window to give the current tab to. + """ + if win_id == self._win_id: + raise cmdexc.CommandError("Can't give a tab to the same window") + + tabbed_browser = objreg.get('tabbed-browser', scope='window', + window=win_id) + tabbed_browser.tabopen(self._current_url()) + self._tabbed_browser.close_tab(self._current_widget(), add_undo=False) + def _back_forward(self, tab, bg, window, count, forward): """Helper function for :back/:forward.""" history = self._current_widget().history diff --git a/qutebrowser/completion/models/miscmodels.py b/qutebrowser/completion/models/miscmodels.py index 3244c7bf3..9b7783e4f 100644 --- a/qutebrowser/completion/models/miscmodels.py +++ b/qutebrowser/completion/models/miscmodels.py @@ -122,3 +122,22 @@ def buffer(*, info=None): # pylint: disable=unused-argument model.add_category(cat) return model + + +def window(*, info=None): # pylint: disable=unused-argument + """A model to complete on all open windows.""" + model = completionmodel.CompletionModel(column_widths=(6, 30, 64)) + + windows = [] + + for win_id in objreg.window_registry: + tabbed_browser = objreg.get('tabbed-browser', scope='window', + window=win_id) + tab_titles = (tab.title() for tab in tabbed_browser.widgets()) + windows.append(("{}".format(win_id), + objreg.window_registry[win_id].windowTitle(), + ", ".join(tab_titles))) + + model.add_category(listcategory.ListCategory("Windows", windows)) + + return model diff --git a/tests/end2end/features/tabs.feature b/tests/end2end/features/tabs.feature index b510a4f66..ba20f9a75 100644 --- a/tests/end2end/features/tabs.feature +++ b/tests/end2end/features/tabs.feature @@ -1010,6 +1010,56 @@ Feature: Tab management And I run :buffer "1/2/3" Then the error "No matching tab for: 1/2/3" should be shown + # :tab-take + + @xfail_norun + Scenario: Take a tab from another window + Given I have a fresh instance + When I open data/numbers/1.txt + And I open data/numbers/2.txt in a new window + And I run :tab-take 0/1 + Then the session should look like: + windows: + - tabs: + - history: + - url: about:blank + - tabs: + - history: + - url: http://localhost:*/data/numbers/2.txt + - history: + - url: http://localhost:*/data/numbers/1.txt + + Scenario: Take a tab from the same window + Given I have a fresh instance + When I open data/numbers/1.txt + And I run :tab-take 0/1 + Then the error "Can't take a tab from the same window" should be shown + + # :tab-give + + @xfail_norun + Scenario: Give a tab to another window + Given I have a fresh instance + When I open data/numbers/1.txt + And I open data/numbers/2.txt in a new window + And I run :tab-give 0 + Then the session should look like: + windows: + - tabs: + - history: + - url: http://localhost:*/data/numbers/1.txt + - history: + - url: http://localhost:*/data/numbers/2.txt + - tabs: + - history: + - url: about:blank + + Scenario: Give a tab to the same window + Given I have a fresh instance + When I open data/numbers/1.txt + And I run :tab-give 0 + Then the error "Can't give a tab to the same window" should be shown + # Other Scenario: Using :tab-next after closing last tab (#1448)