diff --git a/addon/search/search.js b/addon/search/search.js index 4bcfbe1be1deaa08a0f629a4b542a4970dfa2902..9f804b15127290964ff8f153d4f8cddae5fc5f8b 100644 --- a/addon/search/search.js +++ b/addon/search/search.js @@ -57,10 +57,20 @@ return cm.getSearchCursor(query, pos, queryCaseInsensitive(query)); } + function persistentDialog(cm, text, deflt, f) { + cm.openDialog(text, f, { + value: deflt, + selectValueOnOpen: true, + closeOnEnter: false, + onClose: function() { clearSearch(cm); } + }); + } + function dialog(cm, text, shortText, deflt, f) { if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true}); else f(prompt(shortText, deflt)); } + function confirmDialog(cm, text, shortText, fs) { if (cm.openConfirm) cm.openConfirm(text, fs); else if (confirm(shortText)) fs[0](); @@ -80,25 +90,38 @@ var queryDialog = '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>'; - function doSearch(cm, rev) { + function startSearch(cm, state, query) { + state.queryText = query; + state.query = parseQuery(query); + cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query)); + state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query)); + cm.addOverlay(state.overlay); + if (cm.showMatchesOnScrollbar) { + if (state.annotate) { state.annotate.clear(); state.annotate = null; } + state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query)); + } + } + + function doSearch(cm, rev, persistent) { var state = getSearchState(cm); if (state.query) return findNext(cm, rev); var q = cm.getSelection() || state.lastQuery; - dialog(cm, queryDialog, "Search for:", q, function(query) { - cm.operation(function() { - if (!query || state.query) return; - state.query = parseQuery(query); - cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query)); - state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query)); - cm.addOverlay(state.overlay); - if (cm.showMatchesOnScrollbar) { - if (state.annotate) { state.annotate.clear(); state.annotate = null; } - state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query)); - } - state.posFrom = state.posTo = cm.getCursor(); - findNext(cm, rev); + if (persistent && cm.openDialog) { + persistentDialog(cm, queryDialog, q, function(query, event) { + CodeMirror.e_stop(event); + if (!query) return; + if (query != state.queryText) startSearch(cm, state, query); + findNext(cm, event.shiftKey); }); - }); + } else { + dialog(cm, queryDialog, "Search for:", q, function(query) { + if (query && !state.query) cm.operation(function() { + startSearch(cm, state, query); + state.posFrom = state.posTo = cm.getCursor(); + findNext(cm, rev); + }); + }); + } } function findNext(cm, rev) {cm.operation(function() { @@ -170,6 +193,7 @@ } CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);}; + CodeMirror.commands.findPersistent = function(cm) {clearSearch(cm); doSearch(cm, false, true);}; CodeMirror.commands.findNext = doSearch; CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);}; CodeMirror.commands.clearSearch = clearSearch; diff --git a/demo/search.html b/demo/search.html index 04ba7ac09a0995c47a82063ad80a8bcb19c89d92..21c34251e21661004bbfd592f8fee95538c093ce 100644 --- a/demo/search.html +++ b/demo/search.html @@ -71,18 +71,20 @@ <script> var editor = CodeMirror.fromTextArea(document.getElementById("code"), { mode: "text/html", - lineNumbers: true + lineNumbers: true, + extraKeys: {"Alt-F": "findPersistent"} }); </script> <p>Demonstration of primitive search/replace functionality. The - keybindings (which can be overridden by custom keymaps) are:</p> + keybindings (which can be configured with custom keymaps) are:</p> <dl> <dt>Ctrl-F / Cmd-F</dt><dd>Start searching</dd> <dt>Ctrl-G / Cmd-G</dt><dd>Find next</dd> <dt>Shift-Ctrl-G / Shift-Cmd-G</dt><dd>Find previous</dd> <dt>Shift-Ctrl-F / Cmd-Option-F</dt><dd>Replace</dd> <dt>Shift-Ctrl-R / Shift-Cmd-Option-F</dt><dd>Replace all</dd> + <dt>Alt-F</dt><dd>Persistent search (dialog doesn't autoclose, enter to find next, shift-enter to find previous)</dd> </dl> <p>Searching is enabled by including <a href="../addon/search/search.js">addon/search/search.js</a>