Make hints work
This commit is contained in:
parent
12b36de5b5
commit
fd678ff864
@ -222,6 +222,26 @@ class CurCommandDispatcher(QObject):
|
|||||||
"""Fire a completed hint."""
|
"""Fire a completed hint."""
|
||||||
self._tabs.currentWidget().hintmanager.fire(keystr)
|
self._tabs.currentWidget().hintmanager.fire(keystr)
|
||||||
|
|
||||||
|
@cmdutils.register(instance='mainwindow.tabs.cur')
|
||||||
|
def prev_page(self):
|
||||||
|
"""Click on a "previous" link."""
|
||||||
|
widget = self._tabs.currentWidget()
|
||||||
|
frame = widget.page_.currentFrame()
|
||||||
|
if frame is None:
|
||||||
|
message.error("No frame focused!")
|
||||||
|
return
|
||||||
|
widget.hintmanager.click_prevnext(frame, prev=True)
|
||||||
|
|
||||||
|
@cmdutils.register(instance='mainwindow.tabs.cur')
|
||||||
|
def next_page(self):
|
||||||
|
"""Click on a "next" link."""
|
||||||
|
widget = self._tabs.currentWidget()
|
||||||
|
frame = widget.page_.currentFrame()
|
||||||
|
if frame is None:
|
||||||
|
message.error("No frame focused!")
|
||||||
|
return
|
||||||
|
widget.hintmanager.click_prevnext(frame, prev=False)
|
||||||
|
|
||||||
@pyqtSlot(str, int)
|
@pyqtSlot(str, int)
|
||||||
def search(self, text, flags):
|
def search(self, text, flags):
|
||||||
"""Search for text in the current page.
|
"""Search for text in the current page.
|
||||||
|
@ -207,19 +207,24 @@ class HintManager(QObject):
|
|||||||
css, string))
|
css, string))
|
||||||
return doc.lastChild()
|
return doc.lastChild()
|
||||||
|
|
||||||
def _click(self, elem):
|
def _click(self, elem, target=None, frame=None):
|
||||||
"""Click an element.
|
"""Click an element.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
elem: The QWebElement to click.
|
elem: The QWebElement to click.
|
||||||
|
target_override: Target which overrides self._target
|
||||||
"""
|
"""
|
||||||
if self._target == 'rapid':
|
if target is not None:
|
||||||
|
pass
|
||||||
|
elif self._target == 'rapid':
|
||||||
target = 'bgtab'
|
target = 'bgtab'
|
||||||
else:
|
else:
|
||||||
target = self._target
|
target = self._target
|
||||||
|
if frame is None:
|
||||||
|
frame = self._frame
|
||||||
self.set_open_target.emit(target)
|
self.set_open_target.emit(target)
|
||||||
point = elem.geometry().topLeft()
|
point = elem.geometry().topLeft()
|
||||||
scrollpos = self._frame.scrollPosition()
|
scrollpos = frame.scrollPosition()
|
||||||
logging.debug("Clicking on \"{}\" at {}/{} - {}/{}".format(
|
logging.debug("Clicking on \"{}\" at {}/{} - {}/{}".format(
|
||||||
elem.toPlainText(), point.x(), point.y(), scrollpos.x(),
|
elem.toPlainText(), point.x(), point.y(), scrollpos.x(),
|
||||||
scrollpos.y()))
|
scrollpos.y()))
|
||||||
@ -281,22 +286,23 @@ class HintManager(QObject):
|
|||||||
def click_prevnext(self, frame, prev=False):
|
def click_prevnext(self, frame, prev=False):
|
||||||
"""Click a "previous"/"next" element on the page."""
|
"""Click a "previous"/"next" element on the page."""
|
||||||
# First check for <link rel="prev(ious)|next">
|
# First check for <link rel="prev(ious)|next">
|
||||||
self.target='normal'
|
|
||||||
elems = frame.findAllElements(webelem.SELECTORS['prevnext_rel'])
|
elems = frame.findAllElements(webelem.SELECTORS['prevnext_rel'])
|
||||||
rel_values = ['prev', 'previous'] if prev else ['next']
|
rel_values = ['prev', 'previous'] if prev else ['next']
|
||||||
for e in elems:
|
for e in elems:
|
||||||
if e.attribute('rel') in rel_values:
|
if e.attribute('rel') in rel_values:
|
||||||
self.click(e)
|
self._click(e, 'normal', frame)
|
||||||
return
|
return
|
||||||
# Then check for regular links
|
# Then check for regular links
|
||||||
elems = frame.findAllElements(webelem.SELECTORS['prevnext'])
|
elems = frame.findAllElements(webelem.SELECTORS['prevnext'])
|
||||||
option = 'prev-regexes' if prev else 'next-regexes'
|
option = 'prev-regexes' if prev else 'next-regexes'
|
||||||
for regex in config.get('hints', option):
|
if elems:
|
||||||
for e in elems:
|
for regex in config.get('hints', option):
|
||||||
if regex.match(e.toPlainText()):
|
for e in elems:
|
||||||
self.click(e)
|
if regex.match(e.toPlainText()):
|
||||||
return
|
self._click(e, 'normal', frame)
|
||||||
message.error("No prev/forward links found!")
|
return
|
||||||
|
message.error("No {} links found!".format("prev" if prev
|
||||||
|
else "forward"))
|
||||||
|
|
||||||
|
|
||||||
def start(self, frame, baseurl, mode='all', target='normal'):
|
def start(self, frame, baseurl, mode='all', target='normal'):
|
||||||
|
@ -17,7 +17,9 @@
|
|||||||
|
|
||||||
"""Setting options used for qutebrowser."""
|
"""Setting options used for qutebrowser."""
|
||||||
|
|
||||||
|
import re
|
||||||
import shlex
|
import shlex
|
||||||
|
from sre_constants import error as RegexError
|
||||||
|
|
||||||
from PyQt5.QtGui import QColor
|
from PyQt5.QtGui import QColor
|
||||||
|
|
||||||
@ -511,6 +513,42 @@ class KeyBindingName(BaseType):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Regex(BaseType):
|
||||||
|
|
||||||
|
"""A regular expression."""
|
||||||
|
|
||||||
|
def __init__(self, flags=0):
|
||||||
|
self.flags = flags
|
||||||
|
|
||||||
|
def validate(self, value):
|
||||||
|
try:
|
||||||
|
re.compile(value, self.flags)
|
||||||
|
except RegexError as e:
|
||||||
|
raise ValidationError(value, "must be a valid regex - " + str(e))
|
||||||
|
|
||||||
|
def transform(self, value):
|
||||||
|
return re.compile(value, self.flags)
|
||||||
|
|
||||||
|
|
||||||
|
class RegexList(List):
|
||||||
|
|
||||||
|
"""A list of regexes."""
|
||||||
|
|
||||||
|
def __init__(self, flags=0):
|
||||||
|
self.flags=flags
|
||||||
|
|
||||||
|
def transform(self, value):
|
||||||
|
vals = super().transform(value)
|
||||||
|
return [re.compile(pattern, self.flags) for pattern in vals]
|
||||||
|
|
||||||
|
def validate(self, value):
|
||||||
|
try:
|
||||||
|
self.transform(value)
|
||||||
|
except RegexError as e:
|
||||||
|
raise ValidationError(value, "must be a list valid regexes - " +
|
||||||
|
str(e))
|
||||||
|
|
||||||
|
|
||||||
class AutoSearch(BaseType):
|
class AutoSearch(BaseType):
|
||||||
|
|
||||||
"""Whether to start a search when something else than an URL is entered."""
|
"""Whether to start a search when something else than an URL is entered."""
|
||||||
|
@ -24,6 +24,7 @@ SECTION_DESC: A dictionary with descriptions for sections.
|
|||||||
DATA: The config defaults, an OrderedDict of sections.
|
DATA: The config defaults, an OrderedDict of sections.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from qutebrowser.config._value import SettingValue
|
from qutebrowser.config._value import SettingValue
|
||||||
@ -397,6 +398,18 @@ DATA = OrderedDict([
|
|||||||
('auto-follow',
|
('auto-follow',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(types.Bool(), 'true'),
|
||||||
"Whether to auto-follow a hint if there's only one left."),
|
"Whether to auto-follow a hint if there's only one left."),
|
||||||
|
|
||||||
|
('next-regexes',
|
||||||
|
SettingValue(types.RegexList(flags=re.IGNORECASE),
|
||||||
|
r'\bnext\b,\bmore\b,\bnewer\b,^>$$,^(>>|»|→|≫)$$,'
|
||||||
|
r'^(>|»|→|≫),(>|»|→|≫)$$'),
|
||||||
|
"A comma-separated list of regexes to use for 'next' links."),
|
||||||
|
|
||||||
|
('prev-regexes',
|
||||||
|
SettingValue(types.RegexList(flags=re.IGNORECASE),
|
||||||
|
r'\bprev(ious)\b,\bback\b,\bolder\b,^<$$,^(<<|«|←|≪)$$,'
|
||||||
|
r'^(<|«|←|≪),(<|«|←|≪)$$'),
|
||||||
|
"A comma-separated list of regexes to use for 'prev' links."),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
('searchengines', sect.ValueList(
|
('searchengines', sect.ValueList(
|
||||||
@ -456,6 +469,8 @@ DATA = OrderedDict([
|
|||||||
('PP', 'tabpaste sel'),
|
('PP', 'tabpaste sel'),
|
||||||
('-', 'zoomout'),
|
('-', 'zoomout'),
|
||||||
('+', 'zoomin'),
|
('+', 'zoomin'),
|
||||||
|
('[[', 'prev_page'),
|
||||||
|
(']]', 'next_page'),
|
||||||
('<Ctrl-V>', 'enter_mode passthrough'),
|
('<Ctrl-V>', 'enter_mode passthrough'),
|
||||||
('<Ctrl-Q>', 'quit'),
|
('<Ctrl-Q>', 'quit'),
|
||||||
('<Ctrl-Shift-T>', 'undo'),
|
('<Ctrl-Shift-T>', 'undo'),
|
||||||
|
@ -36,8 +36,8 @@ SELECTORS = {
|
|||||||
'input[type=tel], input[type=number], '
|
'input[type=tel], input[type=number], '
|
||||||
'input[type=password], input[type=search], textarea'),
|
'input[type=password], input[type=search], textarea'),
|
||||||
'url': '[src], [href]',
|
'url': '[src], [href]',
|
||||||
'prevnext_rel': 'link [role=link]',
|
'prevnext_rel': 'link, [role=link]',
|
||||||
'prevnext': 'a button [role=button]',
|
'prevnext': 'a, button, [role=button]',
|
||||||
}
|
}
|
||||||
|
|
||||||
SELECTORS['editable_focused'] = ', '.join(
|
SELECTORS['editable_focused'] = ', '.join(
|
||||||
|
Loading…
Reference in New Issue
Block a user