source: OpenRLabs-Git/deploy/rlabs-docker/web2py-rlabs/applications/admin/static/codemirror/addon/search/search.js

main
Last change on this file was 42bd667, checked in by David Fuertes <dfuertes@…>, 4 years ago

Historial Limpio

  • Property mode set to 100755
File size: 7.0 KB
Line 
1// CodeMirror, copyright (c) by Marijn Haverbeke and others
2// Distributed under an MIT license: http://codemirror.net/LICENSE
3
4// Define search commands. Depends on dialog.js or another
5// implementation of the openDialog method.
6
7// Replace works a little oddly -- it will do the replace on the next
8// Ctrl-G (or whatever is bound to findNext) press. You prevent a
9// replace by making sure the match is no longer selected when hitting
10// Ctrl-G.
11
12(function(mod) {
13  if (typeof exports == "object" && typeof module == "object") // CommonJS
14    mod(require("../../lib/codemirror"), require("./searchcursor"), require("../dialog/dialog"));
15  else if (typeof define == "function" && define.amd) // AMD
16    define(["../../lib/codemirror", "./searchcursor", "../dialog/dialog"], mod);
17  else // Plain browser env
18    mod(CodeMirror);
19})(function(CodeMirror) {
20  "use strict";
21  function searchOverlay(query, caseInsensitive) {
22    if (typeof query == "string")
23      query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g");
24    else if (!query.global)
25      query = new RegExp(query.source, query.ignoreCase ? "gi" : "g");
26
27    return {token: function(stream) {
28      query.lastIndex = stream.pos;
29      var match = query.exec(stream.string);
30      if (match && match.index == stream.pos) {
31        stream.pos += match[0].length;
32        return "searching";
33      } else if (match) {
34        stream.pos = match.index;
35      } else {
36        stream.skipToEnd();
37      }
38    }};
39  }
40
41  function SearchState() {
42    this.posFrom = this.posTo = this.query = null;
43    this.overlay = null;
44  }
45  function getSearchState(cm) {
46    return cm.state.search || (cm.state.search = new SearchState());
47  }
48  function queryCaseInsensitive(query) {
49    return typeof query == "string" && query == query.toLowerCase();
50  }
51  function getSearchCursor(cm, query, pos) {
52    // Heuristic: if the query string is all lowercase, do a case insensitive search.
53    return cm.getSearchCursor(query, pos, queryCaseInsensitive(query));
54  }
55  function dialog(cm, text, shortText, deflt, f) {
56    if (cm.openDialog) cm.openDialog(text, f, {value: deflt});
57    else f(prompt(shortText, deflt));
58  }
59  function confirmDialog(cm, text, shortText, fs) {
60    if (cm.openConfirm) cm.openConfirm(text, fs);
61    else if (confirm(shortText)) fs[0]();
62  }
63  function parseQuery(query) {
64    var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
65    if (isRE) {
66      try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); }
67      catch(e) {} // Not a regular expression after all, do a string search
68    }
69    if (typeof query == "string" ? query == "" : query.test(""))
70      query = /x^/;
71    return query;
72  }
73  var queryDialog =
74    'Search: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
75  function doSearch(cm, rev) {
76    var state = getSearchState(cm);
77    if (state.query) return findNext(cm, rev);
78    dialog(cm, queryDialog, "Search for:", cm.getSelection(), function(query) {
79      cm.operation(function() {
80        if (!query || state.query) return;
81        state.query = parseQuery(query);
82        cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
83        state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));
84        cm.addOverlay(state.overlay);
85        if (cm.showMatchesOnScrollbar) {
86          if (state.annotate) { state.annotate.clear(); state.annotate = null; }
87          state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query));
88        }
89        state.posFrom = state.posTo = cm.getCursor();
90        findNext(cm, rev);
91      });
92    });
93  }
94  function findNext(cm, rev) {cm.operation(function() {
95    var state = getSearchState(cm);
96    var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
97    if (!cursor.find(rev)) {
98      cursor = getSearchCursor(cm, state.query, rev ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(cm.firstLine(), 0));
99      if (!cursor.find(rev)) return;
100    }
101    cm.setSelection(cursor.from(), cursor.to());
102    cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
103    state.posFrom = cursor.from(); state.posTo = cursor.to();
104  });}
105  function clearSearch(cm) {cm.operation(function() {
106    var state = getSearchState(cm);
107    if (!state.query) return;
108    state.query = null;
109    cm.removeOverlay(state.overlay);
110    if (state.annotate) { state.annotate.clear(); state.annotate = null; }
111  });}
112
113  var replaceQueryDialog =
114    'Replace: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
115  var replacementQueryDialog = 'With: <input type="text" style="width: 10em" class="CodeMirror-search-field"/>';
116  var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
117  function replace(cm, all) {
118    if (cm.getOption("readOnly")) return;
119    dialog(cm, replaceQueryDialog, "Replace:", cm.getSelection(), function(query) {
120      if (!query) return;
121      query = parseQuery(query);
122      dialog(cm, replacementQueryDialog, "Replace with:", "", function(text) {
123        if (all) {
124          cm.operation(function() {
125            for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
126              if (typeof query != "string") {
127                var match = cm.getRange(cursor.from(), cursor.to()).match(query);
128                cursor.replace(text.replace(/\$(\d)/g, function(_, i) {return match[i];}));
129              } else cursor.replace(text);
130            }
131          });
132        } else {
133          clearSearch(cm);
134          var cursor = getSearchCursor(cm, query, cm.getCursor());
135          var advance = function() {
136            var start = cursor.from(), match;
137            if (!(match = cursor.findNext())) {
138              cursor = getSearchCursor(cm, query);
139              if (!(match = cursor.findNext()) ||
140                  (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return;
141            }
142            cm.setSelection(cursor.from(), cursor.to());
143            cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
144            confirmDialog(cm, doReplaceConfirm, "Replace?",
145                          [function() {doReplace(match);}, advance]);
146          };
147          var doReplace = function(match) {
148            cursor.replace(typeof query == "string" ? text :
149                           text.replace(/\$(\d)/g, function(_, i) {return match[i];}));
150            advance();
151          };
152          advance();
153        }
154      });
155    });
156  }
157
158  CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};
159  CodeMirror.commands.findNext = doSearch;
160  CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};
161  CodeMirror.commands.clearSearch = clearSearch;
162  CodeMirror.commands.replace = replace;
163  CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);};
164});
Note: See TracBrowser for help on using the repository browser.