mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-20 06:07:59 +01:00
Add 'hintkeys' and fix <BS> key in Hint mode.
--HG-- extra : rebase_source : d28184df01b5c3b2194fc332ff8367cb1c7c1fcf
This commit is contained in:
@@ -920,8 +920,8 @@ const Events = Module("events", {
|
|||||||
// under HINT mode, certain keys are redirected to hints.onEvent
|
// under HINT mode, certain keys are redirected to hints.onEvent
|
||||||
if (key == "<Return>" || key == "<Tab>" || key == "<S-Tab>"
|
if (key == "<Return>" || key == "<Tab>" || key == "<S-Tab>"
|
||||||
|| key == mappings.getMapLeader()
|
|| key == mappings.getMapLeader()
|
||||||
|| (key == "<BS>" && hints.previnput == "number")
|
|| (key == "<BS>" && hints.prevInput == "number")
|
||||||
|| (/^[0-9]$/.test(key) && !hints.escNumbers)) {
|
|| (hints.isHintKey(key) && !hints.escNumbers)) {
|
||||||
hints.onEvent(event);
|
hints.onEvent(event);
|
||||||
this._input.buffer = "";
|
this._input.buffer = "";
|
||||||
throw killEvent();
|
throw killEvent();
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const Hints = Module("hints", {
|
|||||||
this._hintString = ""; // the typed string part of the hint is in this string
|
this._hintString = ""; // the typed string part of the hint is in this string
|
||||||
this._hintNumber = 0; // only the numerical part of the hint
|
this._hintNumber = 0; // only the numerical part of the hint
|
||||||
this._usedTabKey = false; // when we used <Tab> to select an element
|
this._usedTabKey = false; // when we used <Tab> to select an element
|
||||||
this._prevInput = ""; // record previous user input type, "text" || "number"
|
this.prevInput = ""; // record previous user input type, "text" || "number"
|
||||||
this._extendedhintCount = null; // for the count argument of Mode#action (extended hint only)
|
this._extendedhintCount = null; // for the count argument of Mode#action (extended hint only)
|
||||||
|
|
||||||
this._pageHints = [];
|
this._pageHints = [];
|
||||||
@@ -67,7 +67,7 @@ const Hints = Module("hints", {
|
|||||||
this._hintString = "";
|
this._hintString = "";
|
||||||
this._hintNumber = 0;
|
this._hintNumber = 0;
|
||||||
this._usedTabKey = false;
|
this._usedTabKey = false;
|
||||||
this._prevInput = "";
|
this.prevInput = "";
|
||||||
this._pageHints = [];
|
this._pageHints = [];
|
||||||
this._validHints = [];
|
this._validHints = [];
|
||||||
this._canUpdate = false;
|
this._canUpdate = false;
|
||||||
@@ -83,7 +83,8 @@ const Hints = Module("hints", {
|
|||||||
* Display the current status to the user.
|
* Display the current status to the user.
|
||||||
*/
|
*/
|
||||||
_updateStatusline: function () {
|
_updateStatusline: function () {
|
||||||
statusline.updateInputBuffer((hints.escNumbers ? mappings.getMapLeader() : "") + (this._hintNumber || ""));
|
statusline.updateInputBuffer((hints.escNumbers ? mappings.getMapLeader() : "") +
|
||||||
|
(this._hintNumber ? this.getHintString(this._hintNumber) : ""));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -256,7 +257,7 @@ const Hints = Module("hints", {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
let computedStyle = doc.defaultView.getComputedStyle(elem, null);
|
let computedStyle = doc.defaultView.getComputedStyle(elem, null);
|
||||||
if (computedStyle.getPropertyValue("visibility") != "visible" || computedStyle.getPropertyValue("display") == "none")
|
if (computedStyle["visibility"] != "visible" || computedStyle["display"] == "none")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (isinstance(elem, [HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement]))
|
if (isinstance(elem, [HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement]))
|
||||||
@@ -268,7 +269,7 @@ const Hints = Module("hints", {
|
|||||||
|
|
||||||
rect = elem.getClientRects()[0] || rect;
|
rect = elem.getClientRects()[0] || rect;
|
||||||
let leftPos = Math.max((rect.left + offsetX), offsetX);
|
let leftPos = Math.max((rect.left + offsetX), offsetX);
|
||||||
let topPos = Math.max((rect.top + offsetY), offsetY);
|
let topPos = Math.max((rect.top + offsetY), offsetY);
|
||||||
|
|
||||||
if (elem instanceof HTMLAreaElement)
|
if (elem instanceof HTMLAreaElement)
|
||||||
[leftPos, topPos] = this._getAreaOffset(elem, leftPos, topPos);
|
[leftPos, topPos] = this._getAreaOffset(elem, leftPos, topPos);
|
||||||
@@ -366,9 +367,10 @@ const Hints = Module("hints", {
|
|||||||
this._setClass(hint.imgSpan, activeHint == hintnum);
|
this._setClass(hint.imgSpan, activeHint == hintnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
hint.span.setAttribute("number", hint.showText ? hintnum + ": " + hint.text.substr(0, 50) : hintnum);
|
let str = this.getHintString(hintnum);
|
||||||
|
hint.span.setAttribute("number", hint.showText ? str + ": " + hint.text.substr(0, 50) : str);
|
||||||
if (hint.imgSpan)
|
if (hint.imgSpan)
|
||||||
hint.imgSpan.setAttribute("number", hintnum);
|
hint.imgSpan.setAttribute("number", str);
|
||||||
else
|
else
|
||||||
this._setClass(hint.elem, activeHint == hintnum);
|
this._setClass(hint.elem, activeHint == hintnum);
|
||||||
this._validHints.push(hint.elem);
|
this._validHints.push(hint.elem);
|
||||||
@@ -481,7 +483,7 @@ const Hints = Module("hints", {
|
|||||||
|
|
||||||
// if we write a numeric part like 3, but we have 45 hints, only follow
|
// if we write a numeric part like 3, but we have 45 hints, only follow
|
||||||
// the hint after a timeout, as the user might have wanted to follow link 34
|
// the hint after a timeout, as the user might have wanted to follow link 34
|
||||||
if (this._hintNumber > 0 && this._hintNumber * 10 <= this._validHints.length) {
|
if (this._hintNumber > 0 && this._hintNumber * this.hintKeys.length <= this._validHints.length) {
|
||||||
let timeout = options["hinttimeout"];
|
let timeout = options["hinttimeout"];
|
||||||
if (timeout > 0)
|
if (timeout > 0)
|
||||||
this._activeTimeout = this.timeout(function () { this._processHints(true); }, timeout);
|
this._activeTimeout = this.timeout(function () { this._processHints(true); }, timeout);
|
||||||
@@ -499,7 +501,7 @@ const Hints = Module("hints", {
|
|||||||
* @param {Event} event The keypress event.
|
* @param {Event} event The keypress event.
|
||||||
*/
|
*/
|
||||||
_onInput: function (event) {
|
_onInput: function (event) {
|
||||||
this._prevInput = "text";
|
this.prevInput = "text";
|
||||||
|
|
||||||
// clear any timeout which might be active after pressing a number
|
// clear any timeout which might be active after pressing a number
|
||||||
if (this._activeTimeout) {
|
if (this._activeTimeout) {
|
||||||
@@ -703,6 +705,32 @@ const Hints = Module("hints", {
|
|||||||
this._hintModes[mode] = Hints.Mode.apply(Hints.Mode, Array.slice(arguments, 1));
|
this._hintModes[mode] = Hints.Mode.apply(Hints.Mode, Array.slice(arguments, 1));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the hint string for a given number based on the values of
|
||||||
|
* the 'hintkeys' option.
|
||||||
|
*
|
||||||
|
* @param {number} n The number to transform.
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
getHintString: function (n) {
|
||||||
|
let res = [], len = this.hintKeys.length;
|
||||||
|
do {
|
||||||
|
res.push(this.hintKeys[n % len]);
|
||||||
|
n = Math.floor(n / len);
|
||||||
|
}
|
||||||
|
while (n > 0);
|
||||||
|
return res.reverse().join("");
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given key string represents a
|
||||||
|
* pseudo-hint-number.
|
||||||
|
*
|
||||||
|
* @param {string} key The key to test.
|
||||||
|
* @returns {boolean} Whether the key represents a hint number.
|
||||||
|
*/
|
||||||
|
isHintKey: function (key) this.hintKeys.indexOf(key) >= 0,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the display of hints.
|
* Updates the display of hints.
|
||||||
*
|
*
|
||||||
@@ -717,11 +745,12 @@ const Hints = Module("hints", {
|
|||||||
commandline.input(this._hintMode.prompt + ": ", null, { onChange: this.closure._onInput });
|
commandline.input(this._hintMode.prompt + ": ", null, { onChange: this.closure._onInput });
|
||||||
modes.extended = modes.HINTS;
|
modes.extended = modes.HINTS;
|
||||||
|
|
||||||
|
this.hintKeys = events.fromString(options["hintkeys"]).map(events.closure.toString);
|
||||||
this._submode = minor;
|
this._submode = minor;
|
||||||
this._hintString = filter || "";
|
this._hintString = filter || "";
|
||||||
this._hintNumber = 0;
|
this._hintNumber = 0;
|
||||||
this._usedTabKey = false;
|
this._usedTabKey = false;
|
||||||
this._prevInput = "";
|
this.prevInput = "";
|
||||||
this._canUpdate = false;
|
this._canUpdate = false;
|
||||||
|
|
||||||
this._generate(win);
|
this._generate(win);
|
||||||
@@ -790,9 +819,9 @@ const Hints = Module("hints", {
|
|||||||
|
|
||||||
case "<BS>":
|
case "<BS>":
|
||||||
if (this._hintNumber > 0 && !this._usedTabKey) {
|
if (this._hintNumber > 0 && !this._usedTabKey) {
|
||||||
this._hintNumber = Math.floor(this._hintNumber / 10);
|
this._hintNumber = Math.floor(this._hintNumber / this.hintKeys.length);
|
||||||
if (this._hintNumber == 0)
|
if (this._hintNumber == 0)
|
||||||
this._prevInput = "text";
|
this.prevInput = "text";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this._usedTabKey = false;
|
this._usedTabKey = false;
|
||||||
@@ -811,16 +840,16 @@ const Hints = Module("hints", {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (/^\d$/.test(key)) {
|
if (this.isHintKey(key)) {
|
||||||
this._prevInput = "number";
|
this.prevInput = "number";
|
||||||
|
|
||||||
let oldHintNumber = this._hintNumber;
|
let oldHintNumber = this._hintNumber;
|
||||||
if (this._hintNumber == 0 || this._usedTabKey) {
|
if (this._usedTabKey) {
|
||||||
|
this._hintNumber = 0;
|
||||||
this._usedTabKey = false;
|
this._usedTabKey = false;
|
||||||
this._hintNumber = parseInt(key, 10);
|
|
||||||
}
|
}
|
||||||
else
|
this._hintNumber = this._hintNumber * this.hintKeys.length +
|
||||||
this._hintNumber = parseInt(String(this._hintNumber) + key, 10);
|
this.hintKeys.indexOf(key);
|
||||||
|
|
||||||
this._updateStatusline();
|
this._updateStatusline();
|
||||||
|
|
||||||
@@ -1028,6 +1057,19 @@ const Hints = Module("hints", {
|
|||||||
"string", DEFAULT_HINTTAGS,
|
"string", DEFAULT_HINTTAGS,
|
||||||
{ validator: checkXPath });
|
{ validator: checkXPath });
|
||||||
|
|
||||||
|
options.add(["hintkeys", "hk"],
|
||||||
|
"The keys used to label and select hints",
|
||||||
|
"string", "0123456789",
|
||||||
|
{
|
||||||
|
completer: function () [
|
||||||
|
["0123456789", "Numbers"],
|
||||||
|
["asdfg;lkjh", "Home Row"]],
|
||||||
|
validator: function (value) {
|
||||||
|
let values = events.fromString(value).map(events.closure.toString).sort();
|
||||||
|
return array.equals(array.uniq(values), values);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
options.add(["hinttimeout", "hto"],
|
options.add(["hinttimeout", "hto"],
|
||||||
"Timeout before automatically following a non-unique numerical hint",
|
"Timeout before automatically following a non-unique numerical hint",
|
||||||
"number", 0,
|
"number", 0,
|
||||||
|
|||||||
@@ -660,6 +660,23 @@
|
|||||||
</item>
|
</item>
|
||||||
|
|
||||||
|
|
||||||
|
<item>
|
||||||
|
<tags>'hk' 'hintkeys'</tags>
|
||||||
|
<spec>'hintkeys' 'hk'</spec>
|
||||||
|
<type>string</type>
|
||||||
|
<default>0123456789</default>
|
||||||
|
<description>
|
||||||
|
<p>
|
||||||
|
The keys used to label and select hints. With its default value,
|
||||||
|
each hint has a unique number which can be typed to select it,
|
||||||
|
while all other characters are used to filter hints based on their
|
||||||
|
text. With a value such as <str>asdfg;lkjh</str>, each hint is
|
||||||
|
‘numbered’ based on the characters of the home row.
|
||||||
|
</p>
|
||||||
|
</description>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<tags>'hm' 'hintmatching'</tags>
|
<tags>'hm' 'hintmatching'</tags>
|
||||||
<spec>'hintmatching' 'hm'</spec>
|
<spec>'hintmatching' 'hm'</spec>
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
* IMPORTANT: Single quotes no longer treat \s specially
|
* IMPORTANT: Single quotes no longer treat \s specially
|
||||||
I.e., 'fo\o''bar' ≡ fo\o'bar
|
I.e., 'fo\o''bar' ≡ fo\o'bar
|
||||||
* Replaced 'focuscontent' with 'strictfocus'
|
* Replaced 'focuscontent' with 'strictfocus'
|
||||||
|
* Added 'hintkeys' option
|
||||||
* Added 'altwildmode' and <A-Tab> commandline key binding
|
* Added 'altwildmode' and <A-Tab> commandline key binding
|
||||||
* Added 'banghist' option
|
* Added 'banghist' option
|
||||||
* Added ‘transliterated’ option to 'hintmatching'
|
* Added ‘transliterated’ option to 'hintmatching'
|
||||||
|
|||||||
Reference in New Issue
Block a user