Skip to content
This repository was archived by the owner on Sep 6, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
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
62 changes: 43 additions & 19 deletions src/search/FindReplace.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@ define(function (require, exports, module) {
$(".modal-bar .message").css("display", "inline-block");
$(".modal-bar .error").css("display", "none");
try {
return isRE ? new RegExp(isRE[1], isRE[2].indexOf("i") === -1 ? "" : "i") : query;
if (isRE && isRE[1]) { // non-empty regexp
return new RegExp(isRE[1], isRE[2].indexOf("i") === -1 ? "" : "i");
} else {
return query;
}
} catch (e) {
$(".modal-bar .message").css("display", "none");
$(".modal-bar .error")
Expand Down Expand Up @@ -101,20 +105,22 @@ define(function (require, exports, module) {
return found;
}

function clearHighlights(state) {
state.marked.forEach(function (markedRange) {
markedRange.clear();
});
state.marked.length = 0;
}

function clearSearch(cm) {
cm.operation(function () {
var state = getSearchState(cm),
i;
var state = getSearchState(cm);
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;

clearHighlights(state);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function only uses the state.marked member, so that should be pass in instead. This would save a a lot of dereferencing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The forEach() change you suggested above removes most of the dereferencing already, so I left it passing the full 'state' object for clarity. If we do more complex highlighting later we may need access to more of the state properties anyway.

});
}

Expand Down Expand Up @@ -158,21 +164,33 @@ define(function (require, exports, module) {
// result, starting from the original cursor position
function findFirst(query) {
cm.operation(function () {
if (!query) {
return;
}

if (state.query) {
clearSearch(cm); // clear highlights from previous query
clearHighlights(getSearchState(cm));
}
state.query = parseQuery(query);
if (!state.query) {
cm.setCursor(searchStartPos);
return;
}

// 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);
// (Except on huge documents, where this is too expensive)
if (cm.getValue().length < 500000) {
// Temporarily change selection color to improve highlighting - see LESS code for details
$(cm.getWrapperElement()).addClass("find-highlighting");

// FUTURE: if last query was prefix of this one, could optimize by filtering existing result set
var cursor = getSearchCursor(cm, state.query);
while (cursor.findNext()) {
state.marked.push(cm.markText(cursor.from(), cursor.to(), "CodeMirror-searching"));

//Remove this section when https://github.com/marijnh/CodeMirror/issues/1155 will be fixed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

codemirror/codemirror5#1155 has been closed, so you should be able to remove this code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's only implemented in CMv3 and this is going into master, so we can't remove it yet. Happy to do that as a cleanup next sprint once things settle down, though.

if (cursor.pos.match && cursor.pos.match[0] === "") {
if (cursor.to().line + 1 === cm.lineCount()) {
break;
}
cursor = getSearchCursor(cm, state.query, {line: cursor.to().line + 1, ch: 0});
}
}
}

Expand Down Expand Up @@ -202,7 +220,13 @@ define(function (require, exports, module) {
findFirst(query);
}
});

$(modalBar).on("closeOk closeCancel closeBlur", function (e, query) {
clearHighlights(state);

// As soon as focus goes back to the editor, restore normal selection color
$(cm.getWrapperElement()).removeClass("find-highlighting");
});

var $input = getDialogTextField();
$input.on("input", function () {
findFirst($input.attr("value"));
Expand Down Expand Up @@ -304,7 +328,7 @@ define(function (require, exports, module) {
if (editor) {
var codeMirror = editor._codeMirror;

// Bring up CodeMirror's existing search bar UI
// Create a new instance of the search bar UI
clearSearch(codeMirror);
doSearch(codeMirror, false, codeMirror.getSelection());
}
Expand Down
13 changes: 12 additions & 1 deletion src/styles/brackets.less
Original file line number Diff line number Diff line change
Expand Up @@ -764,9 +764,20 @@ a, img {
}
}

// Search result highlighting - CodeMirror highlighting is pretty constrained. Highlights are
// blended on TOP of the selection color. The "current" search result is indicated by selection,
// so we want the selection visible underneath the highlight. To do this, the highlight must be
// transparent; it has to look good atop both the selection color AND the regular text bg color.
.CodeMirror-searching {
background-color: inherit;
// Highlight color, overlaid on top of the .find-highlighting color
background-color: rgba(244, 237, 98, 0.7);
}
.CodeMirror.find-highlighting div.CodeMirror-selected {
// Selection color while highlighting shown - ALWAYS has the .CodeMirror-searching color
// blended atop it
background: rgb(255, 108, 0);
}



/* Quick Open search bar & dropdown */
Expand Down
Loading