PluginProbe
Smart Grid-Layout Design for Contact Form 7 / 4.1.2
Smart Grid-Layout Design for Contact Form 7 v4.1.2
4.18.0 4.17.0 3.2.0 3.2.1 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 4.0.0 4.0.1 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.10 4.11 4.12 4.13 4.14 All 119 releases
cf7-grid-layout / assets / codemirror / addon / search / searchcursor.js

searchcursor.js in Smart Grid-Layout Design for Contact Form 7 4.1.2, at assets/codemirror/addon/search/searchcursor.js

290 lines 11.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 // Distributed under an MIT license: http://codemirror.net/LICENSE
3
4 (function(mod) {
5 if (typeof exports == "object" && typeof module == "object") // CommonJS
6 mod(require("../../lib/codemirror"))
7 else if (typeof define == "function" && define.amd) // AMD
8 define(["../../lib/codemirror"], mod)
9 else // Plain browser env
10 mod(CodeMirror)
11 })(function(CodeMirror) {
12 "use strict"
13 var Pos = CodeMirror.Pos
14
15 function regexpFlags(regexp) {
16 var flags = regexp.flags
17 return flags != null ? flags : (regexp.ignoreCase ? "i" : "")
18 + (regexp.global ? "g" : "")
19 + (regexp.multiline ? "m" : "")
20 }
21
22 function ensureGlobal(regexp) {
23 return regexp.global ? regexp : new RegExp(regexp.source, regexpFlags(regexp) + "g")
24 }
25
26 function maybeMultiline(regexp) {
27 return /\\s|\\n|\n|\\W|\\D|\[\^/.test(regexp.source)
28 }
29
30 function searchRegexpForward(doc, regexp, start) {
31 regexp = ensureGlobal(regexp)
32 for (var line = start.line, ch = start.ch, last = doc.lastLine(); line <= last; line++, ch = 0) {
33 regexp.lastIndex = ch
34 var string = doc.getLine(line), match = regexp.exec(string)
35 if (match)
36 return {from: Pos(line, match.index),
37 to: Pos(line, match.index + match[0].length),
38 match: match}
39 }
40 }
41
42 function searchRegexpForwardMultiline(doc, regexp, start) {
43 if (!maybeMultiline(regexp)) return searchRegexpForward(doc, regexp, start)
44
45 regexp = ensureGlobal(regexp)
46 var string, chunk = 1
47 for (var line = start.line, last = doc.lastLine(); line <= last;) {
48 // This grows the search buffer in exponentially-sized chunks
49 // between matches, so that nearby matches are fast and don't
50 // require concatenating the whole document (in case we're
51 // searching for something that has tons of matches), but at the
52 // same time, the amount of retries is limited.
53 for (var i = 0; i < chunk; i++) {
54 var curLine = doc.getLine(line++)
55 string = string == null ? curLine : string + "\n" + curLine
56 }
57 chunk = chunk * 2
58 regexp.lastIndex = start.ch
59 var match = regexp.exec(string)
60 if (match) {
61 var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n")
62 var startLine = start.line + before.length - 1, startCh = before[before.length - 1].length
63 return {from: Pos(startLine, startCh),
64 to: Pos(startLine + inside.length - 1,
65 inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length),
66 match: match}
67 }
68 }
69 }
70
71 function lastMatchIn(string, regexp) {
72 var cutOff = 0, match
73 for (;;) {
74 regexp.lastIndex = cutOff
75 var newMatch = regexp.exec(string)
76 if (!newMatch) return match
77 match = newMatch
78 cutOff = match.index + (match[0].length || 1)
79 if (cutOff == string.length) return match
80 }
81 }
82
83 function searchRegexpBackward(doc, regexp, start) {
84 regexp = ensureGlobal(regexp)
85 for (var line = start.line, ch = start.ch, first = doc.firstLine(); line >= first; line--, ch = -1) {
86 var string = doc.getLine(line)
87 if (ch > -1) string = string.slice(0, ch)
88 var match = lastMatchIn(string, regexp)
89 if (match)
90 return {from: Pos(line, match.index),
91 to: Pos(line, match.index + match[0].length),
92 match: match}
93 }
94 }
95
96 function searchRegexpBackwardMultiline(doc, regexp, start) {
97 regexp = ensureGlobal(regexp)
98 var string, chunk = 1
99 for (var line = start.line, first = doc.firstLine(); line >= first;) {
100 for (var i = 0; i < chunk; i++) {
101 var curLine = doc.getLine(line--)
102 string = string == null ? curLine.slice(0, start.ch) : curLine + "\n" + string
103 }
104 chunk *= 2
105
106 var match = lastMatchIn(string, regexp)
107 if (match) {
108 var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n")
109 var startLine = line + before.length, startCh = before[before.length - 1].length
110 return {from: Pos(startLine, startCh),
111 to: Pos(startLine + inside.length - 1,
112 inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length),
113 match: match}
114 }
115 }
116 }
117
118 var doFold, noFold
119 if (String.prototype.normalize) {
120 doFold = function(str) { return str.normalize("NFD").toLowerCase() }
121 noFold = function(str) { return str.normalize("NFD") }
122 } else {
123 doFold = function(str) { return str.toLowerCase() }
124 noFold = function(str) { return str }
125 }
126
127 // Maps a position in a case-folded line back to a position in the original line
128 // (compensating for codepoints increasing in number during folding)
129 function adjustPos(orig, folded, pos, foldFunc) {
130 if (orig.length == folded.length) return pos
131 for (var min = 0, max = pos + Math.max(0, orig.length - folded.length);;) {
132 if (min == max) return min
133 var mid = (min + max) >> 1
134 var len = foldFunc(orig.slice(0, mid)).length
135 if (len == pos) return mid
136 else if (len > pos) max = mid
137 else min = mid + 1
138 }
139 }
140
141 function searchStringForward(doc, query, start, caseFold) {
142 // Empty string would match anything and never progress, so we
143 // define it to match nothing instead.
144 if (!query.length) return null
145 var fold = caseFold ? doFold : noFold
146 var lines = fold(query).split(/\r|\n\r?/)
147
148 search: for (var line = start.line, ch = start.ch, last = doc.lastLine() + 1 - lines.length; line <= last; line++, ch = 0) {
149 var orig = doc.getLine(line).slice(ch), string = fold(orig)
150 if (lines.length == 1) {
151 var found = string.indexOf(lines[0])
152 if (found == -1) continue search
153 var start = adjustPos(orig, string, found, fold) + ch
154 return {from: Pos(line, adjustPos(orig, string, found, fold) + ch),
155 to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold) + ch)}
156 } else {
157 var cutFrom = string.length - lines[0].length
158 if (string.slice(cutFrom) != lines[0]) continue search
159 for (var i = 1; i < lines.length - 1; i++)
160 if (fold(doc.getLine(line + i)) != lines[i]) continue search
161 var end = doc.getLine(line + lines.length - 1), endString = fold(end), lastLine = lines[lines.length - 1]
162 if (endString.slice(0, lastLine.length) != lastLine) continue search
163 return {from: Pos(line, adjustPos(orig, string, cutFrom, fold) + ch),
164 to: Pos(line + lines.length - 1, adjustPos(end, endString, lastLine.length, fold))}
165 }
166 }
167 }
168
169 function searchStringBackward(doc, query, start, caseFold) {
170 if (!query.length) return null
171 var fold = caseFold ? doFold : noFold
172 var lines = fold(query).split(/\r|\n\r?/)
173
174 search: for (var line = start.line, ch = start.ch, first = doc.firstLine() - 1 + lines.length; line >= first; line--, ch = -1) {
175 var orig = doc.getLine(line)
176 if (ch > -1) orig = orig.slice(0, ch)
177 var string = fold(orig)
178 if (lines.length == 1) {
179 var found = string.lastIndexOf(lines[0])
180 if (found == -1) continue search
181 return {from: Pos(line, adjustPos(orig, string, found, fold)),
182 to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold))}
183 } else {
184 var lastLine = lines[lines.length - 1]
185 if (string.slice(0, lastLine.length) != lastLine) continue search
186 for (var i = 1, start = line - lines.length + 1; i < lines.length - 1; i++)
187 if (fold(doc.getLine(start + i)) != lines[i]) continue search
188 var top = doc.getLine(line + 1 - lines.length), topString = fold(top)
189 if (topString.slice(topString.length - lines[0].length) != lines[0]) continue search
190 return {from: Pos(line + 1 - lines.length, adjustPos(top, topString, top.length - lines[0].length, fold)),
191 to: Pos(line, adjustPos(orig, string, lastLine.length, fold))}
192 }
193 }
194 }
195
196 function SearchCursor(doc, query, pos, options) {
197 this.atOccurrence = false
198 this.doc = doc
199 pos = pos ? doc.clipPos(pos) : Pos(0, 0)
200 this.pos = {from: pos, to: pos}
201
202 var caseFold
203 if (typeof options == "object") {
204 caseFold = options.caseFold
205 } else { // Backwards compat for when caseFold was the 4th argument
206 caseFold = options
207 options = null
208 }
209
210 if (typeof query == "string") {
211 if (caseFold == null) caseFold = false
212 this.matches = function(reverse, pos) {
213 return (reverse ? searchStringBackward : searchStringForward)(doc, query, pos, caseFold)
214 }
215 } else {
216 query = ensureGlobal(query)
217 if (!options || options.multiline !== false)
218 this.matches = function(reverse, pos) {
219 return (reverse ? searchRegexpBackwardMultiline : searchRegexpForwardMultiline)(doc, query, pos)
220 }
221 else
222 this.matches = function(reverse, pos) {
223 return (reverse ? searchRegexpBackward : searchRegexpForward)(doc, query, pos)
224 }
225 }
226 }
227
228 SearchCursor.prototype = {
229 findNext: function() {return this.find(false)},
230 findPrevious: function() {return this.find(true)},
231
232 find: function(reverse) {
233 var result = this.matches(reverse, this.doc.clipPos(reverse ? this.pos.from : this.pos.to))
234
235 // Implements weird auto-growing behavior on null-matches for
236 // backwards-compatiblity with the vim code (unfortunately)
237 while (result && CodeMirror.cmpPos(result.from, result.to) == 0) {
238 if (reverse) {
239 if (result.from.ch) result.from = Pos(result.from.line, result.from.ch - 1)
240 else if (result.from.line == this.doc.firstLine()) result = null
241 else result = this.matches(reverse, this.doc.clipPos(Pos(result.from.line - 1)))
242 } else {
243 if (result.to.ch < this.doc.getLine(result.to.line).length) result.to = Pos(result.to.line, result.to.ch + 1)
244 else if (result.to.line == this.doc.lastLine()) result = null
245 else result = this.matches(reverse, Pos(result.to.line + 1, 0))
246 }
247 }
248
249 if (result) {
250 this.pos = result
251 this.atOccurrence = true
252 return this.pos.match || true
253 } else {
254 var end = Pos(reverse ? this.doc.firstLine() : this.doc.lastLine() + 1, 0)
255 this.pos = {from: end, to: end}
256 return this.atOccurrence = false
257 }
258 },
259
260 from: function() {if (this.atOccurrence) return this.pos.from},
261 to: function() {if (this.atOccurrence) return this.pos.to},
262
263 replace: function(newText, origin) {
264 if (!this.atOccurrence) return
265 var lines = CodeMirror.splitLines(newText)
266 this.doc.replaceRange(lines, this.pos.from, this.pos.to, origin)
267 this.pos.to = Pos(this.pos.from.line + lines.length - 1,
268 lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0))
269 }
270 }
271
272 CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
273 return new SearchCursor(this.doc, query, pos, caseFold)
274 })
275 CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) {
276 return new SearchCursor(this, query, pos, caseFold)
277 })
278
279 CodeMirror.defineExtension("selectMatches", function(query, caseFold) {
280 var ranges = []
281 var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold)
282 while (cur.findNext()) {
283 if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break
284 ranges.push({anchor: cur.from(), head: cur.to()})
285 }
286 if (ranges.length)
287 this.setSelections(ranges, 0)
288 })
289 });
290