Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

Incremental search while typing in the Find bar #1781

Merged
merged 1 commit into from
Oct 12, 2012
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 49 additions & 22 deletions src/search/FindReplace.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,12 @@

/*
* Adds Find and Replace commands
*
* Originally based on the code in CodeMirror2/lib/util/search.js.
*
* Define search commands. Depends on dialog.js or another
* implementation of the openDialog method.
*
* This code was copied from CodeMirror2/lib/util/search.js so that the UI strings
* could be localized.
*
* Replace works a little oddly -- it will do the replace on the next findNext press.
* You prevent a replace by making sure the match is no longer selected when hitting
* findNext.
Expand Down Expand Up @@ -80,6 +79,10 @@ define(function (require, exports, module) {
fs[0]();
}
}

function getDialogTextField() {
return $(".CodeMirror-dialog input[type='text']");
}

function parseQuery(query) {
var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
Expand All @@ -102,45 +105,69 @@ define(function (require, exports, module) {
});
}

function clearSearch(cm) {
cm.operation(function () {
var state = getSearchState(cm),
i;
if (!state.query) {
return;
}
state.query = null;

// Clear highlights
for (i = 0; i < state.marked.length; ++i) {
state.marked[i].clear();
}
state.marked.length = 0;
});
}

var queryDialog = Strings.CMD_FIND +
': <input type="text" style="width: 10em"/> <span style="color: #888">(' +
Strings.SEARCH_REGEXP_INFO + ')</span>';

/**
* If no search pending, opens the search dialog. If search is already open, moves to
* next/prev result (depending on 'rev')
*/
function doSearch(cm, rev) {
var state = getSearchState(cm);
if (state.query) {
return findNext(cm, rev);
}
dialog(cm, queryDialog, Strings.CMD_FIND, function (query) {

var searchStartPos = cm.getCursor();

// Called each time the search query changes while being typed. Jumps to the first matching
// result, starting from the original cursor position
function findFirst(query) {
cm.operation(function () {
if (!query || state.query) {
if (!query) {
return;
}

if (state.query) {
clearSearch(cm); // clear highlights from previous query
}
state.query = parseQuery(query);

// Highlight all matches
// FUTURE: if last query was prefix of this one, could optimize by filtering existing result set
if (cm.lineCount() < 2000) { // This is too expensive on big documents.
var cursor = getSearchCursor(cm, query);
while (cursor.findNext()) {
state.marked.push(cm.markText(cursor.from(), cursor.to(), "CodeMirror-searching"));
}
}
state.posFrom = state.posTo = cm.getCursor();

state.posFrom = state.posTo = searchStartPos;
findNext(cm, rev);
});
});
}

function clearSearch(cm) {
cm.operation(function () {
var state = getSearchState(cm),
i;
if (!state.query) {
return;
}
state.query = null;
for (i = 0; i < state.marked.length; ++i) {
state.marked[i].clear();
}
state.marked.length = 0;
}

dialog(cm, queryDialog, Strings.CMD_FIND, findFirst);
getDialogTextField().on("input", function () {
findFirst(getDialogTextField().attr("value"));
});
}

Expand Down Expand Up @@ -218,7 +245,7 @@ define(function (require, exports, module) {
doSearch(codeMirror);

// Prepopulate the search field with the current selection, if any
$(".CodeMirror-dialog input[type='text']")
getDialogTextField()
.attr("value", codeMirror.getSelection())
.get(0).select();
}
Expand Down