Add completion for :undo

See #32
This commit is contained in:
Florian Bruhin 2020-07-29 20:18:23 +02:00
parent 63b44c17ac
commit f42cc99595
6 changed files with 73 additions and 9 deletions

View File

@ -795,26 +795,36 @@ class CommandDispatcher:
@cmdutils.register(instance='command-dispatcher', scope='window')
@cmdutils.argument('count', value=cmdutils.Value.count)
def undo(self, window: bool = False, count: int = 1) -> None:
@cmdutils.argument('depth', completion=miscmodels.undo)
def undo(self, window: bool = False,
count: int = None, depth: int = None) -> None:
"""Re-open the last closed tab(s) or window.
Args:
window: Re-open the last closed window (and its tabs).
count: How deep in the undo stack to find the tab or tabs to
re-open.
depth: Same as `count` but as argument for completion, `count`
takes precedence.
"""
if window and count != 1:
has_depth = count is not None or depth is not None
if count is not None:
depth = count
elif depth is None:
depth = 1
if window and has_depth:
raise cmdutils.CommandError(
":undo --window does not support a count")
":undo --window does not support a count/depth")
try:
if window:
windowundo.instance.undo_last_window_close()
else:
self._tabbed_browser.undo(count)
self._tabbed_browser.undo(depth)
except IndexError:
msg = "Nothing to undo"
if not window and count == 1:
if not window and not has_depth:
msg += " (use :undo --window to reopen a closed window)"
raise cmdutils.CommandError(msg)

View File

@ -274,3 +274,23 @@ def back(*, info):
Used for the :back command.
"""
return _back_forward(info, go_forward=False)
def undo(*, info):
"""A model to complete undo entries."""
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=info.win_id)
model = completionmodel.CompletionModel(column_widths=(6, 94, 0))
entries = [
(
str(idx),
', '.join(entry.url.toDisplayString() for entry in group)
)
for idx, group in
enumerate(reversed(tabbed_browser.undo_stack), start=1)
]
cat = listcategory.ListCategory("Closed tabs", entries)
model.add_category(cat)
return model

View File

@ -494,7 +494,7 @@ class TabbedBrowser(QWidget):
tab.deleteLater()
def undo(self, count=1):
def undo(self, depth=1):
"""Undo removing of a tab or tabs."""
# Remove unused tab which may be created after the last tab is closed
last_close = config.val.tabs.last_close
@ -517,8 +517,8 @@ class TabbedBrowser(QWidget):
use_current_tab = (only_one_tab_open and no_history and
last_close_url_used)
entries = self.undo_stack[-count]
del self.undo_stack[-count]
entries = self.undo_stack[-depth]
del self.undo_stack[-depth]
for entry in reversed(entries):
if use_current_tab:

View File

@ -1014,7 +1014,11 @@ Feature: Tab management
Scenario: Undo with --window and count
When I run :undo --window with count 2
Then the error ":undo --window does not support a count" should be shown
Then the error ":undo --window does not support a count/depth" should be shown
Scenario: Undo with --window and depth
When I run :undo --window 1
Then the error ":undo --window does not support a count/depth" should be shown
# tabs.last_close

View File

@ -484,6 +484,7 @@ class TabbedBrowserStub(QObject):
self.is_shutting_down = False
self.loaded_url = None
self.cur_url = None
self.undo_stack = None
def on_tab_close_requested(self, idx):
del self.widget.tabs[idx]

View File

@ -40,6 +40,7 @@ from qutebrowser.completion import completer
from qutebrowser.completion.models import miscmodels, urlmodel, configmodel
from qutebrowser.config import configdata, configtypes
from qutebrowser.utils import usertypes
from qutebrowser.mainwindow import tabbedbrowser
def _check_completions(model, expected):
@ -1263,3 +1264,31 @@ def test_forward_completion(tab_with_history, info):
("4", "http://example.com/thing4", "thing4 detail"),
],
})
def test_undo_completion(tabbed_browser_stubs, info):
"""Test :undo completion."""
entry1 = tabbedbrowser._UndoEntry(url=QUrl('https://example.org/'),
history=None, index=None, pinned=None)
entry2 = tabbedbrowser._UndoEntry(url=QUrl('https://example.com/'),
history=None, index=None, pinned=None)
entry3 = tabbedbrowser._UndoEntry(url=QUrl('https://example.net/'),
history=None, index=None, pinned=None)
# Most recently closed is at the end
tabbed_browser_stubs[0].undo_stack = [
[entry1],
[entry2, entry3],
]
model = miscmodels.undo(info=info)
model.set_pattern('')
# Most recently closed is at the top, indices are used like "-x" for the
# undo stack.
_check_completions(model, {
"Closed tabs": [
("1", "https://example.com/, https://example.net/", None),
("2", "https://example.org/", None),
],
})