mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2026-03-05 21:25:47 +01:00
Resurrect my range finder, Part IV: Links only, match case, and all that stuff no one uses.
This commit is contained in:
@@ -464,8 +464,7 @@ const RangeFinder = Module("rangefinder", {
|
|||||||
requires: ["config"],
|
requires: ["config"],
|
||||||
|
|
||||||
init: function () {
|
init: function () {
|
||||||
this.lastSearchString = "";
|
this.lastSearchPattern = "";
|
||||||
this.lastSearchBackwards = false;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
openPrompt: function (mode) {
|
openPrompt: function (mode) {
|
||||||
@@ -475,23 +474,48 @@ const RangeFinder = Module("rangefinder", {
|
|||||||
this.find("", backwards);
|
this.find("", backwards);
|
||||||
},
|
},
|
||||||
|
|
||||||
find: function (str, backwards) {
|
bootstrap: function (str, backward) {
|
||||||
let caseSensitive = false;
|
let highlighted = this.rangeFind && this.rangeFind.highlighted;
|
||||||
let highlighted = this.rangeFind && this.rangeFind.highlighted; // Kludge?
|
let matchCase = !(options["ignorecase"] || options["smartcase"] && !/[A-Z]/.test(str));
|
||||||
this.rangeFind = RangeFind(caseSensitive, backwards);
|
let linksOnly = options["linksearch"];
|
||||||
this.rangeFind.highlighted = highlighted;
|
|
||||||
|
|
||||||
|
// All this ado is ludicrous.
|
||||||
|
str = str.replace(/\\(.|$)/g, function (m, n1) {
|
||||||
|
if (n1 == "l")
|
||||||
|
linksOnly = true;
|
||||||
|
else if (n1 == "L")
|
||||||
|
linksOnly = false;
|
||||||
|
else if (n1 == "c")
|
||||||
|
matchCase = false;
|
||||||
|
else if (n1 == "C")
|
||||||
|
matchCase = true;
|
||||||
|
else
|
||||||
|
return n1;
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
if (!this.rangeFind || linksOnly ^ !!this.rangeFind.elementPath ||
|
||||||
|
matchCase ^ this.rangeFind.matchCase || backward ^ this.rangeFind.reverse) {
|
||||||
|
if (this.rangeFind)
|
||||||
|
this.rangeFind.cancel();
|
||||||
|
this.rangeFind = RangeFind(matchCase, backward, linksOnly && options["hinttags"]);
|
||||||
|
this.rangeFind.highlighted = highlighted;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
},
|
||||||
|
|
||||||
|
find: function (pattern, backwards) {
|
||||||
|
let str = this.bootstrap(pattern);
|
||||||
if (!this.rangeFind.search(str))
|
if (!this.rangeFind.search(str))
|
||||||
setTimeout(function () { liberator.echoerr("E486: Pattern not found: " + str); }, 0);
|
setTimeout(function () { liberator.echoerr("E486: Pattern not found: " + pattern); }, 0);
|
||||||
|
|
||||||
return this.rangeFind.found;
|
return this.rangeFind.found;
|
||||||
},
|
},
|
||||||
|
|
||||||
findAgain: function (reverse) {
|
findAgain: function (reverse) {
|
||||||
if (!this.rangeFind)
|
if (!this.rangeFind)
|
||||||
this.find(this.lastSearchString);
|
this.find(this.lastSearchPattern);
|
||||||
else if (!this.rangeFind.search(null, reverse))
|
else if (!this.rangeFind.search(null, reverse))
|
||||||
liberator.echoerr("E486: Pattern not found: " + this.lastSearchString);
|
liberator.echoerr("E486: Pattern not found: " + this.lastSearchPattern);
|
||||||
else if (this.rangeFind.wrapped) {
|
else if (this.rangeFind.wrapped) {
|
||||||
// hack needed, because wrapping causes a "scroll" event which clears
|
// hack needed, because wrapping causes a "scroll" event which clears
|
||||||
// our command line
|
// our command line
|
||||||
@@ -502,7 +526,7 @@ const RangeFinder = Module("rangefinder", {
|
|||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
commandline.echo((this.rangeFind.backward ? "?" : "/") + this.lastSearchString, null, commandline.FORCE_SINGLELINE);
|
commandline.echo((this.rangeFind.backward ? "?" : "/") + this.lastSearchPattern, null, commandline.FORCE_SINGLELINE);
|
||||||
|
|
||||||
if (options["hlsearch"])
|
if (options["hlsearch"])
|
||||||
this.highlight();
|
this.highlight();
|
||||||
@@ -510,18 +534,19 @@ const RangeFinder = Module("rangefinder", {
|
|||||||
|
|
||||||
// Called when the user types a key in the search dialog. Triggers a find attempt if 'incsearch' is set
|
// Called when the user types a key in the search dialog. Triggers a find attempt if 'incsearch' is set
|
||||||
onKeyPress: function (command) {
|
onKeyPress: function (command) {
|
||||||
if (options["incsearch"] && this.rangeFind)
|
if (options["incsearch"]) {
|
||||||
|
command = this.bootstrap(command);
|
||||||
this.rangeFind.search(command);
|
this.rangeFind.search(command);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onSubmit: function (command) {
|
onSubmit: function (command) {
|
||||||
if (!options["incsearch"] || !this.rangeFind || !this.rangeFind.found) {
|
if (!options["incsearch"] || !this.rangeFind || !this.rangeFind.found) {
|
||||||
this.clear();
|
this.clear();
|
||||||
this.find(command || this.lastSearchString, this.lastSearchBackwards);
|
this.find(command || this.lastSearchPattern, modes.extended & modes.FIND_BACKWARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.lastSearchBackwards = this.rangeFind.backwards;
|
this.lastSearchPattern = command;
|
||||||
this.lastSearchString = this.rangeFind.searchString;
|
|
||||||
|
|
||||||
if (options["hlsearch"])
|
if (options["hlsearch"])
|
||||||
this.highlight();
|
this.highlight();
|
||||||
@@ -614,9 +639,10 @@ const RangeFinder = Module("rangefinder", {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const RangeFind = Class("RangeFind", {
|
const RangeFind = Class("RangeFind", {
|
||||||
init: function (matchCase, backward) {
|
init: function (matchCase, backward, elementPath) {
|
||||||
|
this.elementPath = elementPath || null;
|
||||||
this.matchCase = Boolean(matchCase);
|
this.matchCase = Boolean(matchCase);
|
||||||
this._backward = Boolean(backward);
|
this.reverse = Boolean(backward);
|
||||||
this.finder = services.create("find");
|
this.finder = services.create("find");
|
||||||
this.finder.caseSensitive = this.matchCase;
|
this.finder.caseSensitive = this.matchCase;
|
||||||
|
|
||||||
@@ -654,18 +680,39 @@ const RangeFind = Class("RangeFind", {
|
|||||||
return ranges[0];
|
return ranges[0];
|
||||||
},
|
},
|
||||||
|
|
||||||
|
findSubRanges: function (range) {
|
||||||
|
let doc = range.startContainer.ownerDocument;
|
||||||
|
for (let elem in util.evaluateXPath(this.elementPath, doc)) {
|
||||||
|
let r = doc.createRange();
|
||||||
|
r.selectNode(elem);
|
||||||
|
if (range.compareBoundaryPoints(Range.START_TO_END, r) >= 0 &&
|
||||||
|
range.compareBoundaryPoints(Range.END_TO_START, r) <= 0)
|
||||||
|
yield r;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
makeFrameList: function (win) {
|
makeFrameList: function (win) {
|
||||||
|
const self = this;
|
||||||
win = win.top;
|
win = win.top;
|
||||||
let frames = [];
|
let frames = [];
|
||||||
|
let backup = null;
|
||||||
|
|
||||||
function pushRange(start, end) {
|
function pushRange(start, end) {
|
||||||
frames.push(RangeFind.Range(start, end, frames.length));
|
let range = start.startContainer.ownerDocument.createRange();
|
||||||
|
range.setStart(start.startContainer, start.startOffset);
|
||||||
|
range.setEnd(end.startContainer, end.startOffset);
|
||||||
|
|
||||||
|
if (!self.elementPath)
|
||||||
|
frames.push(RangeFind.Range(range, frames.length));
|
||||||
|
else
|
||||||
|
for (let r in self.findSubRanges(range))
|
||||||
|
frames.push(RangeFind.Range(r, frames.length));
|
||||||
}
|
}
|
||||||
function rec(win) {
|
function rec(win) {
|
||||||
let doc = win.document;
|
let doc = win.document;
|
||||||
let pageRange = doc.createRange();
|
let pageRange = doc.createRange();
|
||||||
pageRange.setStartBefore(doc.body || doc.documentElement.lastChild);
|
pageRange.selectNode(doc.body || doc.documentElement.lastChild);
|
||||||
pageRange.setEndAfter(doc.body || doc.documentElement.lastChild);
|
backup = backup || pageRange;
|
||||||
let pageStart = RangeFind.endpoint(pageRange, true);
|
let pageStart = RangeFind.endpoint(pageRange, true);
|
||||||
let pageEnd = RangeFind.endpoint(pageRange, false);
|
let pageEnd = RangeFind.endpoint(pageRange, false);
|
||||||
|
|
||||||
@@ -679,6 +726,8 @@ const RangeFind = Class("RangeFind", {
|
|||||||
pushRange(pageStart, pageEnd);
|
pushRange(pageStart, pageEnd);
|
||||||
}
|
}
|
||||||
rec(win);
|
rec(win);
|
||||||
|
if (frames.length == 0)
|
||||||
|
frames[0] = RangeFind.Range(RangeFind.endpoint(backup, true), 0);
|
||||||
return frames;
|
return frames;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -726,7 +775,7 @@ const RangeFind = Class("RangeFind", {
|
|||||||
this.lastRange = null;
|
this.lastRange = null;
|
||||||
this.lastString = word
|
this.lastString = word
|
||||||
var res;
|
var res;
|
||||||
while (res = this.search(null, this._backward, true))
|
while (res = this.search(null, this.reverse, true))
|
||||||
yield res;
|
yield res;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
@@ -736,7 +785,7 @@ const RangeFind = Class("RangeFind", {
|
|||||||
|
|
||||||
search: function (word, reverse, private) {
|
search: function (word, reverse, private) {
|
||||||
this.wrapped = false;
|
this.wrapped = false;
|
||||||
this.finder.findBackwards = reverse ? !this._backward : this._backward;
|
this.finder.findBackwards = reverse ? !this.reverse : this.reverse;
|
||||||
let again = word == null;
|
let again = word == null;
|
||||||
if (again)
|
if (again)
|
||||||
word = this.lastString;
|
word = this.lastString;
|
||||||
@@ -769,7 +818,7 @@ const RangeFind = Class("RangeFind", {
|
|||||||
for (let i in indices.call(this)) {
|
for (let i in indices.call(this)) {
|
||||||
this.range = this.ranges[i];
|
this.range = this.ranges[i];
|
||||||
|
|
||||||
let start = this.sameDocument(this.lastRange, this.range.range) ?
|
let start = this.sameDocument(this.lastRange, this.range.range) && this.range.intersects(this.lastRange) ?
|
||||||
RangeFind.endpoint(this.lastRange, !(again ^ this.backward)) :
|
RangeFind.endpoint(this.lastRange, !(again ^ this.backward)) :
|
||||||
RangeFind.endpoint(this.range.range, !this.backward);;
|
RangeFind.endpoint(this.range.range, !this.backward);;
|
||||||
if (this.backward && !again)
|
if (this.backward && !again)
|
||||||
@@ -863,24 +912,25 @@ const RangeFind = Class("RangeFind", {
|
|||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
Range: Class("RangeFind.Range", {
|
Range: Class("RangeFind.Range", {
|
||||||
init: function (start, end, index) {
|
init: function (range, index) {
|
||||||
if (start instanceof Ci.nsIDOMWindow) { // Kludge
|
if (range instanceof Ci.nsIDOMWindow) { // Kludge
|
||||||
this.document = start.document;
|
this.document = range.document;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.index = index;
|
this.index = index;
|
||||||
|
|
||||||
this.document = start.startContainer.ownerDocument;
|
this.document = range.startContainer.ownerDocument;
|
||||||
this.window = this.document.defaultView;
|
this.window = this.document.defaultView;
|
||||||
|
this.range = range;
|
||||||
this.range = this.document.createRange();
|
|
||||||
this.range.setStart(start.startContainer, start.startOffset);
|
|
||||||
this.range.setEnd(end.startContainer, end.startOffset);
|
|
||||||
|
|
||||||
this.save();
|
this.save();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
intersects: function (range)
|
||||||
|
this.range.compareBoundaryPoints(Range.START_TO_END, range) >= 0 &&
|
||||||
|
this.range.compareBoundaryPoints(Range.END_TO_START, range) <= 0,
|
||||||
|
|
||||||
save: function () {
|
save: function () {
|
||||||
this.scroll = Point(this.window.pageXOffset, this.window.pageYOffset);
|
this.scroll = Point(this.window.pageXOffset, this.window.pageYOffset);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user