[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/media/vendor/codemirror/addon/search/ -> searchcursor.js (source)

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


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer