PluginProbe
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor / 2.0.2
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor v2.0.2
4.0.2 4.0.1 4.0.0 3.16.6 3.16.5 3.16.4 3.16.3 3.16.2 3.16.1 3.16.0 3.15.9 3.9.9 3.9.5 3.9.6 3.9.7 3.9.8 1.1.7 1.1.8 1.1.9 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 All 340 releases
profile-builder / assets / lib / codemirror / addon / search / searchcursor.js

searchcursor.js in User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor 2.0.2, at assets/lib/codemirror/addon/search/searchcursor.js

144 lines 5.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function(){
2 var Pos = CodeMirror.Pos;
3
4 function SearchCursor(doc, query, pos, caseFold) {
5 this.atOccurrence = false; this.doc = doc;
6 if (caseFold == null && typeof query == "string") caseFold = false;
7
8 pos = pos ? doc.clipPos(pos) : Pos(0, 0);
9 this.pos = {from: pos, to: pos};
10
11 // The matches method is filled in based on the type of query.
12 // It takes a position and a direction, and returns an object
13 // describing the next occurrence of the query, or null if no
14 // more matches were found.
15 if (typeof query != "string") { // Regexp match
16 if (!query.global) query = new RegExp(query.source, query.ignoreCase ? "ig" : "g");
17 this.matches = function(reverse, pos) {
18 if (reverse) {
19 query.lastIndex = 0;
20 var line = doc.getLine(pos.line).slice(0, pos.ch), cutOff = 0, match, start;
21 for (;;) {
22 query.lastIndex = cutOff;
23 var newMatch = query.exec(line);
24 if (!newMatch) break;
25 match = newMatch;
26 start = match.index;
27 cutOff = match.index + (match[0].length || 1);
28 if (cutOff == line.length) break;
29 }
30 var matchLen = (match && match[0].length) || 0;
31 if (!matchLen) {
32 if (start == 0 && line.length == 0) {match = undefined;}
33 else if (start != doc.getLine(pos.line).length) {
34 matchLen++;
35 }
36 }
37 } else {
38 query.lastIndex = pos.ch;
39 var line = doc.getLine(pos.line), match = query.exec(line);
40 var matchLen = (match && match[0].length) || 0;
41 var start = match && match.index;
42 if (start + matchLen != line.length && !matchLen) matchLen = 1;
43 }
44 if (match && matchLen)
45 return {from: Pos(pos.line, start),
46 to: Pos(pos.line, start + matchLen),
47 match: match};
48 };
49 } else { // String query
50 if (caseFold) query = query.toLowerCase();
51 var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;};
52 var target = query.split("\n");
53 // Different methods for single-line and multi-line queries
54 if (target.length == 1) {
55 if (!query.length) {
56 // Empty string would match anything and never progress, so
57 // we define it to match nothing instead.
58 this.matches = function() {};
59 } else {
60 this.matches = function(reverse, pos) {
61 var line = fold(doc.getLine(pos.line)), len = query.length, match;
62 if (reverse ? (pos.ch >= len && (match = line.lastIndexOf(query, pos.ch - len)) != -1)
63 : (match = line.indexOf(query, pos.ch)) != -1)
64 return {from: Pos(pos.line, match),
65 to: Pos(pos.line, match + len)};
66 };
67 }
68 } else {
69 this.matches = function(reverse, pos) {
70 var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(doc.getLine(ln));
71 var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match));
72 if (reverse ? offsetA > pos.ch || offsetA != match.length
73 : offsetA < pos.ch || offsetA != line.length - match.length)
74 return;
75 for (;;) {
76 if (reverse ? !ln : ln == doc.lineCount() - 1) return;
77 line = fold(doc.getLine(ln += reverse ? -1 : 1));
78 match = target[reverse ? --idx : ++idx];
79 if (idx > 0 && idx < target.length - 1) {
80 if (line != match) return;
81 else continue;
82 }
83 var offsetB = (reverse ? line.lastIndexOf(match) : line.indexOf(match) + match.length);
84 if (reverse ? offsetB != line.length - match.length : offsetB != match.length)
85 return;
86 var start = Pos(pos.line, offsetA), end = Pos(ln, offsetB);
87 return {from: reverse ? end : start, to: reverse ? start : end};
88 }
89 };
90 }
91 }
92 }
93
94 SearchCursor.prototype = {
95 findNext: function() {return this.find(false);},
96 findPrevious: function() {return this.find(true);},
97
98 find: function(reverse) {
99 var self = this, pos = this.doc.clipPos(reverse ? this.pos.from : this.pos.to);
100 function savePosAndFail(line) {
101 var pos = Pos(line, 0);
102 self.pos = {from: pos, to: pos};
103 self.atOccurrence = false;
104 return false;
105 }
106
107 for (;;) {
108 if (this.pos = this.matches(reverse, pos)) {
109 if (!this.pos.from || !this.pos.to) { console.log(this.matches, this.pos); }
110 this.atOccurrence = true;
111 return this.pos.match || true;
112 }
113 if (reverse) {
114 if (!pos.line) return savePosAndFail(0);
115 pos = Pos(pos.line-1, this.doc.getLine(pos.line-1).length);
116 }
117 else {
118 var maxLine = this.doc.lineCount();
119 if (pos.line == maxLine - 1) return savePosAndFail(maxLine);
120 pos = Pos(pos.line + 1, 0);
121 }
122 }
123 },
124
125 from: function() {if (this.atOccurrence) return this.pos.from;},
126 to: function() {if (this.atOccurrence) return this.pos.to;},
127
128 replace: function(newText) {
129 if (!this.atOccurrence) return;
130 var lines = CodeMirror.splitLines(newText);
131 this.doc.replaceRange(lines, this.pos.from, this.pos.to);
132 this.pos.to = Pos(this.pos.from.line + lines.length - 1,
133 lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0));
134 }
135 };
136
137 CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
138 return new SearchCursor(this.doc, query, pos, caseFold);
139 });
140 CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) {
141 return new SearchCursor(this, query, pos, caseFold);
142 });
143 })();
144