Move most :navigate code to browser.navigate
This commit is contained in:
parent
68595e1736
commit
778ccad39f
@ -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)
|
||||
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')
|
||||
|
@ -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)
|
||||
|
146
qutebrowser/browser/navigate.py
Normal file
146
qutebrowser/browser/navigate.py
Normal 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)
|
Loading…
Reference in New Issue
Block a user