LaravelTest
305 строк · 11.9 Кб
1// CodeMirror, copyright (c) by Marijn Haverbeke and others
2// Distributed under an MIT license: https://codemirror.net/LICENSE
3
4(function(mod) {5if (typeof exports == "object" && typeof module == "object") // CommonJS6mod(require("../../lib/codemirror"))7else if (typeof define == "function" && define.amd) // AMD8define(["../../lib/codemirror"], mod)9else // Plain browser env10mod(CodeMirror)11})(function(CodeMirror) {12"use strict"13var Pos = CodeMirror.Pos14
15function regexpFlags(regexp) {16var flags = regexp.flags17return flags != null ? flags : (regexp.ignoreCase ? "i" : "")18+ (regexp.global ? "g" : "")19+ (regexp.multiline ? "m" : "")20}21
22function ensureFlags(regexp, flags) {23var current = regexpFlags(regexp), target = current24for (var i = 0; i < flags.length; i++) if (target.indexOf(flags.charAt(i)) == -1)25target += flags.charAt(i)26return current == target ? regexp : new RegExp(regexp.source, target)27}28
29function maybeMultiline(regexp) {30return /\\s|\\n|\n|\\W|\\D|\[\^/.test(regexp.source)31}32
33function searchRegexpForward(doc, regexp, start) {34regexp = ensureFlags(regexp, "g")35for (var line = start.line, ch = start.ch, last = doc.lastLine(); line <= last; line++, ch = 0) {36regexp.lastIndex = ch37var string = doc.getLine(line), match = regexp.exec(string)38if (match)39return {from: Pos(line, match.index),40to: Pos(line, match.index + match[0].length),41match: match}42}43}44
45function searchRegexpForwardMultiline(doc, regexp, start) {46if (!maybeMultiline(regexp)) return searchRegexpForward(doc, regexp, start)47
48regexp = ensureFlags(regexp, "gm")49var string, chunk = 150for (var line = start.line, last = doc.lastLine(); line <= last;) {51// This grows the search buffer in exponentially-sized chunks52// between matches, so that nearby matches are fast and don't53// require concatenating the whole document (in case we're54// searching for something that has tons of matches), but at the55// same time, the amount of retries is limited.56for (var i = 0; i < chunk; i++) {57if (line > last) break58var curLine = doc.getLine(line++)59string = string == null ? curLine : string + "\n" + curLine60}61chunk = chunk * 262regexp.lastIndex = start.ch63var match = regexp.exec(string)64if (match) {65var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n")66var startLine = start.line + before.length - 1, startCh = before[before.length - 1].length67return {from: Pos(startLine, startCh),68to: Pos(startLine + inside.length - 1,69inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length),70match: match}71}72}73}74
75function lastMatchIn(string, regexp, endMargin) {76var match, from = 077while (from <= string.length) {78regexp.lastIndex = from79var newMatch = regexp.exec(string)80if (!newMatch) break81var end = newMatch.index + newMatch[0].length82if (end > string.length - endMargin) break83if (!match || end > match.index + match[0].length)84match = newMatch85from = newMatch.index + 186}87return match88}89
90function searchRegexpBackward(doc, regexp, start) {91regexp = ensureFlags(regexp, "g")92for (var line = start.line, ch = start.ch, first = doc.firstLine(); line >= first; line--, ch = -1) {93var string = doc.getLine(line)94var match = lastMatchIn(string, regexp, ch < 0 ? 0 : string.length - ch)95if (match)96return {from: Pos(line, match.index),97to: Pos(line, match.index + match[0].length),98match: match}99}100}101
102function searchRegexpBackwardMultiline(doc, regexp, start) {103if (!maybeMultiline(regexp)) return searchRegexpBackward(doc, regexp, start)104regexp = ensureFlags(regexp, "gm")105var string, chunkSize = 1, endMargin = doc.getLine(start.line).length - start.ch106for (var line = start.line, first = doc.firstLine(); line >= first;) {107for (var i = 0; i < chunkSize && line >= first; i++) {108var curLine = doc.getLine(line--)109string = string == null ? curLine : curLine + "\n" + string110}111chunkSize *= 2112
113var match = lastMatchIn(string, regexp, endMargin)114if (match) {115var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n")116var startLine = line + before.length, startCh = before[before.length - 1].length117return {from: Pos(startLine, startCh),118to: Pos(startLine + inside.length - 1,119inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length),120match: match}121}122}123}124
125var doFold, noFold126if (String.prototype.normalize) {127doFold = function(str) { return str.normalize("NFD").toLowerCase() }128noFold = function(str) { return str.normalize("NFD") }129} else {130doFold = function(str) { return str.toLowerCase() }131noFold = function(str) { return str }132}133
134// Maps a position in a case-folded line back to a position in the original line135// (compensating for codepoints increasing in number during folding)136function adjustPos(orig, folded, pos, foldFunc) {137if (orig.length == folded.length) return pos138for (var min = 0, max = pos + Math.max(0, orig.length - folded.length);;) {139if (min == max) return min140var mid = (min + max) >> 1141var len = foldFunc(orig.slice(0, mid)).length142if (len == pos) return mid143else if (len > pos) max = mid144else min = mid + 1145}146}147
148function searchStringForward(doc, query, start, caseFold) {149// Empty string would match anything and never progress, so we150// define it to match nothing instead.151if (!query.length) return null152var fold = caseFold ? doFold : noFold153var lines = fold(query).split(/\r|\n\r?/)154
155search: for (var line = start.line, ch = start.ch, last = doc.lastLine() + 1 - lines.length; line <= last; line++, ch = 0) {156var orig = doc.getLine(line).slice(ch), string = fold(orig)157if (lines.length == 1) {158var found = string.indexOf(lines[0])159if (found == -1) continue search160var start = adjustPos(orig, string, found, fold) + ch161return {from: Pos(line, adjustPos(orig, string, found, fold) + ch),162to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold) + ch)}163} else {164var cutFrom = string.length - lines[0].length165if (string.slice(cutFrom) != lines[0]) continue search166for (var i = 1; i < lines.length - 1; i++)167if (fold(doc.getLine(line + i)) != lines[i]) continue search168var end = doc.getLine(line + lines.length - 1), endString = fold(end), lastLine = lines[lines.length - 1]169if (endString.slice(0, lastLine.length) != lastLine) continue search170return {from: Pos(line, adjustPos(orig, string, cutFrom, fold) + ch),171to: Pos(line + lines.length - 1, adjustPos(end, endString, lastLine.length, fold))}172}173}174}175
176function searchStringBackward(doc, query, start, caseFold) {177if (!query.length) return null178var fold = caseFold ? doFold : noFold179var lines = fold(query).split(/\r|\n\r?/)180
181search: for (var line = start.line, ch = start.ch, first = doc.firstLine() - 1 + lines.length; line >= first; line--, ch = -1) {182var orig = doc.getLine(line)183if (ch > -1) orig = orig.slice(0, ch)184var string = fold(orig)185if (lines.length == 1) {186var found = string.lastIndexOf(lines[0])187if (found == -1) continue search188return {from: Pos(line, adjustPos(orig, string, found, fold)),189to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold))}190} else {191var lastLine = lines[lines.length - 1]192if (string.slice(0, lastLine.length) != lastLine) continue search193for (var i = 1, start = line - lines.length + 1; i < lines.length - 1; i++)194if (fold(doc.getLine(start + i)) != lines[i]) continue search195var top = doc.getLine(line + 1 - lines.length), topString = fold(top)196if (topString.slice(topString.length - lines[0].length) != lines[0]) continue search197return {from: Pos(line + 1 - lines.length, adjustPos(top, topString, top.length - lines[0].length, fold)),198to: Pos(line, adjustPos(orig, string, lastLine.length, fold))}199}200}201}202
203function SearchCursor(doc, query, pos, options) {204this.atOccurrence = false205this.afterEmptyMatch = false206this.doc = doc207pos = pos ? doc.clipPos(pos) : Pos(0, 0)208this.pos = {from: pos, to: pos}209
210var caseFold211if (typeof options == "object") {212caseFold = options.caseFold213} else { // Backwards compat for when caseFold was the 4th argument214caseFold = options215options = null216}217
218if (typeof query == "string") {219if (caseFold == null) caseFold = false220this.matches = function(reverse, pos) {221return (reverse ? searchStringBackward : searchStringForward)(doc, query, pos, caseFold)222}223} else {224query = ensureFlags(query, "gm")225if (!options || options.multiline !== false)226this.matches = function(reverse, pos) {227return (reverse ? searchRegexpBackwardMultiline : searchRegexpForwardMultiline)(doc, query, pos)228}229else230this.matches = function(reverse, pos) {231return (reverse ? searchRegexpBackward : searchRegexpForward)(doc, query, pos)232}233}234}235
236SearchCursor.prototype = {237findNext: function() {return this.find(false)},238findPrevious: function() {return this.find(true)},239
240find: function(reverse) {241var head = this.doc.clipPos(reverse ? this.pos.from : this.pos.to);242if (this.afterEmptyMatch && this.atOccurrence) {243// do not return the same 0 width match twice244head = Pos(head.line, head.ch)245if (reverse) {246head.ch--;247if (head.ch < 0) {248head.line--;249head.ch = (this.doc.getLine(head.line) || "").length;250}251} else {252head.ch++;253if (head.ch > (this.doc.getLine(head.line) || "").length) {254head.ch = 0;255head.line++;256}257}258if (CodeMirror.cmpPos(head, this.doc.clipPos(head)) != 0) {259return this.atOccurrence = false260}261}262var result = this.matches(reverse, head)263this.afterEmptyMatch = result && CodeMirror.cmpPos(result.from, result.to) == 0264
265if (result) {266this.pos = result267this.atOccurrence = true268return this.pos.match || true269} else {270var end = Pos(reverse ? this.doc.firstLine() : this.doc.lastLine() + 1, 0)271this.pos = {from: end, to: end}272return this.atOccurrence = false273}274},275
276from: function() {if (this.atOccurrence) return this.pos.from},277to: function() {if (this.atOccurrence) return this.pos.to},278
279replace: function(newText, origin) {280if (!this.atOccurrence) return281var lines = CodeMirror.splitLines(newText)282this.doc.replaceRange(lines, this.pos.from, this.pos.to, origin)283this.pos.to = Pos(this.pos.from.line + lines.length - 1,284lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0))285}286}287
288CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {289return new SearchCursor(this.doc, query, pos, caseFold)290})291CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) {292return new SearchCursor(this, query, pos, caseFold)293})294
295CodeMirror.defineExtension("selectMatches", function(query, caseFold) {296var ranges = []297var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold)298while (cur.findNext()) {299if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break300ranges.push({anchor: cur.from(), head: cur.to()})301}302if (ranges.length)303this.setSelections(ranges, 0)304})305});306