Implement hint strings
This commit is contained in:
parent
809e7e15b8
commit
98ed6c9812
@ -18,6 +18,7 @@
|
|||||||
"""A HintManager to draw hints over links."""
|
"""A HintManager to draw hints over links."""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import math
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
import qutebrowser.config.config as config
|
||||||
|
|
||||||
@ -70,14 +71,82 @@ class HintManager:
|
|||||||
self._elems = []
|
self._elems = []
|
||||||
self._labels = []
|
self._labels = []
|
||||||
|
|
||||||
def _draw_label(self, elem):
|
def _hint_strings(self, elems):
|
||||||
|
"""Calculate the hint strings for elems.
|
||||||
|
|
||||||
|
Inspirated by Vimium.
|
||||||
|
"""
|
||||||
|
chars = config.get("hints", "chars")
|
||||||
|
# Determine how many digits the link hints will require in the worst
|
||||||
|
# case. Usually we do not need all of these digits for every link
|
||||||
|
# single hint, so we can show shorter hints for a few of the links.
|
||||||
|
needed = math.ceil(math.log(len(elems), len(chars)))
|
||||||
|
# Short hints are the number of hints we can possibly show which are
|
||||||
|
# (needed - 1) digits in length.
|
||||||
|
short_count = math.floor((len(chars) ** needed - len(elems)) /
|
||||||
|
len(chars))
|
||||||
|
long_count = len(elems) - short_count
|
||||||
|
|
||||||
|
strings = []
|
||||||
|
|
||||||
|
if needed > 1:
|
||||||
|
for i in range(short_count):
|
||||||
|
strings.append(self._number_to_hint_str(i, chars, needed - 1))
|
||||||
|
|
||||||
|
start = short_count * len(chars)
|
||||||
|
for i in range(start, start + long_count):
|
||||||
|
strings.append(self._number_to_hint_str(i, chars, needed))
|
||||||
|
|
||||||
|
return self._shuffle_hints(strings, len(chars))
|
||||||
|
|
||||||
|
def _shuffle_hints(self, hints, length):
|
||||||
|
"""Shuffle the given set of hints so that they're scattered.
|
||||||
|
|
||||||
|
Hints starting with the same character will be spread evenly throughout
|
||||||
|
the array.
|
||||||
|
|
||||||
|
Inspired by Vimium.
|
||||||
|
"""
|
||||||
|
buckets = [[] for i in range(length)]
|
||||||
|
for i, hint in enumerate(hints):
|
||||||
|
buckets[i % len(buckets)].append(hint)
|
||||||
|
result = []
|
||||||
|
for bucket in buckets:
|
||||||
|
result += bucket
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _number_to_hint_str(self, number, chars, digits=0):
|
||||||
|
"""Convert a number like "8" into a hint string like "JK".
|
||||||
|
|
||||||
|
This is used to sequentially generate all of the hint text.
|
||||||
|
The hint string will be "padded with zeroes" to ensure its length is >=
|
||||||
|
digits.
|
||||||
|
|
||||||
|
Inspired by Vimium.
|
||||||
|
"""
|
||||||
|
base = len(chars)
|
||||||
|
hintstr = []
|
||||||
|
remainder = 0
|
||||||
|
while True:
|
||||||
|
remainder = number % base
|
||||||
|
hintstr.insert(0, chars[remainder])
|
||||||
|
number -= remainder
|
||||||
|
number //= base
|
||||||
|
if number <= 0:
|
||||||
|
break
|
||||||
|
# Pad the hint string we're returning so that it matches digits.
|
||||||
|
for i in range(0, digits - len(hintstr)):
|
||||||
|
hintstr.insert(0, chars[0])
|
||||||
|
return ''.join(hintstr)
|
||||||
|
|
||||||
|
def _draw_label(self, elem, string):
|
||||||
"""Draw a hint label over an element."""
|
"""Draw a hint label over an element."""
|
||||||
rect = elem.geometry()
|
rect = elem.geometry()
|
||||||
css = HintManager.HINT_CSS.format(left=rect.x(), top=rect.y(),
|
css = HintManager.HINT_CSS.format(left=rect.x(), top=rect.y(),
|
||||||
config=config.instance)
|
config=config.instance)
|
||||||
doc = self._frame.documentElement()
|
doc = self._frame.documentElement()
|
||||||
doc.appendInside('<span class="qutehint" style="{}">foo</span>'.format(
|
doc.appendInside('<span class="qutehint" style="{}">{}</span>'.format(
|
||||||
css))
|
css, string))
|
||||||
self._labels.append(doc.lastChild())
|
self._labels.append(doc.lastChild())
|
||||||
|
|
||||||
def start(self, mode="all"):
|
def start(self, mode="all"):
|
||||||
@ -99,7 +168,9 @@ class HintManager:
|
|||||||
# out of screen
|
# out of screen
|
||||||
continue
|
continue
|
||||||
self._elems.append(e)
|
self._elems.append(e)
|
||||||
self._draw_label(e)
|
strings = self._hint_strings(self._elems)
|
||||||
|
for e, string in zip(self._elems, strings):
|
||||||
|
self._draw_label(e, string)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""Stop hinting."""
|
"""Stop hinting."""
|
||||||
|
@ -311,6 +311,9 @@ DATA = OrderedDict([
|
|||||||
('opacity',
|
('opacity',
|
||||||
SettingValue(types.Float, "0.7"),
|
SettingValue(types.Float, "0.7"),
|
||||||
"Opacity for hints."),
|
"Opacity for hints."),
|
||||||
|
('chars',
|
||||||
|
SettingValue(types.String, "asdfghjkl"),
|
||||||
|
"Chars used for hint strings."),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
('searchengines', sect.ValueList(
|
('searchengines', sect.ValueList(
|
||||||
|
Loading…
Reference in New Issue
Block a user