Skip to content

Commit 014ad59

Browse files
committed
Improved replace UX
1 parent 9916ef0 commit 014ad59

File tree

1 file changed

+80
-19
lines changed

1 file changed

+80
-19
lines changed

client/utils/codemirror-search.js

+80-19
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export default function(CodeMirror) {
5050
this.regexp = false;
5151
this.caseInsensitive = true;
5252
this.wholeWord = false;
53+
this.replaceStarted = false;
5354
}
5455

5556
function getSearchState(cm) {
@@ -89,6 +90,12 @@ export default function(CodeMirror) {
8990
CodeMirror.on(searchField, "keyup", function (e) {
9091
if (e.keyCode === 13) {
9192
// If enter is pressed, then shift focus to replace field
93+
var state = getSearchState(cm);
94+
startSearch(cm, state, searchField.value);
95+
state.replaceStarted = true;
96+
cm.focus();
97+
CodeMirror.commands.findNext(cm);
98+
searchField.blur();
9299
replaceField.focus();
93100
}
94101
else if (e.keyCode !== 13 && searchField.value.length > 1) { // not enter and more than 1 character to search
@@ -162,19 +169,11 @@ export default function(CodeMirror) {
162169
return nextState;
163170
}
164171

165-
var showReplaceButton = dialog.getElementsByClassName("CodeMirror-replace-toggle-button")[0];
166-
var toggleReplaceBtnDiv = dialog.getElementsByClassName("Toggle-replace-btn-div")[0];
167-
var replaceDiv = dialog.getElementsByClassName("CodeMirror-replace-div")[0];
168-
var replaceDivHeightOpened = "45px", replaceDivHeightClosed = "0px";
169-
var toggleButtonHeightOpened = "80px", toggleButtonHeightClosed = "40px";
170-
if (replaceOpened) {
171-
replaceDiv.style.height = replaceDivHeightOpened;
172-
toggleReplaceBtnDiv.style.height = toggleButtonHeightOpened;
173-
showReplaceButton.style.height = toggleButtonHeightOpened;
174-
showReplaceButton.innerHTML = "▼";
175-
}
176-
CodeMirror.on(showReplaceButton, "click", function () {
177-
if (replaceDiv.style.height === "0px") {
172+
function toggleReplace(open) {
173+
var replaceDivHeightOpened = "45px", replaceDivHeightClosed = "0px";
174+
var toggleButtonHeightOpened = "80px", toggleButtonHeightClosed = "40px";
175+
176+
if (open) {
178177
replaceDiv.style.height = replaceDivHeightOpened;
179178
toggleReplaceBtnDiv.style.height = toggleButtonHeightOpened;
180179
showReplaceButton.style.height = toggleButtonHeightOpened;
@@ -185,27 +184,88 @@ export default function(CodeMirror) {
185184
showReplaceButton.style.height = toggleButtonHeightClosed;
186185
showReplaceButton.innerHTML = "▶";
187186
}
187+
}
188+
189+
var showReplaceButton = dialog.getElementsByClassName("CodeMirror-replace-toggle-button")[0];
190+
var toggleReplaceBtnDiv = dialog.getElementsByClassName("Toggle-replace-btn-div")[0];
191+
var replaceDiv = dialog.getElementsByClassName("CodeMirror-replace-div")[0];
192+
if (replaceOpened) {
193+
toggleReplace(true);
194+
}
195+
CodeMirror.on(showReplaceButton, "click", function () {
196+
if (replaceDiv.style.height === "0px") {
197+
toggleReplace(true);
198+
} else {
199+
toggleReplace(false);
200+
}
188201
});
189202

190203
var replaceField = document.getElementById('Replace-input-field');
191204
CodeMirror.on(replaceField, "keyup", function (e) {
205+
if (!searchField.value) {
206+
searchField.focus();
207+
return;
208+
}
209+
var state = getSearchState(cm);
210+
var query = parseQuery(searchField.value, state);
211+
var withText = parseString(replaceField.value);
192212
if (e.keyCode === 13) // if enter
193213
{
194-
startSearch(cm, getSearchState(cm), searchField.value);
195-
replace(cm, parseString(searchField.value), parseString(replaceField.value));
214+
var cursor = getSearchCursor(cm, query, cm.getCursor("from"));
215+
var match = cursor.findNext();
216+
cm.setSelection(cursor.from(), cursor.to());
217+
doReplace(match, cursor, query, withText);
196218
}
197219
})
198220

221+
function doReplace(match, cursor, query, withText) {
222+
cursor.replace(typeof query == "string" ? withText :
223+
withText.replace(/\$(\d)/g, function(_, i) {return match[i];}));
224+
cursor.findNext();
225+
cm.focus();
226+
CodeMirror.commands.findNext(cm);
227+
searchField.blur();
228+
};
229+
199230
var doReplaceButton = document.getElementById('Btn-replace');
200231
CodeMirror.on(doReplaceButton, "click", function(e) {
201-
startSearch(cm, getSearchState(cm), searchField.value);
202-
replace(cm, parseString(searchField.value), parseString(replaceField.value));
232+
if (!searchField.value) {
233+
searchField.focus();
234+
return;
235+
}
236+
var state = getSearchState(cm);
237+
var query = parseQuery(searchField.value, state);
238+
var withText = parseString(replaceField.value);
239+
if (state.replaceStarted) {
240+
var cursor = getSearchCursor(cm, query, cm.getCursor("from"));
241+
var match = cursor.findNext();
242+
cm.setSelection(cursor.from(), cursor.to());
243+
doReplace(match, cursor, query, withText);
244+
} else {
245+
startSearch(cm, state, searchField.value);
246+
state.replaceStarted = true;
247+
cm.focus();
248+
CodeMirror.commands.findNext(cm);
249+
searchField.blur();
250+
}
203251
})
204252

205253
var doReplaceAllButton = document.getElementById('Btn-replace-all');
206254
CodeMirror.on(doReplaceAllButton, "click", function(e) {
207-
startSearch(cm, getSearchState(cm), searchField.value);
208-
replace(cm, parseString(searchField.value), parseString(replaceField.value), true);
255+
if (!searchField.value) {
256+
searchField.focus();
257+
return;
258+
}
259+
var state = getSearchState(cm);
260+
var query = parseQuery(searchField.value, state);
261+
var withText = parseString(replaceField.value);
262+
if (state.replaceStarted) {
263+
replaceAll(cm, query, withText);
264+
state.replaceStarted = false;
265+
} else {
266+
startSearch(cm, state, searchField.value);
267+
state.replaceStarted = true;
268+
}
209269
})
210270

211271
} else {
@@ -399,6 +459,7 @@ export default function(CodeMirror) {
399459
function clearSearch(cm) {cm.operation(function() {
400460
var state = getSearchState(cm);
401461
state.lastQuery = state.queryText;
462+
state.replaceStarted = false;
402463
if (!state.query) return;
403464
state.query = state.queryText = null;
404465
cm.removeOverlay(state.overlay);

0 commit comments

Comments
 (0)