Merge branch 'lahwaacz-fix_hints_autofollow'
This commit is contained in:
commit
7b7dff30bf
@ -71,6 +71,9 @@ Changed
|
||||
- The `:buffer` completion now also filters using the first column (id).
|
||||
- `:undo` has been improved to reopen tabs at the position they were closed.
|
||||
- `:navigate` now takes a count for `up`/`increment`/`decrement`.
|
||||
- The `hints -> auto-follow` setting now can be set to
|
||||
`always`/`full-match`/`unique-match`/`never` to more precisely control when
|
||||
hints should be followed automatically.
|
||||
|
||||
Deprecated
|
||||
~~~~~~~~~~
|
||||
|
@ -142,10 +142,10 @@ Contributors, sorted by the number of commits in descending order:
|
||||
* Florian Bruhin
|
||||
* Daniel Schadt
|
||||
* Ryan Roden-Corrent
|
||||
* Jakub Klinkovský
|
||||
* Antoni Boucher
|
||||
* Lamar Pavel
|
||||
* Bruno Oliveira
|
||||
* Jakub Klinkovský
|
||||
* Jan Verbeek
|
||||
* Alexander Cogneau
|
||||
* Marshall Lochbaum
|
||||
|
@ -185,7 +185,7 @@
|
||||
|<<hints-scatter,scatter>>|Whether to scatter hint key chains (like Vimium) or not (like dwb). Ignored for number hints.
|
||||
|<<hints-uppercase,uppercase>>|Make chars in hint strings uppercase.
|
||||
|<<hints-dictionary,dictionary>>|The dictionary file to be used by the word hints.
|
||||
|<<hints-auto-follow,auto-follow>>|Follow a hint immediately when the hint text is completely matched.
|
||||
|<<hints-auto-follow,auto-follow>>|Controls when a hint can be automatically followed without the user pressing Enter.
|
||||
|<<hints-auto-follow-timeout,auto-follow-timeout>>|A timeout (in milliseconds) to inhibit normal-mode key bindings after a successful auto-follow.
|
||||
|<<hints-next-regexes,next-regexes>>|A comma-separated list of regexes to use for 'next' links.
|
||||
|<<hints-prev-regexes,prev-regexes>>|A comma-separated list of regexes to use for 'prev' links.
|
||||
@ -1660,14 +1660,16 @@ Default: +pass:[/usr/share/dict/words]+
|
||||
|
||||
[[hints-auto-follow]]
|
||||
=== auto-follow
|
||||
Follow a hint immediately when the hint text is completely matched.
|
||||
Controls when a hint can be automatically followed without the user pressing Enter.
|
||||
|
||||
Valid values:
|
||||
|
||||
* +true+
|
||||
* +false+
|
||||
* +always+: Auto-follow whenever there is only a single hint on a page.
|
||||
* +unique-match+: Auto-follow whenever there is a unique non-empty match in either the hint string (word mode) or filter (number mode).
|
||||
* +full-match+: Follow the hint when the user typed the whole hint (letter, word or number mode) or the element's text (only in number mode).
|
||||
* +never+: The user will always need to press Enter to follow a hint.
|
||||
|
||||
Default: +pass:[true]+
|
||||
Default: +pass:[unique-match]+
|
||||
|
||||
[[hints-auto-follow-timeout]]
|
||||
=== auto-follow-timeout
|
||||
|
@ -62,7 +62,6 @@ class HintContext:
|
||||
"""Context namespace used for hinting.
|
||||
|
||||
Attributes:
|
||||
frames: The QWebFrames to use.
|
||||
all_elems: A list of all (elem, label) namedtuples ever created.
|
||||
elems: A mapping from key strings to (elem, label) namedtuples.
|
||||
May contain less elements than `all_elems` due to filtering.
|
||||
@ -79,6 +78,7 @@ class HintContext:
|
||||
to_follow: The link to follow when enter is pressed.
|
||||
args: Custom arguments for userscript/spawn
|
||||
rapid: Whether to do rapid hinting.
|
||||
filterstr: Used to save the filter string for restoring in rapid mode.
|
||||
tab: The WebTab object we started hinting in.
|
||||
group: The group of web elements to hint.
|
||||
"""
|
||||
@ -90,7 +90,7 @@ class HintContext:
|
||||
self.baseurl = None
|
||||
self.to_follow = None
|
||||
self.rapid = False
|
||||
self.frames = []
|
||||
self.filterstr = None
|
||||
self.args = []
|
||||
self.tab = None
|
||||
self.group = None
|
||||
@ -309,7 +309,6 @@ class HintManager(QObject):
|
||||
_context: The HintContext for the current invocation.
|
||||
_win_id: The window ID this HintManager is associated with.
|
||||
_tab_id: The tab ID this HintManager is associated with.
|
||||
_filterstr: Used to save the filter string for restoring in rapid mode.
|
||||
|
||||
Signals:
|
||||
See HintActions
|
||||
@ -342,7 +341,6 @@ class HintManager(QObject):
|
||||
self._win_id = win_id
|
||||
self._tab_id = tab_id
|
||||
self._context = None
|
||||
self._filterstr = None
|
||||
self._word_hinter = WordHinter()
|
||||
|
||||
self._actions = HintActions(win_id)
|
||||
@ -381,7 +379,6 @@ class HintManager(QObject):
|
||||
window=self._win_id)
|
||||
message_bridge.maybe_reset_text(text)
|
||||
self._context = None
|
||||
self._filterstr = None
|
||||
|
||||
def _hint_strings(self, elems):
|
||||
"""Calculate the hint strings for elems.
|
||||
@ -394,6 +391,8 @@ class HintManager(QObject):
|
||||
Return:
|
||||
A list of hint strings, in the same order as the elements.
|
||||
"""
|
||||
if not elems:
|
||||
return []
|
||||
hint_mode = self._context.hint_mode
|
||||
if hint_mode == 'word':
|
||||
try:
|
||||
@ -630,6 +629,15 @@ class HintManager(QObject):
|
||||
# Do multi-word matching
|
||||
return all(word in elemstr for word in filterstr.split())
|
||||
|
||||
def _filter_matches_exactly(self, filterstr, elemstr):
|
||||
"""Return True if `filterstr` exactly matches `elemstr`."""
|
||||
# Empty string and None never match
|
||||
if not filterstr:
|
||||
return False
|
||||
filterstr = filterstr.casefold()
|
||||
elemstr = elemstr.casefold()
|
||||
return filterstr == elemstr
|
||||
|
||||
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)
|
||||
@ -656,6 +664,9 @@ class HintManager(QObject):
|
||||
modeman.enter(self._win_id, usertypes.KeyMode.hint,
|
||||
'HintManager.start')
|
||||
|
||||
# to make auto-follow == 'always' work
|
||||
self._handle_auto_follow()
|
||||
|
||||
@cmdutils.register(instance='hintmanager', scope='tab', name='hint',
|
||||
star_args_optional=True, maxsplit=2,
|
||||
backend=usertypes.Backend.QtWebKit)
|
||||
@ -753,7 +764,6 @@ class HintManager(QObject):
|
||||
self._context.baseurl = tabbed_browser.current_url()
|
||||
except qtutils.QtValueError:
|
||||
raise cmdexc.CommandError("No URL set for this page yet!")
|
||||
self._context.tab = tab
|
||||
self._context.args = args
|
||||
self._context.group = group
|
||||
selector = webelem.SELECTORS[self._context.group]
|
||||
@ -767,6 +777,51 @@ class HintManager(QObject):
|
||||
|
||||
return self._context.hint_mode
|
||||
|
||||
def _get_visible_hints(self):
|
||||
"""Get elements which are currently visible."""
|
||||
visible = {}
|
||||
for string, elem in self._context.elems.items():
|
||||
try:
|
||||
if not self._is_hidden(elem.label):
|
||||
visible[string] = elem
|
||||
except webelem.Error:
|
||||
pass
|
||||
return visible
|
||||
|
||||
def _handle_auto_follow(self, keystr="", filterstr="", visible=None):
|
||||
"""Handle the auto-follow option."""
|
||||
if visible is None:
|
||||
visible = self._get_visible_hints()
|
||||
|
||||
if len(visible) != 1:
|
||||
return
|
||||
|
||||
auto_follow = config.get('hints', 'auto-follow')
|
||||
|
||||
if auto_follow == "always":
|
||||
follow = True
|
||||
elif auto_follow == "unique-match":
|
||||
follow = keystr or filterstr
|
||||
elif auto_follow == "full-match":
|
||||
elemstr = str(list(visible.values())[0].elem)
|
||||
filter_match = self._filter_matches_exactly(filterstr, elemstr)
|
||||
follow = (keystr in visible) or filter_match
|
||||
else:
|
||||
follow = False
|
||||
# save the keystr of the only one visible hint to be picked up
|
||||
# later by self.follow_hint
|
||||
self._context.to_follow = list(visible.keys())[0]
|
||||
|
||||
if follow:
|
||||
# apply auto-follow-timeout
|
||||
timeout = config.get('hints', 'auto-follow-timeout')
|
||||
keyparsers = objreg.get('keyparsers', scope='window',
|
||||
window=self._win_id)
|
||||
normal_parser = keyparsers[usertypes.KeyMode.normal]
|
||||
normal_parser.set_inhibited_timeout(timeout)
|
||||
# unpacking gets us the first (and only) key in the dict.
|
||||
self._fire(*visible)
|
||||
|
||||
def handle_partial_key(self, keystr):
|
||||
"""Handle a new partial keypress."""
|
||||
log.hints.debug("Handling new keystring: '{}'".format(keystr))
|
||||
@ -790,57 +845,7 @@ class HintManager(QObject):
|
||||
self._hide_elem(elem.label)
|
||||
except webelem.Error:
|
||||
pass
|
||||
|
||||
def _filter_number_hints(self):
|
||||
"""Apply filters for numbered hints and renumber them.
|
||||
|
||||
Return:
|
||||
Elements which are still visible
|
||||
"""
|
||||
# renumber filtered hints
|
||||
elems = []
|
||||
for e in self._context.all_elems:
|
||||
try:
|
||||
if not self._is_hidden(e.label):
|
||||
elems.append(e)
|
||||
except webelem.Error:
|
||||
pass
|
||||
if not elems:
|
||||
# Whoops, filtered all hints
|
||||
modeman.leave(self._win_id, usertypes.KeyMode.hint,
|
||||
'all filtered')
|
||||
return {}
|
||||
|
||||
strings = self._hint_strings(elems)
|
||||
self._context.elems = {}
|
||||
for elem, string in zip(elems, strings):
|
||||
elem.label.set_inner_xml(string)
|
||||
self._context.elems[string] = elem
|
||||
keyparsers = objreg.get('keyparsers', scope='window',
|
||||
window=self._win_id)
|
||||
keyparser = keyparsers[usertypes.KeyMode.hint]
|
||||
keyparser.update_bindings(strings, preserve_filter=True)
|
||||
|
||||
return self._context.elems
|
||||
|
||||
def _filter_non_number_hints(self):
|
||||
"""Apply filters for letter/word hints.
|
||||
|
||||
Return:
|
||||
Elements which are still visible
|
||||
"""
|
||||
visible = {}
|
||||
for string, elem in self._context.elems.items():
|
||||
try:
|
||||
if not self._is_hidden(elem.label):
|
||||
visible[string] = elem
|
||||
except webelem.Error:
|
||||
pass
|
||||
if not visible:
|
||||
# Whoops, filtered all hints
|
||||
modeman.leave(self._win_id, usertypes.KeyMode.hint,
|
||||
'all filtered')
|
||||
return visible
|
||||
self._handle_auto_follow(keystr=keystr)
|
||||
|
||||
def filter_hints(self, filterstr):
|
||||
"""Filter displayed hints according to a text.
|
||||
@ -852,13 +857,15 @@ class HintManager(QObject):
|
||||
and `self._filterstr` are None, all hints are shown.
|
||||
"""
|
||||
if filterstr is None:
|
||||
filterstr = self._filterstr
|
||||
filterstr = self._context.filterstr
|
||||
else:
|
||||
self._filterstr = filterstr
|
||||
self._context.filterstr = filterstr
|
||||
|
||||
visible = []
|
||||
for elem in self._context.all_elems:
|
||||
try:
|
||||
if self._filter_matches(filterstr, str(elem.elem)):
|
||||
visible.append(elem)
|
||||
if self._is_hidden(elem.label):
|
||||
# hidden element which matches again -> show it
|
||||
self._show_elem(elem.label)
|
||||
@ -868,35 +875,37 @@ class HintManager(QObject):
|
||||
except webelem.Error:
|
||||
pass
|
||||
|
||||
if self._context.hint_mode == 'number':
|
||||
visible = self._filter_number_hints()
|
||||
else:
|
||||
visible = self._filter_non_number_hints()
|
||||
if not visible:
|
||||
# Whoops, filtered all hints
|
||||
modeman.leave(self._win_id, usertypes.KeyMode.hint,
|
||||
'all filtered')
|
||||
return
|
||||
|
||||
if (len(visible) == 1 and
|
||||
config.get('hints', 'auto-follow') and
|
||||
filterstr is not None):
|
||||
# apply auto-follow-timeout
|
||||
timeout = config.get('hints', 'auto-follow-timeout')
|
||||
if self._context.hint_mode == 'number':
|
||||
# renumber filtered hints
|
||||
strings = self._hint_strings(visible)
|
||||
self._context.elems = {}
|
||||
for elem, string in zip(visible, strings):
|
||||
elem.label.set_inner_xml(string)
|
||||
self._context.elems[string] = elem
|
||||
keyparsers = objreg.get('keyparsers', scope='window',
|
||||
window=self._win_id)
|
||||
normal_parser = keyparsers[usertypes.KeyMode.normal]
|
||||
normal_parser.set_inhibited_timeout(timeout)
|
||||
# unpacking gets us the first (and only) key in the dict.
|
||||
self.fire(*visible)
|
||||
keyparser = keyparsers[usertypes.KeyMode.hint]
|
||||
keyparser.update_bindings(strings, preserve_filter=True)
|
||||
|
||||
def fire(self, keystr, force=False):
|
||||
# Note: filter_hints can be called with non-None filterstr only
|
||||
# when number mode is active
|
||||
if filterstr is not None:
|
||||
# pass self._context.elems as the dict of visible hints
|
||||
self._handle_auto_follow(filterstr=filterstr,
|
||||
visible=self._context.elems)
|
||||
|
||||
def _fire(self, keystr):
|
||||
"""Fire a completed hint.
|
||||
|
||||
Args:
|
||||
keystr: The keychain string to follow.
|
||||
force: When True, follow even when auto-follow is false.
|
||||
"""
|
||||
if not (force or config.get('hints', 'auto-follow')):
|
||||
self.handle_partial_key(keystr)
|
||||
self._context.to_follow = keystr
|
||||
return
|
||||
|
||||
# Handlers which take a QWebElement
|
||||
elem_handlers = {
|
||||
Target.normal: self._actions.click,
|
||||
@ -969,7 +978,7 @@ class HintManager(QObject):
|
||||
keystring = self._context.to_follow
|
||||
elif keystring not in self._context.elems:
|
||||
raise cmdexc.CommandError("No hint {}!".format(keystring))
|
||||
self.fire(keystring, force=True)
|
||||
self._fire(keystring)
|
||||
|
||||
@pyqtSlot()
|
||||
def on_contents_size_changed(self):
|
||||
|
@ -365,6 +365,8 @@ class ConfigManager(QObject):
|
||||
_get_value_transformer({'false': 'none', 'true': 'debug'}),
|
||||
('ui', 'keyhint-blacklist'):
|
||||
_get_value_transformer({'false': '*', 'true': ''}),
|
||||
('hints', 'auto-follow'):
|
||||
_get_value_transformer({'false': 'never', 'true': 'unique-match'}),
|
||||
}
|
||||
|
||||
changed = pyqtSignal(str, str)
|
||||
|
@ -936,9 +936,21 @@ def data(readonly=False):
|
||||
"The dictionary file to be used by the word hints."),
|
||||
|
||||
('auto-follow',
|
||||
SettingValue(typ.Bool(), 'true'),
|
||||
"Follow a hint immediately when the hint text is completely "
|
||||
"matched."),
|
||||
SettingValue(typ.String(
|
||||
valid_values=typ.ValidValues(
|
||||
('always', "Auto-follow whenever there is only a single "
|
||||
"hint on a page."),
|
||||
('unique-match', "Auto-follow whenever there is a unique "
|
||||
"non-empty match in either the hint string (word mode) "
|
||||
"or filter (number mode)."),
|
||||
('full-match', "Follow the hint when the user typed the "
|
||||
"whole hint (letter, word or number mode) or the "
|
||||
"element's text (only in number mode)."),
|
||||
('never', "The user will always need to press Enter to "
|
||||
"follow a hint."),
|
||||
)), 'unique-match'),
|
||||
"Controls when a hint can be automatically followed without the "
|
||||
"user pressing Enter."),
|
||||
|
||||
('auto-follow-timeout',
|
||||
SettingValue(typ.Int(), '0'),
|
||||
|
@ -231,7 +231,7 @@ class HintKeyParser(keyparser.CommandKeyParser):
|
||||
if keytype == self.Type.chain:
|
||||
hintmanager = objreg.get('hintmanager', scope='tab',
|
||||
window=self._win_id, tab='current')
|
||||
hintmanager.fire(cmdstr)
|
||||
hintmanager.handle_partial_key(cmdstr)
|
||||
else:
|
||||
# execute as command
|
||||
super().execute(cmdstr, keytype, count)
|
||||
|
@ -39,10 +39,10 @@ Feature: Using hints
|
||||
- data/hello.txt (active)
|
||||
|
||||
Scenario: Entering and leaving hinting mode (issue 1464)
|
||||
When I open data/hints/html/simple.html
|
||||
And I run :hint
|
||||
And I run :fake-key -g <Esc>
|
||||
Then no crash should happen
|
||||
When I open data/hints/html/simple.html
|
||||
And I run :hint
|
||||
And I run :fake-key -g <Esc>
|
||||
Then no crash should happen
|
||||
|
||||
Scenario: Using :hint spawn with flags and -- (issue 797)
|
||||
When I open data/hints/html/simple.html
|
||||
@ -225,7 +225,7 @@ Feature: Using hints
|
||||
Scenario: Multi-word matching
|
||||
When I open data/hints/number.html
|
||||
And I set hints -> mode to number
|
||||
And I set hints -> auto-follow to true
|
||||
And I set hints -> auto-follow to unique-match
|
||||
And I set hints -> auto-follow-timeout to 0
|
||||
And I run :hint all
|
||||
And I press the keys "ten pos"
|
||||
@ -265,3 +265,133 @@ Feature: Using hints
|
||||
And I press the key "s"
|
||||
And I run :follow-hint 1
|
||||
Then data/numbers/7.txt should be loaded
|
||||
|
||||
### auto-follow option
|
||||
|
||||
Scenario: Using hints -> auto-follow == 'always' in letter mode
|
||||
When I open data/hints/html/simple.html
|
||||
And I set hints -> mode to letter
|
||||
And I set hints -> auto-follow to always
|
||||
And I run :hint
|
||||
Then data/hello.txt should be loaded
|
||||
|
||||
# unique-match is actually the same as full-match in letter mode
|
||||
Scenario: Using hints -> auto-follow == 'unique-match' in letter mode
|
||||
When I open data/hints/html/simple.html
|
||||
And I set hints -> mode to letter
|
||||
And I set hints -> auto-follow to unique-match
|
||||
And I run :hint
|
||||
And I press the key "a"
|
||||
Then data/hello.txt should be loaded
|
||||
|
||||
Scenario: Using hints -> auto-follow == 'full-match' in letter mode
|
||||
When I open data/hints/html/simple.html
|
||||
And I set hints -> mode to letter
|
||||
And I set hints -> auto-follow to full-match
|
||||
And I run :hint
|
||||
And I press the key "a"
|
||||
Then data/hello.txt should be loaded
|
||||
|
||||
Scenario: Using hints -> auto-follow == 'never' without Enter in letter mode
|
||||
When I open data/hints/html/simple.html
|
||||
And I set hints -> mode to letter
|
||||
And I set hints -> auto-follow to never
|
||||
And I run :hint
|
||||
And I press the key "a"
|
||||
Then "Leaving mode KeyMode.hint (reason: followed)" should not be logged
|
||||
|
||||
Scenario: Using hints -> auto-follow == 'never' in letter mode
|
||||
When I open data/hints/html/simple.html
|
||||
And I set hints -> mode to letter
|
||||
And I set hints -> auto-follow to never
|
||||
And I run :hint
|
||||
And I press the key "a"
|
||||
And I press the key "<Enter>"
|
||||
Then data/hello.txt should be loaded
|
||||
|
||||
Scenario: Using hints -> auto-follow == 'always' in number mode
|
||||
When I open data/hints/html/simple.html
|
||||
And I set hints -> mode to number
|
||||
And I set hints -> auto-follow to always
|
||||
And I run :hint
|
||||
Then data/hello.txt should be loaded
|
||||
|
||||
Scenario: Using hints -> auto-follow == 'unique-match' in number mode
|
||||
When I open data/hints/html/simple.html
|
||||
And I set hints -> mode to number
|
||||
And I set hints -> auto-follow to unique-match
|
||||
And I run :hint
|
||||
And I press the key "f"
|
||||
Then data/hello.txt should be loaded
|
||||
|
||||
Scenario: Using hints -> auto-follow == 'full-match' in number mode
|
||||
When I open data/hints/html/simple.html
|
||||
And I set hints -> mode to number
|
||||
And I set hints -> auto-follow to full-match
|
||||
And I run :hint
|
||||
# this actually presses the keys one by one
|
||||
And I press the key "follow me!"
|
||||
Then data/hello.txt should be loaded
|
||||
|
||||
Scenario: Using hints -> auto-follow == 'never' without Enter in number mode
|
||||
When I open data/hints/html/simple.html
|
||||
And I set hints -> mode to number
|
||||
And I set hints -> auto-follow to never
|
||||
And I run :hint
|
||||
# this actually presses the keys one by one
|
||||
And I press the key "follow me!"
|
||||
Then "Leaving mode KeyMode.hint (reason: followed)" should not be logged
|
||||
|
||||
Scenario: Using hints -> auto-follow == 'never' in number mode
|
||||
When I open data/hints/html/simple.html
|
||||
And I set hints -> mode to number
|
||||
And I set hints -> auto-follow to never
|
||||
And I run :hint
|
||||
# this actually presses the keys one by one
|
||||
And I press the key "follow me!"
|
||||
And I press the key "<Enter>"
|
||||
Then data/hello.txt should be loaded
|
||||
|
||||
Scenario: Using hints -> auto-follow == 'always' in word mode
|
||||
When I open data/hints/html/simple.html
|
||||
And I set hints -> mode to word
|
||||
And I set hints -> auto-follow to always
|
||||
And I run :hint
|
||||
Then data/hello.txt should be loaded
|
||||
|
||||
Scenario: Using hints -> auto-follow == 'unique-match' in word mode
|
||||
When I open data/hints/html/simple.html
|
||||
And I set hints -> mode to word
|
||||
And I set hints -> auto-follow to unique-match
|
||||
And I run :hint
|
||||
# the link gets "hello" as the hint
|
||||
And I press the key "h"
|
||||
Then data/hello.txt should be loaded
|
||||
|
||||
Scenario: Using hints -> auto-follow == 'full-match' in word mode
|
||||
When I open data/hints/html/simple.html
|
||||
And I set hints -> mode to word
|
||||
And I set hints -> auto-follow to full-match
|
||||
And I run :hint
|
||||
# this actually presses the keys one by one
|
||||
And I press the key "hello"
|
||||
Then data/hello.txt should be loaded
|
||||
|
||||
Scenario: Using hints -> auto-follow == 'never' without Enter in word mode
|
||||
When I open data/hints/html/simple.html
|
||||
And I set hints -> mode to word
|
||||
And I set hints -> auto-follow to never
|
||||
And I run :hint
|
||||
# this actually presses the keys one by one
|
||||
And I press the key "hello"
|
||||
Then "Leaving mode KeyMode.hint (reason: followed)" should not be logged
|
||||
|
||||
Scenario: Using hints -> auto-follow == 'never' in word mode
|
||||
When I open data/hints/html/simple.html
|
||||
And I set hints -> mode to word
|
||||
And I set hints -> auto-follow to never
|
||||
And I run :hint
|
||||
# this actually presses the keys one by one
|
||||
And I press the key "hello"
|
||||
And I press the key "<Enter>"
|
||||
Then data/hello.txt should be loaded
|
||||
|
@ -17,5 +17,30 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import textwrap
|
||||
|
||||
import pytest
|
||||
|
||||
import pytest_bdd as bdd
|
||||
bdd.scenarios('hints.feature')
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def set_up_word_hints(tmpdir, quteproc):
|
||||
dict_file = tmpdir / 'dict'
|
||||
dict_file.write(textwrap.dedent("""
|
||||
one
|
||||
two
|
||||
three
|
||||
four
|
||||
five
|
||||
six
|
||||
seven
|
||||
eight
|
||||
nine
|
||||
ten
|
||||
eleven
|
||||
twelve
|
||||
thirteen
|
||||
"""))
|
||||
quteproc.set_setting('hints', 'dictionary', str(dict_file))
|
||||
|
Loading…
Reference in New Issue
Block a user