Move most :navigate code to browser.navigate

This commit is contained in:
Florian Bruhin 2016-08-05 17:12:44 +02:00
parent 68595e1736
commit 778ccad39f
3 changed files with 169 additions and 132 deletions

View File

@ -22,7 +22,6 @@
import os
import os.path
import shlex
import posixpath
import functools
from PyQt5.QtWidgets import QApplication, QTabBar
@ -40,7 +39,7 @@ import pygments.formatters
from qutebrowser.commands import userscripts, cmdexc, cmdutils, runners
from qutebrowser.config import config, configexc
from qutebrowser.browser import urlmarks, browsertab, inspector
from qutebrowser.browser import urlmarks, browsertab, inspector, navigate
from qutebrowser.browser.webkit import webelem, downloads, mhtml
from qutebrowser.keyinput import modeman
from qutebrowser.utils import (message, usertypes, log, qtutils, urlutils,
@ -440,40 +439,6 @@ class CommandDispatcher:
"""
self._back_forward(tab, bg, window, count, forward=True)
def _navigate_incdec(self, url, incdec, tab, background, window):
"""Helper method for :navigate when `where' is increment/decrement.
Args:
url: The current url.
incdec: Either 'increment' or 'decrement'.
tab: Whether to open the link in a new tab.
background: Open the link in a new background tab.
window: Open the link in a new window.
"""
segments = set(config.get('general', 'url-incdec-segments'))
try:
new_url = urlutils.incdec_number(url, incdec, segments=segments)
except urlutils.IncDecError as error:
raise cmdexc.CommandError(error.msg)
self._open(new_url, tab, background, window)
def _navigate_up(self, url, tab, background, window):
"""Helper method for :navigate when `where' is up.
Args:
url: The current url.
tab: Whether to open the link in a new tab.
background: Open the link in a new background tab.
window: Open the link in a new window.
"""
path = url.path()
if not path or path == '/':
raise cmdexc.CommandError("Can't go up!")
new_path = posixpath.join(path, posixpath.pardir)
url.setPath(new_path)
self._open(url, tab, background, window)
@cmdutils.register(instance='command-dispatcher', scope='window',
backend=usertypes.Backend.QtWebKit)
@cmdutils.argument('where', choices=['prev', 'next', 'up', 'increment',
@ -506,26 +471,29 @@ class CommandDispatcher:
widget = self._current_widget()
url = self._current_url().adjusted(QUrl.RemoveFragment)
if where in ['prev', 'next']:
# FIXME:qtwebengine have a proper API for this
if widget.backend == usertypes.Backend.QtWebEngine:
raise cmdexc.CommandError(":navigate prev/next is not "
"supported yet with QtWebEngine")
handlers = {
'prev': functools.partial(navigate.prevnext, prev=True),
'next': functools.partial(navigate.prevnext, prev=False),
'up': navigate.path_up,
'decrement': functools.partial(navigate.incdec,
inc_or_dec='decrement'),
'increment': functools.partial(navigate.incdec,
inc_or_dec='increment'),
}
hintmanager = objreg.get('hintmanager', scope='tab', tab='current')
if where == 'prev':
hintmanager.follow_prevnext(widget, url, prev=True, tab=tab,
background=bg, window=window)
elif where == 'next':
hintmanager.follow_prevnext(widget, url, prev=False, tab=tab,
background=bg, window=window)
elif where == 'up':
self._navigate_up(url, tab, bg, window)
elif where in ['decrement', 'increment']:
self._navigate_incdec(url, where, tab, bg, window)
else: # pragma: no cover
raise ValueError("Got called with invalid value {} for "
"`where'.".format(where))
try:
if where in ['prev', 'next']:
handler = handlers[where]
handler(browsertab=widget, win_id=self._win_id, baseurl=url,
tab=tab, background=bg, window=window)
elif where in ['up', 'increment', 'decrement']:
new_url = handlers[where](url)
self._open(new_url, tab, bg, window)
else: # pragma: no cover
raise ValueError("Got called with invalid value {} for "
"`where'.".format(where))
except navigate.Error as e:
raise cmdexc.CommandError(e)
@cmdutils.register(instance='command-dispatcher', hide=True,
scope='window')

View File

@ -630,83 +630,6 @@ class HintManager(QObject):
# Do multi-word matching
return all(word in elemstr for word in filterstr.split())
def _find_prevnext(self, prev, elems):
"""Find a prev/next element in the given list of elements."""
# First check for <link rel="prev(ious)|next">
rel_values = ('prev', 'previous') if prev else ('next')
for e in elems:
if e.tag_name() != 'link' or 'rel' not in e:
continue
if e['rel'] in rel_values:
log.hints.debug("Found '{}' with rel={}".format(
e.debug_text(), e['rel']))
return e
# Then check for regular links/buttons.
filterfunc = webelem.FILTERS[webelem.Group.prevnext]
elems = [e for e in elems if e.tag_name() != 'link' and filterfunc(e)]
option = 'prev-regexes' if prev else 'next-regexes'
if not elems:
return None
for regex in config.get('hints', option):
log.hints.vdebug("== Checking regex '{}'.".format(regex.pattern))
for e in elems:
text = str(e)
if not text:
continue
if regex.search(text):
log.hints.debug("Regex '{}' matched on '{}'.".format(
regex.pattern, text))
return e
else:
log.hints.vdebug("No match on '{}'!".format(text))
return None
def follow_prevnext(self, browsertab, baseurl, prev=False, tab=False,
background=False, window=False):
"""Click a "previous"/"next" element on the page.
Args:
browsertab: The WebKitTab/WebEngineTab of the page.
baseurl: The base URL of the current tab.
prev: True to open a "previous" link, False to open a "next" link.
tab: True to open in a new tab, False for the current tab.
background: True to open in a background tab.
window: True to open in a new window, False for the current one.
"""
def _follow_prevnext_cb(elems):
elem = self._find_prevnext(prev, elems)
word = 'prev' if prev else 'forward'
if elem is None:
message.error(self._win_id, "No {} links found!".format(word))
return
url = _resolve_url(elem, baseurl)
if url is None:
message.error(self._win_id, "No {} links found!".format(word))
return
qtutils.ensure_valid(url)
if window:
from qutebrowser.mainwindow import mainwindow
new_window = mainwindow.MainWindow()
new_window.show()
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=new_window.win_id)
tabbed_browser.tabopen(url, background=False)
elif tab:
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=self._win_id)
tabbed_browser.tabopen(url, background=background)
else:
browsertab = objreg.get('tab', scope='tab',
window=self._win_id, tab=self._tab_id)
browsertab.openurl(url)
selector = ', '.join([webelem.SELECTORS[webelem.Group.links],
webelem.SELECTORS[webelem.Group.prevnext]])
browsertab.find_all_elements(selector, _follow_prevnext_cb)
def _start_cb(self, elems):
"""Initialize the elements and labels based on the context set."""
filterfunc = webelem.FILTERS.get(self._context.group, lambda e: True)

View File

@ -0,0 +1,146 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""Implementation of :navigate"""
import posixpath
from qutebrowser.browser.webkit import webelem
from qutebrowser.config import config
from qutebrowser.utils import (usertypes, objreg, urlutils, log, message,
qtutils)
class Error(Exception):
"""Raised when the navigation can't be done."""
def incdec(url, inc_or_dec):
"""Helper method for :navigate when `where' is increment/decrement.
Args:
url: The current url.
inc_or_dec: Either 'increment' or 'decrement'.
tab: Whether to open the link in a new tab.
background: Open the link in a new background tab.
window: Open the link in a new window.
"""
segments = set(config.get('general', 'url-incdec-segments'))
try:
new_url = urlutils.incdec_number(url, inc_or_dec, segments=segments)
except urlutils.IncDecError as error:
raise Error(error.msg)
return new_url
def path_up(url):
"""Helper method for :navigate when `where' is up.
Args:
url: The current url.
"""
path = url.path()
if not path or path == '/':
raise Error("Can't go up!")
new_path = posixpath.join(path, posixpath.pardir)
url.setPath(new_path)
return url
def _find_prevnext(prev, elems):
"""Find a prev/next element in the given list of elements."""
# First check for <link rel="prev(ious)|next">
rel_values = ('prev', 'previous') if prev else ('next')
for e in elems:
if e.tag_name() != 'link' or 'rel' not in e:
continue
if e['rel'] in rel_values:
log.hints.debug("Found '{}' with rel={}".format(
e.debug_text(), e['rel']))
return e
# Then check for regular links/buttons.
filterfunc = webelem.FILTERS[webelem.Group.prevnext]
elems = [e for e in elems if e.tag_name() != 'link' and filterfunc(e)]
option = 'prev-regexes' if prev else 'next-regexes'
if not elems:
return None
for regex in config.get('hints', option):
log.hints.vdebug("== Checking regex '{}'.".format(regex.pattern))
for e in elems:
text = str(e)
if not text:
continue
if regex.search(text):
log.hints.debug("Regex '{}' matched on '{}'.".format(
regex.pattern, text))
return e
else:
log.hints.vdebug("No match on '{}'!".format(text))
return None
def prevnext(*, browsertab, win_id, baseurl, prev=False,
tab=False, background=False, window=False):
"""Click a "previous"/"next" element on the page.
Args:
browsertab: The WebKitTab/WebEngineTab of the page.
baseurl: The base URL of the current tab.
prev: True to open a "previous" link, False to open a "next" link.
tab: True to open in a new tab, False for the current tab.
background: True to open in a background tab.
window: True to open in a new window, False for the current one.
"""
# FIXME:qtwebengine have a proper API for this
if browsertab.backend == usertypes.Backend.QtWebEngine:
raise Error(":navigate prev/next is not supported yet with "
"QtWebEngine")
def _prevnext_cb(elems):
elem = _find_prevnext(prev, elems)
word = 'prev' if prev else 'forward'
if elem is None:
message.error(win_id, "No {} links found!".format(word))
return
url = elem.resolve_url(baseurl)
if url is None:
message.error(win_id, "No {} links found!".format(word))
return
qtutils.ensure_valid(url)
if window:
from qutebrowser.mainwindow import mainwindow
new_window = mainwindow.MainWindow()
new_window.show()
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=new_window.win_id)
tabbed_browser.tabopen(url, background=False)
elif tab:
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=win_id)
tabbed_browser.tabopen(url, background=background)
else:
browsertab.openurl(url)
selector = ', '.join([webelem.SELECTORS[webelem.Group.links],
webelem.SELECTORS[webelem.Group.prevnext]])
browsertab.find_all_elements(selector, _prevnext_cb)