1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2025-12-23 13:52:26 +01:00

Add hints.addMode (e.g., hints.addMode("k", "Kill image", function (elem) elem.style.display="none", function () "//img")). Etc.

This commit is contained in:
Kris Maglione
2008-11-18 20:10:24 +00:00
parent 870538e032
commit a4072000c9
2 changed files with 78 additions and 84 deletions

View File

@@ -179,14 +179,19 @@ function Commands() //{{{
return NaN; return NaN;
} }
function quote(q, list) list.reduce(function (acc, [k, v]) { const quoteMap = {
v = "\\" + (v || k); "\n": "n",
return function (str) acc(String.replace(str, k, v, "g")) "\t": "t"
}, function (val) q + val + q); }
function quote(q, list)
{
let re = RegExp("[" + list + "]", "g");
return function (str) q + str.replace(re, function ($0, $1) $1 in quoteMap ? quoteMap[$1] : "\\" + $1) + q;
}
const quoteArg = { const quoteArg = {
'"': quote('"', [["\n", "n"], ["\t", "t"], ['"'], ["\\"]]), '"': quote('"', '\n\t"\\\\'),
"'": quote("'", [["\\"], ["'"]]), "'": quote("'", "\\\\'"),
"": quote("", [["\\"], [" "]]) "": quote("", "\\\\ ")
} }
const ArgType = new Struct("description", "parse"); const ArgType = new Struct("description", "parse");
@@ -439,6 +444,9 @@ function Commands() //{{{
while (i < str.length) while (i < str.length)
{ {
// skip whitespace // skip whitespace
//let re = /^\s*/;
//re.lastIndex = i;
//i += re.exec(str)[0].length;
if (/\s/.test(str[i])) if (/\s/.test(str[i]))
{ {
i++; i++;
@@ -501,16 +509,16 @@ function Commands() //{{{
if (quote) if (quote)
{ {
if (!complete) if (complete)
{ {
liberator.echoerr("Invalid argument for option " + optname); args.completions = opt[3] || [];
return null; if (typeof args.completions == "function")
args.completions = args.completions();
args.quote = quoteArg[sub[optname.length + 1]] || quoteArg[""];
return args;
} }
let compl = opt[3] || []; liberator.echoerr("Invalid argument for option " + optname);
if (typeof compl == "function") return null;
compl = compl();
let quote = quoteArg[sub[optname.length + 1]] || quoteArg[""];
return [i + optname.length + 1, completion.filter(compl.map(quote), quote(arg))];
} }
if (!invalid) if (!invalid)

View File

@@ -32,6 +32,8 @@ function Hints() //{{{
////////////////////// PRIVATE SECTION ///////////////////////////////////////// ////////////////////// PRIVATE SECTION /////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////{{{ /////////////////////////////////////////////////////////////////////////////{{{
const ELEM = 0, TEXT = 1, SPAN = 2, IMGSPAN = 3, BGCOLOR = 4, COLOR = 5;
var myModes = config.browserModes; var myModes = config.browserModes;
var hintMode; var hintMode;
@@ -53,24 +55,26 @@ function Hints() //{{{
// docs = { doc: document, start: start_index in hints[], end: end_index in hints[] } // docs = { doc: document, start: start_index in hints[], end: end_index in hints[] }
var docs = []; var docs = [];
const Mode = new Struct("prompt", "action", "extended"); const Mode = new Struct("prompt", "action", "tags");
Mode.defaultValue("tags", function () function () options.hinttags);
function extended() options.extendedhinttags;
const hintModes = { const hintModes = {
";": Mode("Focus hint", function (elem) buffer.focusElement(elem), true), ";": Mode("Focus hint", function (elem) buffer.focusElement(elem), extended),
a: Mode("Save hint with prompt", function (elem) buffer.saveLink(elem, false)), a: Mode("Save hint with prompt", function (elem) buffer.saveLink(elem, false)),
s: Mode("Save hint", function (elem) buffer.saveLink(elem, true)), s: Mode("Save hint", function (elem) buffer.saveLink(elem, true)),
o: Mode("Follow hint", function (elem) buffer.followLink(elem, liberator.CURRENT_TAB)), o: Mode("Follow hint", function (elem) buffer.followLink(elem, liberator.CURRENT_TAB)),
t: Mode("Follow hint in a new tab", function (elem) buffer.followLink(elem, liberator.NEW_TAB)), t: Mode("Follow hint in a new tab", function (elem) buffer.followLink(elem, liberator.NEW_TAB)),
b: Mode("Follow hint in a background tab", function (elem) buffer.followLink(elem, liberator.NEW_BACKGROUND_TAB)), b: Mode("Follow hint in a background tab", function (elem) buffer.followLink(elem, liberator.NEW_BACKGROUND_TAB)),
v: Mode("View hint source", function (elem, loc) buffer.viewSource(loc, false), true), v: Mode("View hint source", function (elem, loc) buffer.viewSource(loc, false), extended),
V: Mode("View hint source", function (elem, loc) buffer.viewSource(loc, true), true), V: Mode("View hint source", function (elem, loc) buffer.viewSource(loc, true), extended),
w: Mode("Follow hint in a new window", function (elem) buffer.followLink(elem, liberator.NEW_WINDOW), true), w: Mode("Follow hint in a new window", function (elem) buffer.followLink(elem, liberator.NEW_WINDOW), extended),
"?": Mode("Show information for hint", function (elem) buffer.showElementInfo(elem), true), "?": Mode("Show information for hint", function (elem) buffer.showElementInfo(elem), extended),
O: Mode("Open location based on hint", function (elem, loc) commandline.open(":", "open " + loc, modes.EX)), O: Mode("Open location based on hint", function (elem, loc) commandline.open(":", "open " + loc, modes.EX)),
T: Mode("Open new tab based on hint", function (elem, loc) commandline.open(":", "tabopen " + loc, modes.EX)), T: Mode("Open new tab based on hint", function (elem, loc) commandline.open(":", "tabopen " + loc, modes.EX)),
W: Mode("Open new window based on hint", function (elem, loc) commandline.open(":", "winopen " + loc, modes.EX)), W: Mode("Open new window based on hint", function (elem, loc) commandline.open(":", "winopen " + loc, modes.EX)),
y: Mode("Yank hint location", function (elem, loc) util.copyToClipboard(loc, true)), y: Mode("Yank hint location", function (elem, loc) util.copyToClipboard(loc, true)),
Y: Mode("Yank hint description", function (elem) util.copyToClipboard(elem.textContent || "", true), true), Y: Mode("Yank hint description", function (elem) util.copyToClipboard(elem.textContent || "", true), extended),
}; };
// reset all important variables // reset all important variables
@@ -112,7 +116,7 @@ function Hints() //{{{
<span class="liberator-hint"/>, doc); <span class="liberator-hint"/>, doc);
var elem, tagname, text, span, rect; var elem, tagname, text, span, rect;
var res = buffer.evaluateXPath(options[hintMode.extended ? "extendedhinttags" : "hinttags"], doc, null, true); var res = buffer.evaluateXPath(hintMode.tags(), doc, null, true);
var fragment = doc.createDocumentFragment(); var fragment = doc.createDocumentFragment();
var start = pageHints.length; var start = pageHints.length;
@@ -181,19 +185,16 @@ function Hints() //{{{
var activelinkfgcolor = options["activelinkfgcolor"]; var activelinkfgcolor = options["activelinkfgcolor"];
var activelinkbgcolor = options["activelinkbgcolor"]; var activelinkbgcolor = options["activelinkbgcolor"];
var elem, tagname, text, rect, span, imgspan; let elem, tagname, text, rect, span, imgspan;
var hintnum = 1; let hintnum = 1;
var validHint = hintMatcher(hintString.toLowerCase()); let validHint = hintMatcher(hintString.toLowerCase());
var activeHint = hintNumber || 1; let activeHint = hintNumber || 1;
validHints = []; validHints = [];
for (let j = 0; j < docs.length; j++) for (let [,{ doc: doc, start: start, end: end }] in Iterator(docs))
{ {
var doc = docs[j].doc; let scrollX = doc.defaultView.scrollX;
var start = docs[j].start; let scrollY = doc.defaultView.scrollY;
var end = docs[j].end;
var scrollX = doc.defaultView.scrollX;
var scrollY = doc.defaultView.scrollY;
inner: inner:
for (let i in (util.interruptableRange(start, end + 1, 500))) for (let i in (util.interruptableRange(start, end + 1, 500)))
@@ -208,8 +209,8 @@ function Hints() //{{{
imgspan.style.display = "none"; imgspan.style.display = "none";
// reset background color // reset background color
elem.style.backgroundColor = hint[4]; elem.style.backgroundColor = hint[BGCOLOR];
elem.style.color = hint[5]; elem.style.color = hint[COLOR];
continue inner; continue inner;
} }
@@ -230,7 +231,7 @@ function Hints() //{{{
imgspan.style.width = (rect.right - rect.left) + "px"; imgspan.style.width = (rect.right - rect.left) + "px";
imgspan.style.height = (rect.bottom - rect.top) + "px"; imgspan.style.height = (rect.bottom - rect.top) + "px";
imgspan.className = "liberator-hint"; imgspan.className = "liberator-hint";
hint[3] = imgspan; hint[IMGSPAN] = imgspan;
doc.body.appendChild(imgspan); doc.body.appendChild(imgspan);
} }
imgspan.style.backgroundColor = (activeHint == hintnum) ? activelinkbgcolor : linkbgcolor; imgspan.style.backgroundColor = (activeHint == hintnum) ? activelinkbgcolor : linkbgcolor;
@@ -240,7 +241,7 @@ function Hints() //{{{
if (!imgspan) if (!imgspan)
elem.style.backgroundColor = (activeHint == hintnum) ? activelinkbgcolor : linkbgcolor; elem.style.backgroundColor = (activeHint == hintnum) ? activelinkbgcolor : linkbgcolor;
elem.style.color = (activeHint == hintnum) ? activelinkfgcolor : linkfgcolor; elem.style.color = (activeHint == hintnum) ? activelinkfgcolor : linkfgcolor;
span.textContent = "" + (hintnum++); span.textContent = String(hintnum++);
span.style.display = "inline"; span.style.display = "inline";
validHints.push(elem); validHints.push(elem);
} }
@@ -255,32 +256,27 @@ function Hints() //{{{
var firstElemBgColor = ""; var firstElemBgColor = "";
var firstElemColor = ""; var firstElemColor = "";
for (let j = 0; j < docs.length; j++) for (let [,{ doc: doc, start: start, end: end }] in Iterator(docs))
{ {
var doc = docs[j].doc; for (let i in util.range(start, end + 1))
var start = docs[j].start;
var end = docs[j].end;
for (let i = start; i <= end; i++)
{ {
let hint = pageHints[i]; let hint = pageHints[i];
// remove the span for the numeric display part // remove the span for the numeric display part
doc.body.removeChild(hint[2]); doc.body.removeChild(hint[SPAN]);
if (hint[3]) // a transparent span for images if (hint[IMGSPAN]) // a transparent span for images
doc.body.removeChild(hint[3]); doc.body.removeChild(hint[IMGSPAN]);
if (timeout && firstElem == hint[0]) if (timeout && firstElem == hint[ELEM])
{ {
firstElemBgColor = hint[4]; firstElemBgColor = hint[BGCOLOR];
firstElemColor = hint[5]; firstElemColor = hint[COLOR];
} }
else else
{ {
// restore colors // restore colors
var elem = hint[0]; var elem = hint[ELEM];
elem.style.backgroundColor = hint[4]; elem.style.backgroundColor = hint[BGCOLOR];
elem.style.color = hint[5]; elem.style.color = hint[COLOR]; }
}
} }
// animate the disappearance of the first hint // animate the disappearance of the first hint
@@ -381,19 +377,7 @@ function Hints() //{{{
function containsMatcher(hintString) //{{{ function containsMatcher(hintString) //{{{
{ {
var tokens = hintString.split(/ +/); var tokens = hintString.split(/ +/);
return function (linkText) tokens.every(function (token) linkText.indexOf(token) >= 0);
function contains(textOfLink)
{
for (let i = 0; i < tokens.length; i++)
{
if (textOfLink.indexOf(tokens[i]) < 0)
return false;
}
return true;
}
return contains;
} //}}} } //}}}
function wordStartsWithMatcher(hintString, allowWordOverleaping) //{{{ function wordStartsWithMatcher(hintString, allowWordOverleaping) //{{{
@@ -401,23 +385,23 @@ function Hints() //{{{
var hintStrings = hintString.split(/ +/); var hintStrings = hintString.split(/ +/);
var wordSplitRegex = new RegExp(options["wordseparators"]); var wordSplitRegex = new RegExp(options["wordseparators"]);
// What the **** does this do? --Kris
function charsAtBeginningOfWords(chars, words, allowWordOverleaping) function charsAtBeginningOfWords(chars, words, allowWordOverleaping)
{ {
var charIdx = 0; var charIdx = 0;
var numMatchedWords = 0; var numMatchedWords = 0;
for (let wIdx = 0; wIdx < words.length; wIdx++) for (let [,word] in Iterator(words))
{ {
var word = words[wIdx];
if (word.length == 0) if (word.length == 0)
continue; continue;
var wcIdx = 0; let wcIdx = 0;
// Check if the current word matches same characters as the previous word. // Check if the current word matches same characters as the previous word.
// Each already matched word has matched at least one character. // Each already matched word has matched at least one character.
if (charIdx > numMatchedWords) if (charIdx > numMatchedWords)
{ {
var matchingStarted = false; let matchingStarted = false;
for (let i = numMatchedWords; i < charIdx; i++) for (let i in util.range(numMatchedWords, charIdx))
{ {
if (chars[i] == word[wcIdx]) if (chars[i] == word[wcIdx])
{ {
@@ -433,9 +417,10 @@ function Hints() //{{{
} }
// the current word matches same characters as the previous word // the current word matches same characters as the previous word
var prevCharIdx;
if (wcIdx > 0) if (wcIdx > 0)
{ {
var prevCharIdx = charIdx; prevCharIdx = charIdx;
// now check if it matches additional characters // now check if it matches additional characters
for (; wcIdx < word.length && charIdx < chars.length; wcIdx++, charIdx++) for (; wcIdx < word.length && charIdx < chars.length; wcIdx++, charIdx++)
{ {
@@ -461,7 +446,7 @@ function Hints() //{{{
// try to match the next characters // try to match the next characters
else else
{ {
var prevCharIdx = charIdx; prevCharIdx = charIdx;
for (let i = 0; i < word.length && charIdx < chars.length; i++, charIdx++) for (let i = 0; i < word.length && charIdx < chars.length; i++, charIdx++)
{ {
if (word[i] != chars[charIdx]) if (word[i] != chars[charIdx])
@@ -487,16 +472,13 @@ function Hints() //{{{
function stringsAtBeginningOfWords(strings, words, allowWordOverleaping) function stringsAtBeginningOfWords(strings, words, allowWordOverleaping)
{ {
var strIdx = 0; var strIdx = 0;
for (let wIdx = 0; wIdx < words.length; wIdx++) for (let [,word] in Iterator(words))
{ {
var word = words[wIdx];
if (word.length == 0) if (word.length == 0)
continue; continue;
var str = strings[strIdx]; let str = strings[strIdx];
if (str.length == 0) if (str.length == 0 || word.indexOf(str) == 0)
strIdx++;
else if (word.indexOf(str) == 0)
strIdx++; strIdx++;
else if (!allowWordOverleaping) else if (!allowWordOverleaping)
return false; return false;
@@ -510,16 +492,15 @@ function Hints() //{{{
if (strings[strIdx].length != 0) if (strings[strIdx].length != 0)
return false; return false;
} }
return true;
return (strIdx == strings.length);
} }
function wordStartsWith(textOfLink) function wordStartsWith(linkText)
{ {
if (hintStrings.length == 1 && hintStrings[0].length == 0) if (hintStrings.length == 1 && hintStrings[0].length == 0)
return true; return true;
var words = textOfLink.split(wordSplitRegex); let words = linkText.split(wordSplitRegex);
if (hintStrings.length == 1) if (hintStrings.length == 1)
return charsAtBeginningOfWords(hintStrings[0], words, allowWordOverleaping); return charsAtBeginningOfWords(hintStrings[0], words, allowWordOverleaping);
else else
@@ -592,7 +573,7 @@ function Hints() //{{{
options.add(["wordseparators", "wsp"], options.add(["wordseparators", "wsp"],
"How words are split for hintmatching", "How words are split for hintmatching",
"string", '[\\.,!\\?:;/\\\"\\^\\$%&?\\(\\)\\[\\]\\{\\}<>#\\*\\+\\|=~ _\\-]'); "string", '[.,!?:;/"^$%&?()[\\]{}<>#*+|=~ _-]');
/////////////////////////////////////////////////////////////////////////////}}} /////////////////////////////////////////////////////////////////////////////}}}
////////////////////// MAPPINGS //////////////////////////////////////////////// ////////////////////// MAPPINGS ////////////////////////////////////////////////
@@ -617,6 +598,11 @@ function Hints() //{{{
return { return {
addMode: function (mode)
{
hintModes[mode] = Mode.apply(Mode, Array.slice(arguments, 1));
},
show: function (minor, filter, win) show: function (minor, filter, win)
{ {
hintMode = hintModes[minor]; hintMode = hintModes[minor];