PluginProbe ʕ •ᴥ•ʔ
SiteOrigin CSS / 1.2.1
SiteOrigin CSS v1.2.1
1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.4.0 1.4.1 1.4.2 1.4.3 1.5.0 1.5.1 1.5.10 1.5.11 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 trunk 1.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.1 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.2.0
so-css / lib / codemirror / addon / search / search.js
so-css / lib / codemirror / addon / search Last commit date
jump-to-line.js 8 years ago jump-to-line.min.js 8 years ago match-highlighter.js 8 years ago match-highlighter.min.js 8 years ago matchesonscrollbar.css 8 years ago matchesonscrollbar.js 8 years ago matchesonscrollbar.min.js 8 years ago search.js 8 years ago search.min.js 8 years ago searchcursor.js 8 years ago searchcursor.min.js 8 years ago
search.js
253 lines
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
22 function searchOverlay(query, caseInsensitive) {
23 if (typeof query == "string")
24 query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g");
25 else if (!query.global)
26 query = new RegExp(query.source, query.ignoreCase ? "gi" : "g");
27
28 return {token: function(stream) {
29 query.lastIndex = stream.pos;
30 var match = query.exec(stream.string);
31 if (match && match.index == stream.pos) {
32 stream.pos += match[0].length || 1;
33 return "searching";
34 } else if (match) {
35 stream.pos = match.index;
36 } else {
37 stream.skipToEnd();
38 }
39 }};
40 }
41
42 function SearchState() {
43 this.posFrom = this.posTo = this.lastQuery = this.query = null;
44 this.overlay = null;
45 }
46
47 function getSearchState(cm) {
48 return cm.state.search || (cm.state.search = new SearchState());
49 }
50
51 function queryCaseInsensitive(query) {
52 return typeof query == "string" && query == query.toLowerCase();
53 }
54
55 function getSearchCursor(cm, query, pos) {
56 // Heuristic: if the query string is all lowercase, do a case insensitive search.
57 return cm.getSearchCursor(query, pos, {caseFold: queryCaseInsensitive(query), multiline: true});
58 }
59
60 function persistentDialog(cm, text, deflt, onEnter, onKeyDown) {
61 cm.openDialog(text, onEnter, {
62 value: deflt,
63 selectValueOnOpen: true,
64 closeOnEnter: false,
65 onClose: function() { clearSearch(cm); },
66 onKeyDown: onKeyDown
67 });
68 }
69
70 function dialog(cm, text, shortText, deflt, f) {
71 if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true});
72 else f(prompt(shortText, deflt));
73 }
74
75 function confirmDialog(cm, text, shortText, fs) {
76 if (cm.openConfirm) cm.openConfirm(text, fs);
77 else if (confirm(shortText)) fs[0]();
78 }
79
80 function parseString(string) {
81 return string.replace(/\\(.)/g, function(_, ch) {
82 if (ch == "n") return "\n"
83 if (ch == "r") return "\r"
84 return ch
85 })
86 }
87
88 function parseQuery(query) {
89 var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
90 if (isRE) {
91 try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); }
92 catch(e) {} // Not a regular expression after all, do a string search
93 } else {
94 query = parseString(query)
95 }
96 if (typeof query == "string" ? query == "" : query.test(""))
97 query = /x^/;
98 return query;
99 }
100
101 var queryDialog =
102 '<span class="CodeMirror-search-label">Search:</span> <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>';
103
104 function startSearch(cm, state, query) {
105 state.queryText = query;
106 state.query = parseQuery(query);
107 cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
108 state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));
109 cm.addOverlay(state.overlay);
110 if (cm.showMatchesOnScrollbar) {
111 if (state.annotate) { state.annotate.clear(); state.annotate = null; }
112 state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query));
113 }
114 }
115
116 function doSearch(cm, rev, persistent, immediate) {
117 var state = getSearchState(cm);
118 if (state.query) return findNext(cm, rev);
119 var q = cm.getSelection() || state.lastQuery;
120 if (q instanceof RegExp && q.source == "x^") q = null
121 if (persistent && cm.openDialog) {
122 var hiding = null
123 var searchNext = function(query, event) {
124 CodeMirror.e_stop(event);
125 if (!query) return;
126 if (query != state.queryText) {
127 startSearch(cm, state, query);
128 state.posFrom = state.posTo = cm.getCursor();
129 }
130 if (hiding) hiding.style.opacity = 1
131 findNext(cm, event.shiftKey, function(_, to) {
132 var dialog
133 if (to.line < 3 && document.querySelector &&
134 (dialog = cm.display.wrapper.querySelector(".CodeMirror-dialog")) &&
135 dialog.getBoundingClientRect().bottom - 4 > cm.cursorCoords(to, "window").top)
136 (hiding = dialog).style.opacity = .4
137 })
138 };
139 persistentDialog(cm, queryDialog, q, searchNext, function(event, query) {
140 var keyName = CodeMirror.keyName(event)
141 var extra = cm.getOption('extraKeys'), cmd = (extra && extra[keyName]) || CodeMirror.keyMap[cm.getOption("keyMap")][keyName]
142 if (cmd == "findNext" || cmd == "findPrev" ||
143 cmd == "findPersistentNext" || cmd == "findPersistentPrev") {
144 CodeMirror.e_stop(event);
145 startSearch(cm, getSearchState(cm), query);
146 cm.execCommand(cmd);
147 } else if (cmd == "find" || cmd == "findPersistent") {
148 CodeMirror.e_stop(event);
149 searchNext(query, event);
150 }
151 });
152 if (immediate && q) {
153 startSearch(cm, state, q);
154 findNext(cm, rev);
155 }
156 } else {
157 dialog(cm, queryDialog, "Search for:", q, function(query) {
158 if (query && !state.query) cm.operation(function() {
159 startSearch(cm, state, query);
160 state.posFrom = state.posTo = cm.getCursor();
161 findNext(cm, rev);
162 });
163 });
164 }
165 }
166
167 function findNext(cm, rev, callback) {cm.operation(function() {
168 var state = getSearchState(cm);
169 var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
170 if (!cursor.find(rev)) {
171 cursor = getSearchCursor(cm, state.query, rev ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(cm.firstLine(), 0));
172 if (!cursor.find(rev)) return;
173 }
174 cm.setSelection(cursor.from(), cursor.to());
175 cm.scrollIntoView({from: cursor.from(), to: cursor.to()}, 20);
176 state.posFrom = cursor.from(); state.posTo = cursor.to();
177 if (callback) callback(cursor.from(), cursor.to())
178 });}
179
180 function clearSearch(cm) {cm.operation(function() {
181 var state = getSearchState(cm);
182 state.lastQuery = state.query;
183 if (!state.query) return;
184 state.query = state.queryText = null;
185 cm.removeOverlay(state.overlay);
186 if (state.annotate) { state.annotate.clear(); state.annotate = null; }
187 });}
188
189 var replaceQueryDialog =
190 ' <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>';
191 var replacementQueryDialog = '<span class="CodeMirror-search-label">With:</span> <input type="text" style="width: 10em" class="CodeMirror-search-field"/>';
192 var doReplaceConfirm = '<span class="CodeMirror-search-label">Replace?</span> <button>Yes</button> <button>No</button> <button>All</button> <button>Stop</button>';
193
194 function replaceAll(cm, query, text) {
195 cm.operation(function() {
196 for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
197 if (typeof query != "string") {
198 var match = cm.getRange(cursor.from(), cursor.to()).match(query);
199 cursor.replace(text.replace(/\$(\d)/g, function(_, i) {return match[i];}));
200 } else cursor.replace(text);
201 }
202 });
203 }
204
205 function replace(cm, all) {
206 if (cm.getOption("readOnly")) return;
207 var query = cm.getSelection() || getSearchState(cm).lastQuery;
208 var dialogText = '<span class="CodeMirror-search-label">' + (all ? 'Replace all:' : 'Replace:') + '</span>';
209 dialog(cm, dialogText + replaceQueryDialog, dialogText, query, function(query) {
210 if (!query) return;
211 query = parseQuery(query);
212 dialog(cm, replacementQueryDialog, "Replace with:", "", function(text) {
213 text = parseString(text)
214 if (all) {
215 replaceAll(cm, query, text)
216 } else {
217 clearSearch(cm);
218 var cursor = getSearchCursor(cm, query, cm.getCursor("from"));
219 var advance = function() {
220 var start = cursor.from(), match;
221 if (!(match = cursor.findNext())) {
222 cursor = getSearchCursor(cm, query);
223 if (!(match = cursor.findNext()) ||
224 (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return;
225 }
226 cm.setSelection(cursor.from(), cursor.to());
227 cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
228 confirmDialog(cm, doReplaceConfirm, "Replace?",
229 [function() {doReplace(match);}, advance,
230 function() {replaceAll(cm, query, text)}]);
231 };
232 var doReplace = function(match) {
233 cursor.replace(typeof query == "string" ? text :
234 text.replace(/\$(\d)/g, function(_, i) {return match[i];}));
235 advance();
236 };
237 advance();
238 }
239 });
240 });
241 }
242
243 CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};
244 CodeMirror.commands.findPersistent = function(cm) {clearSearch(cm); doSearch(cm, false, true);};
245 CodeMirror.commands.findPersistentNext = function(cm) {doSearch(cm, false, true, true);};
246 CodeMirror.commands.findPersistentPrev = function(cm) {doSearch(cm, true, true, true);};
247 CodeMirror.commands.findNext = doSearch;
248 CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};
249 CodeMirror.commands.clearSearch = clearSearch;
250 CodeMirror.commands.replace = replace;
251 CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);};
252 });
253