Add completion for :back/:forward

Adds a completion for :back and :forward based on the history API for
the current tab in the current window. The column widths are copied from
the buffer completion. The first column is just the index in history.

I imagine that people may be interested in the `item.lastVisited()`
value which appears to be supported by both backends but we don't save
it out to the session file and it isn't used anywhere else in the
codebase so I held off on that.

Both backend's history classes also have `backItems()` and
`forwardItems()` but they aren't exposed in qutebrowsers history API,
hence the conditional in the list comprehension.

I haven't added a delete function, although I'm sure people will want
it, because:

* since there is no API for it it would involve serializing, editing,
  and deserealizing the history which would cause the tab to be reloaded at
  which point you may as well just have opened a new one and closed the
  tab with the unwanted history item
* it would only remove from the tab history, not the global history
  which may be surprising behavior

I had to pass `index=index` in the command methods because `forward`
isn't defined as a keyword argument in `_back_forward` but it is called
as one.

Passing negative values for index will do slightly weird things (for
back it go all the way back, for forward it'll go 1 forward) but I don't
care enough to add an extra check in there.
This commit is contained in:
Jimmy 2018-09-01 14:47:35 +12:00
parent b1f13310cd
commit 68b9b54888
3 changed files with 60 additions and 7 deletions

View File

@ -143,10 +143,13 @@ This updates `~/.local/share/qutebrowser/blocked-hosts` with downloaded host lis
[[back]]
=== back
Syntax: +:back [*--tab*] [*--bg*] [*--window*]+
Syntax: +:back [*--tab*] [*--bg*] [*--window*] ['index']+
Go back in the history of the current tab.
==== positional arguments
* +'index'+: Which page to go back to, count takes precedence.
==== optional arguments
* +*-t*+, +*--tab*+: Go back in a new tab.
* +*-b*+, +*--bg*+: Go back in a background tab.
@ -542,10 +545,13 @@ Follow the selected text.
[[forward]]
=== forward
Syntax: +:forward [*--tab*] [*--bg*] [*--window*]+
Syntax: +:forward [*--tab*] [*--bg*] [*--window*] ['index']+
Go forward in the history of the current tab.
==== positional arguments
* +'index'+: Which page to go forward to, count takes precedence.
==== optional arguments
* +*-t*+, +*--tab*+: Go forward in a new tab.
* +*-b*+, +*--bg*+: Go forward in a background tab.

View File

@ -492,7 +492,7 @@ class CommandDispatcher:
self._tabbed_browser.close_tab(self._current_widget(),
add_undo=False)
def _back_forward(self, tab, bg, window, count, forward):
def _back_forward(self, tab, bg, window, count, forward, index=None):
"""Helper function for :back/:forward."""
history = self._current_widget().history
# Catch common cases before e.g. cloning tab
@ -506,6 +506,12 @@ class CommandDispatcher:
else:
widget = self._current_widget()
if count is None:
if index is None:
count = 1
else:
count = abs(history.current_idx() - index)
try:
if forward:
widget.history.forward(count)
@ -516,7 +522,9 @@ class CommandDispatcher:
@cmdutils.register(instance='command-dispatcher', scope='window')
@cmdutils.argument('count', value=cmdutils.Value.count)
def back(self, tab=False, bg=False, window=False, count=1):
@cmdutils.argument('index', completion=miscmodels.back)
def back(self, tab=False, bg=False, window=False,
count=None, index: int = None):
"""Go back in the history of the current tab.
Args:
@ -524,12 +532,15 @@ class CommandDispatcher:
bg: Go back in a background tab.
window: Go back in a new window.
count: How many pages to go back.
index: Which page to go back to, count takes precedence.
"""
self._back_forward(tab, bg, window, count, forward=False)
self._back_forward(tab, bg, window, count, forward=False, index=index)
@cmdutils.register(instance='command-dispatcher', scope='window')
@cmdutils.argument('count', value=cmdutils.Value.count)
def forward(self, tab=False, bg=False, window=False, count=1):
@cmdutils.argument('index', completion=miscmodels.forward)
def forward(self, tab=False, bg=False, window=False,
count=None, index: int = None):
"""Go forward in the history of the current tab.
Args:
@ -537,8 +548,9 @@ class CommandDispatcher:
bg: Go forward in a background tab.
window: Go forward in a new window.
count: How many pages to go forward.
index: Which page to go forward to, count takes precedence.
"""
self._back_forward(tab, bg, window, count, forward=True)
self._back_forward(tab, bg, window, count, forward=True, index=index)
@cmdutils.register(instance='command-dispatcher', scope='window')
@cmdutils.argument('where', choices=['prev', 'next', 'up', 'increment',

View File

@ -179,3 +179,38 @@ def window(*, info):
model.add_category(listcategory.ListCategory("Windows", windows))
return model
def _back_forward(info, go_forward):
tab = objreg.get('tab', scope='tab', window=info.win_id, tab='current')
history = tab.history
current_idx = history.current_idx()
model = completionmodel.CompletionModel(column_widths=(6, 40, 54))
entries = [
(str(idx), entry.url().toDisplayString(), entry.title())
for idx, entry in enumerate(history)
if (idx > current_idx) == go_forward and idx != current_idx
]
if not go_forward:
# make sure the most recent is at the top for :back
entries = reversed(entries)
cat = listcategory.ListCategory("History", entries, sort=False)
model.add_category(cat)
return model
def forward(*, info):
"""A model to complete on history of the current tab.
Used for the :forward command.
"""
return _back_forward(info, go_forward=True)
def back(*, info):
"""A model to complete on history of the current tab.
Used for the :back command.
"""
return _back_forward(info, go_forward=False)