Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.

Commit 3aa884f

Browse files
author
Nathan Sobo
authored
Merge pull request #1088 from atom/ns/multiple-selections
Support multiple selections when "Only In Selection" option is enabled
2 parents 4012253 + f694fe7 commit 3aa884f

File tree

2 files changed

+78
-19
lines changed

2 files changed

+78
-19
lines changed

lib/buffer-search.js

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ class BufferSearch {
7777
changedParams.wholeWord != null ||
7878
changedParams.caseSensitive != null ||
7979
changedParams.inCurrentSelection != null ||
80-
(this.findOptions.inCurrentSelection === true && !this.editor.getSelectedBufferRange().isEqual(this.selectedRange))) {
80+
(this.findOptions.inCurrentSelection === true
81+
&& !selectionsEqual(this.editor.getSelectedBufferRanges(), this.selectedRanges))) {
8182
this.recreateMarkers();
8283
}
8384
}
@@ -135,37 +136,32 @@ class BufferSearch {
135136
createMarkers(start, end) {
136137
let newMarkers = [];
137138
if (this.findOptions.findPattern && this.editor) {
138-
this.selectedRange = this.editor.getSelectedBufferRange()
139-
if (this.findOptions.inCurrentSelection && !this.selectedRange.isEmpty()) {
140-
start = Point.max(start, this.selectedRange.start);
141-
end = Point.min(end, this.selectedRange.end);
139+
this.selectedRanges = this.editor.getSelectedBufferRanges()
140+
141+
let searchRanges = []
142+
if (this.findOptions.inCurrentSelection) {
143+
searchRanges.push(...this.selectedRanges.filter(range => !range.isEmpty()))
144+
}
145+
if (searchRanges.length === 0) {
146+
searchRanges.push(Range(start, end))
142147
}
143148

144149
const buffer = this.editor.getBuffer()
145150
const regex = this.getFindPatternRegex(buffer.hasAstral && buffer.hasAstral())
146151
if (regex) {
147152
try {
148-
// TODO - remove this conditional after Atom 1.25 ships
149-
if (buffer.findAndMarkAllInRangeSync) {
150-
newMarkers = this.editor.getBuffer().findAndMarkAllInRangeSync(
153+
for (const range of searchRanges) {
154+
const bufferMarkers = this.editor.getBuffer().findAndMarkAllInRangeSync(
151155
this.resultsMarkerLayer.bufferMarkerLayer,
152156
regex,
153-
Range(start, end),
157+
range,
154158
{invalidate: 'inside'}
155159
);
156-
for (let i = 0, n = newMarkers.length; i < n; i++) {
157-
newMarkers[i] = this.resultsMarkerLayer.getMarker(newMarkers[i].id)
160+
for (const bufferMarker of bufferMarkers) {
161+
newMarkers.push(this.resultsMarkerLayer.getMarker(bufferMarker.id))
158162
}
159-
} else {
160-
buffer.scanInRange(regex, Range(start, end), ({range}) => {
161-
newMarkers.push(this.createMarker(range));
162-
});
163163
}
164164
} catch (error) {
165-
// TODO - remove after Atom 1.25 ships.
166-
if (/RegExp too big$/.test(error.message)) {
167-
error.message = "regular expression is too large";
168-
}
169165
this.emitter.emit('did-error', error);
170166
return false;
171167
}
@@ -291,3 +287,16 @@ class BufferSearch {
291287
}
292288
}
293289
};
290+
291+
function selectionsEqual(selectionsA, selectionsB) {
292+
if (selectionsA.length === selectionsB.length) {
293+
for (let i = 0; i < selectionsA.length; i++) {
294+
if (!selectionsA[i].isEqual(selectionsB[i])) {
295+
return false
296+
}
297+
}
298+
return true
299+
} else {
300+
return false
301+
}
302+
}

spec/buffer-search-spec.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,56 @@ describe('BufferSearch', () => {
448448
})
449449
})
450450

451+
describe("if there are multiple non-empty selections", () => {
452+
beforeEach(() => {
453+
editor.setSelectedBufferRanges([
454+
[[1, 3], [2, 11]],
455+
[[5, 2], [8, 0]],
456+
]);
457+
})
458+
459+
it("searches in all the selections", () => {
460+
model.search("a+");
461+
462+
expect(getHighlightedRanges()).toEqual([
463+
[[2, 4], [2, 7]],
464+
[[5, 2], [5, 3]],
465+
[[6, 4], [6, 7]],
466+
[[7, 8], [7, 11]]
467+
]);
468+
})
469+
470+
it("executes another search if the current selection is different from the last search's selection", () => {
471+
spyOn(model, 'recreateMarkers').andCallThrough()
472+
473+
model.search("a+");
474+
editor.setSelectedBufferRanges([
475+
[[1, 3], [2, 11]],
476+
[[5, 1], [8, 0]],
477+
]);
478+
model.search("a+");
479+
480+
expect(model.recreateMarkers.callCount).toBe(2)
481+
expect(getHighlightedRanges()).toEqual([
482+
[[2, 4], [2, 7]],
483+
[[5, 1], [5, 3]],
484+
[[6, 4], [6, 7]],
485+
[[7, 8], [7, 11]]
486+
]);
487+
})
488+
489+
it("does not execute another search if the current selection is idential to the last search's selection", () => {
490+
spyOn(model, 'recreateMarkers').andCallThrough()
491+
editor.setSelectedBufferRanges([
492+
[[1, 3], [2, 11]],
493+
[[5, 1], [8, 0]],
494+
]);
495+
model.search("a+");
496+
model.search("a+");
497+
expect(model.recreateMarkers.callCount).toBe(1)
498+
})
499+
})
500+
451501
describe("if the current selection is empty", () => {
452502
beforeEach(() => {
453503
editor.setSelectedBufferRange([[0, 0], [0, 0]]);

0 commit comments

Comments
 (0)