refactor find widget to support multiple selection find/replace

上级 fcd551f9
......@@ -800,7 +800,7 @@ export interface ITextModel {
/**
* Search the model.
* @param searchString The string used to search. If it is a regular expression, set `isRegex` to true.
* @param searchScope Limit the searching to only search inside this range.
* @param searchScope Limit the searching to only search inside these ranges.
* @param isRegex Used to indicate that `searchString` is a regular expression.
* @param matchCase Force the matching to match lower/upper case exactly.
* @param wordSeparators Force the matching to match entire words only. Pass null otherwise.
......@@ -808,7 +808,7 @@ export interface ITextModel {
* @param limitResultCount Limit the number of results
* @return The ranges where the matches are. It is empty if no matches have been found.
*/
findMatches(searchString: string, searchScope: IRange, isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean, limitResultCount?: number): FindMatch[];
findMatches(searchString: string, searchScope: IRange | IRange[], isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean, limitResultCount?: number): FindMatch[];
/**
* Search the model for the next match. Loops to the beginning of the model if needed.
* @param searchString The string used to search. If it is a regular expression, set `isRegex` to true.
......
......@@ -1112,13 +1112,23 @@ export class TextModel extends Disposable implements model.ITextModel {
public findMatches(searchString: string, rawSearchScope: any, isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean, limitResultCount: number = LIMIT_FIND_COUNT): model.FindMatch[] {
this._assertNotDisposed();
let searchRange: Range;
if (Range.isIRange(rawSearchScope)) {
searchRange = this.validateRange(rawSearchScope);
} else {
searchRange = this.getFullModelRange();
let searchRanges: Range[] | null = null;
if (rawSearchScope !== null) {
if (!Array.isArray(rawSearchScope)) {
rawSearchScope = [rawSearchScope];
}
if (rawSearchScope.every((searchScope: Range) => Range.isIRange(searchScope))) {
searchRanges = rawSearchScope.map((searchScope: Range) => this.validateRange(searchScope));
}
}
if (searchRanges === null) {
searchRanges = [this.getFullModelRange()];
}
let matchMapper: (value: Range, index: number, array: Range[]) => model.FindMatch[];
if (!isRegex && searchString.indexOf('\n') < 0) {
// not regex, not multi line
const searchParams = new SearchParams(searchString, isRegex, matchCase, wordSeparators);
......@@ -1128,10 +1138,12 @@ export class TextModel extends Disposable implements model.ITextModel {
return [];
}
return this.findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount);
matchMapper = (searchRange: Range) => this.findMatchesLineByLine(searchRange, searchData, captureMatches, limitResultCount);
} else {
matchMapper = (searchRange: Range) => TextModelSearch.findMatches(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchRange, captureMatches, limitResultCount);
}
return TextModelSearch.findMatches(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchRange, captureMatches, limitResultCount);
return searchRanges.map(matchMapper).reduce((arr, matches: model.FindMatch[]) => arr.concat(matches), []);
}
public findNextMatch(searchString: string, rawSearchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string, captureMatches: boolean): model.FindMatch | null {
......
......@@ -233,12 +233,22 @@ export class CommonFindController extends Disposable implements IEditorContribut
this._state.change({ searchScope: null }, true);
} else {
if (this._editor.hasModel()) {
let selection = this._editor.getSelection();
if (selection.endColumn === 1 && selection.endLineNumber > selection.startLineNumber) {
selection = selection.setEndPosition(selection.endLineNumber - 1, this._editor.getModel().getLineMaxColumn(selection.endLineNumber - 1));
}
if (!selection.isEmpty()) {
this._state.change({ searchScope: selection }, true);
let selections = this._editor.getSelections();
selections.map(selection => {
if (selection.endColumn === 1 && selection.endLineNumber > selection.startLineNumber) {
selection = selection.setEndPosition(
selection.endLineNumber - 1,
this._editor.getModel()!.getLineMaxColumn(selection.endLineNumber - 1)
);
}
if (!selection.isEmpty()) {
return selection;
}
return null;
}).filter(element => !!element);
if (selections.length) {
this._state.change({ searchScope: selections }, true);
}
}
}
......@@ -293,9 +303,9 @@ export class CommonFindController extends Disposable implements IEditorContribut
}
if (opts.updateSearchScope) {
let currentSelection = this._editor.getSelection();
if (!currentSelection.isEmpty()) {
stateChanges.searchScope = currentSelection;
let currentSelections = this._editor.getSelections();
if (currentSelections.some(selection => !selection.isEmpty())) {
stateChanges.searchScope = currentSelections;
}
}
......
......@@ -17,7 +17,7 @@ export class FindDecorations implements IDisposable {
private readonly _editor: IActiveCodeEditor;
private _decorations: string[];
private _overviewRulerApproximateDecorations: string[];
private _findScopeDecorationId: string | null;
private _findScopeDecorationIds: string[];
private _rangeHighlightDecorationId: string | null;
private _highlightedDecorationId: string | null;
private _startPosition: Position;
......@@ -26,7 +26,7 @@ export class FindDecorations implements IDisposable {
this._editor = editor;
this._decorations = [];
this._overviewRulerApproximateDecorations = [];
this._findScopeDecorationId = null;
this._findScopeDecorationIds = [];
this._rangeHighlightDecorationId = null;
this._highlightedDecorationId = null;
this._startPosition = this._editor.getPosition();
......@@ -37,7 +37,7 @@ export class FindDecorations implements IDisposable {
this._decorations = [];
this._overviewRulerApproximateDecorations = [];
this._findScopeDecorationId = null;
this._findScopeDecorationIds = [];
this._rangeHighlightDecorationId = null;
this._highlightedDecorationId = null;
}
......@@ -45,7 +45,7 @@ export class FindDecorations implements IDisposable {
public reset(): void {
this._decorations = [];
this._overviewRulerApproximateDecorations = [];
this._findScopeDecorationId = null;
this._findScopeDecorationIds = [];
this._rangeHighlightDecorationId = null;
this._highlightedDecorationId = null;
}
......@@ -54,9 +54,22 @@ export class FindDecorations implements IDisposable {
return this._decorations.length;
}
/** @deprecated use getFindScopes to support multiple selections */
public getFindScope(): Range | null {
if (this._findScopeDecorationId) {
return this._editor.getModel().getDecorationRange(this._findScopeDecorationId);
if (this._findScopeDecorationIds[0]) {
return this._editor.getModel().getDecorationRange(this._findScopeDecorationIds[0]);
}
return null;
}
public getFindScopes(): Range[] | null {
if (this._findScopeDecorationIds.length) {
const scopes = this._findScopeDecorationIds.map(findScopeDecorationId =>
this._editor.getModel().getDecorationRange(findScopeDecorationId)
).filter(element => !!element);
if (scopes.length) {
return scopes as Range[];
}
}
return null;
}
......@@ -133,7 +146,7 @@ export class FindDecorations implements IDisposable {
return matchPosition;
}
public set(findMatches: FindMatch[], findScope: Range | null): void {
public set(findMatches: FindMatch[], findScopes: Range[] | null): void {
this._editor.changeDecorations((accessor) => {
let findMatchesOptions: ModelDecorationOptions = FindDecorations._FIND_MATCH_DECORATION;
......@@ -195,12 +208,12 @@ export class FindDecorations implements IDisposable {
}
// Find scope
if (this._findScopeDecorationId) {
accessor.removeDecoration(this._findScopeDecorationId);
this._findScopeDecorationId = null;
if (this._findScopeDecorationIds.length) {
this._findScopeDecorationIds.forEach(findScopeDecorationId => accessor.removeDecoration(findScopeDecorationId));
this._findScopeDecorationIds = [];
}
if (findScope) {
this._findScopeDecorationId = accessor.addDecoration(findScope, FindDecorations._FIND_SCOPE_DECORATION);
if (findScopes?.length) {
this._findScopeDecorationIds = findScopes.map(findScope => accessor.addDecoration(findScope, FindDecorations._FIND_SCOPE_DECORATION));
}
});
}
......@@ -253,8 +266,8 @@ export class FindDecorations implements IDisposable {
let result: string[] = [];
result = result.concat(this._decorations);
result = result.concat(this._overviewRulerApproximateDecorations);
if (this._findScopeDecorationId) {
result.push(this._findScopeDecorationId);
if (this._findScopeDecorationIds.length) {
result.push(...this._findScopeDecorationIds);
}
if (this._rangeHighlightDecorationId) {
result.push(this._rangeHighlightDecorationId);
......
......@@ -168,26 +168,36 @@ export class FindModelBoundToEditorModel {
return model.getFullModelRange();
}
private research(moveCursor: boolean, newFindScope?: Range | null): void {
let findScope: Range | null = null;
private research(moveCursor: boolean, newFindScope?: Range | Range[] | null): void {
let findScopes: Range[] | null = null;
if (typeof newFindScope !== 'undefined') {
findScope = newFindScope;
} else {
findScope = this._decorations.getFindScope();
}
if (findScope !== null) {
if (findScope.startLineNumber !== findScope.endLineNumber) {
if (findScope.endColumn === 1) {
findScope = new Range(findScope.startLineNumber, 1, findScope.endLineNumber - 1, this._editor.getModel().getLineMaxColumn(findScope.endLineNumber - 1));
if (newFindScope !== null) {
if (!Array.isArray(newFindScope)) {
findScopes = [newFindScope as Range];
} else {
// multiline find scope => expand to line starts / ends
findScope = new Range(findScope.startLineNumber, 1, findScope.endLineNumber, this._editor.getModel().getLineMaxColumn(findScope.endLineNumber));
findScopes = newFindScope;
}
}
} else {
findScopes = this._decorations.getFindScopes();
}
if (findScopes !== null) {
findScopes = findScopes.map(findScope => {
if (findScope.startLineNumber !== findScope.endLineNumber) {
let endLineNumber = findScope.endLineNumber;
let findMatches = this._findMatches(findScope, false, MATCHES_LIMIT);
this._decorations.set(findMatches, findScope);
if (findScope.endColumn === 1) {
endLineNumber = endLineNumber - 1;
}
return new Range(findScope.startLineNumber, 1, endLineNumber, this._editor.getModel().getLineMaxColumn(endLineNumber));
}
return findScope;
});
}
let findMatches = this._findMatches(findScopes, false, MATCHES_LIMIT);
this._decorations.set(findMatches, findScopes);
this._state.changeMatchInfo(
this._decorations.getCurrentMatchesPosition(this._editor.getSelection()),
......@@ -443,9 +453,12 @@ export class FindModelBoundToEditorModel {
}
}
private _findMatches(findScope: Range | null, captureMatches: boolean, limitResultCount: number): FindMatch[] {
let searchRange = FindModelBoundToEditorModel._getSearchRange(this._editor.getModel(), findScope);
return this._editor.getModel().findMatches(this._state.searchString, searchRange, this._state.isRegex, this._state.matchCase, this._state.wholeWord ? this._editor.getOption(EditorOption.wordSeparators) : null, captureMatches, limitResultCount);
private _findMatches(findScopes: Range[] | null, captureMatches: boolean, limitResultCount: number): FindMatch[] {
const searchRanges = (findScopes as [] || [null]).map((scope: Range | null) =>
FindModelBoundToEditorModel._getSearchRange(this._editor.getModel(), scope)
);
return this._editor.getModel().findMatches(this._state.searchString, searchRanges, this._state.isRegex, this._state.matchCase, this._state.wholeWord ? this._editor.getOption(EditorOption.wordSeparators) : null, captureMatches, limitResultCount);
}
public replaceAll(): void {
......@@ -453,13 +466,13 @@ export class FindModelBoundToEditorModel {
return;
}
const findScope = this._decorations.getFindScope();
const findScopes = this._decorations.getFindScopes();
if (findScope === null && this._state.matchesCount >= MATCHES_LIMIT) {
if (findScopes === null && this._state.matchesCount >= MATCHES_LIMIT) {
// Doing a replace on the entire file that is over ${MATCHES_LIMIT} matches
this._largeReplaceAll();
} else {
this._regularReplaceAll(findScope);
this._regularReplaceAll(findScopes);
}
this.research(false);
......@@ -504,10 +517,10 @@ export class FindModelBoundToEditorModel {
this._executeEditorCommand('replaceAll', command);
}
private _regularReplaceAll(findScope: Range | null): void {
private _regularReplaceAll(findScopes: Range[] | null): void {
const replacePattern = this._getReplacePattern();
// Get all the ranges (even more than the highlighted ones)
let matches = this._findMatches(findScope, replacePattern.hasReplacementPatterns || this._state.preserveCase, Constants.MAX_SAFE_SMALL_INTEGER);
let matches = this._findMatches(findScopes, replacePattern.hasReplacementPatterns || this._state.preserveCase, Constants.MAX_SAFE_SMALL_INTEGER);
let replaceStrings: string[] = [];
for (let i = 0, len = matches.length; i < len; i++) {
......@@ -523,10 +536,10 @@ export class FindModelBoundToEditorModel {
return;
}
let findScope = this._decorations.getFindScope();
let findScopes = this._decorations.getFindScopes();
// Get all the ranges (even more than the highlighted ones)
let matches = this._findMatches(findScope, false, Constants.MAX_SAFE_SMALL_INTEGER);
let matches = this._findMatches(findScopes, false, Constants.MAX_SAFE_SMALL_INTEGER);
let selections = matches.map(m => new Selection(m.range.startLineNumber, m.range.startColumn, m.range.endLineNumber, m.range.endColumn));
// If one of the ranges is the editor selection, then maintain it as primary
......
......@@ -46,7 +46,7 @@ export interface INewFindReplaceState {
matchCaseOverride?: FindOptionOverride;
preserveCase?: boolean;
preserveCaseOverride?: FindOptionOverride;
searchScope?: Range | null;
searchScope?: Range[] | null;
loop?: boolean;
}
......@@ -73,7 +73,7 @@ export class FindReplaceState extends Disposable {
private _matchCaseOverride: FindOptionOverride;
private _preserveCase: boolean;
private _preserveCaseOverride: FindOptionOverride;
private _searchScope: Range | null;
private _searchScope: Range[] | null;
private _matchesPosition: number;
private _matchesCount: number;
private _currentMatch: Range | null;
......@@ -94,7 +94,7 @@ export class FindReplaceState extends Disposable {
public get actualMatchCase(): boolean { return this._matchCase; }
public get actualPreserveCase(): boolean { return this._preserveCase; }
public get searchScope(): Range | null { return this._searchScope; }
public get searchScope(): Range[] | null { return this._searchScope; }
public get matchesPosition(): number { return this._matchesPosition; }
public get matchesCount(): number { return this._matchesCount; }
public get currentMatch(): Range | null { return this._currentMatch; }
......@@ -238,7 +238,11 @@ export class FindReplaceState extends Disposable {
this._preserveCase = newState.preserveCase;
}
if (typeof newState.searchScope !== 'undefined') {
if (!Range.equalsRange(this._searchScope, newState.searchScope)) {
if (!newState.searchScope?.every((newSearchScope) => {
return this._searchScope?.some(existingSearchScope => {
return !Range.equalsRange(existingSearchScope, newSearchScope);
});
})) {
this._searchScope = newState.searchScope;
changeEvent.searchScope = true;
somethingChanged = true;
......
......@@ -803,16 +803,26 @@ export class FindWidget extends Widget implements IOverlayWidget, IVerticalSashL
}
if (this._toggleSelectionFind.checked) {
let selection = this._codeEditor.getSelection();
if (selection.endColumn === 1 && selection.endLineNumber > selection.startLineNumber) {
selection = selection.setEndPosition(selection.endLineNumber - 1, this._codeEditor.getModel().getLineMaxColumn(selection.endLineNumber - 1));
}
const currentMatch = this._state.currentMatch;
if (selection.startLineNumber !== selection.endLineNumber) {
if (!Range.equalsRange(selection, currentMatch)) {
// Reseed find scope
this._state.change({ searchScope: selection }, true);
let selections = this._codeEditor.getSelections();
selections.map(selection => {
if (selection.endColumn === 1 && selection.endLineNumber > selection.startLineNumber) {
selection = selection.setEndPosition(
selection.endLineNumber - 1,
this._codeEditor.getModel()!.getLineMaxColumn(selection.endLineNumber - 1)
);
}
const currentMatch = this._state.currentMatch;
if (selection.startLineNumber !== selection.endLineNumber) {
if (!Range.equalsRange(selection, currentMatch)) {
return selection;
}
}
return null;
}).filter(element => !!element);
if (selections.length) {
this._state.change({ searchScope: selections as Range[] }, true);
}
}
}
......@@ -1027,12 +1037,19 @@ export class FindWidget extends Widget implements IOverlayWidget, IVerticalSashL
this._register(this._toggleSelectionFind.onChange(() => {
if (this._toggleSelectionFind.checked) {
if (this._codeEditor.hasModel()) {
let selection = this._codeEditor.getSelection();
if (selection.endColumn === 1 && selection.endLineNumber > selection.startLineNumber) {
selection = selection.setEndPosition(selection.endLineNumber - 1, this._codeEditor.getModel().getLineMaxColumn(selection.endLineNumber - 1));
}
if (!selection.isEmpty()) {
this._state.change({ searchScope: selection }, true);
let selections = this._codeEditor.getSelections();
selections.map(selection => {
if (selection.endColumn === 1 && selection.endLineNumber > selection.startLineNumber) {
selection = selection.setEndPosition(selection.endLineNumber - 1, this._codeEditor.getModel()!.getLineMaxColumn(selection.endLineNumber - 1));
}
if (!selection.isEmpty()) {
return selection;
}
return null;
}).filter(element => !!element);
if (selections.length) {
this._state.change({ searchScope: selections as Range[] }, true);
}
}
} else {
......
......@@ -309,10 +309,10 @@ suite('FindController', () => {
assert.equal(findController.getState().searchScope, null);
findController.getState().change({
searchScope: new Range(1, 1, 1, 5)
searchScope: [new Range(1, 1, 1, 5)]
}, false);
assert.deepEqual(findController.getState().searchScope, new Range(1, 1, 1, 5));
assert.deepEqual(findController.getState().searchScope, [new Range(1, 1, 1, 5)]);
findController.closeFindWidget();
assert.equal(findController.getState().searchScope, null);
......@@ -523,10 +523,8 @@ suite('FindController query options persistence', () => {
'var z = (3 * 5)',
], { serviceCollection: serviceCollection, find: { autoFindInSelection: 'always', globalFindClipboard: false } }, (editor) => {
// clipboardState = '';
editor.setSelection(new Range(1, 1, 2, 1));
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
findController.start({
const findConfig = {
forceRevealReplace: false,
seedSearchStringFromSelection: false,
seedSearchStringFromGlobalClipboard: false,
......@@ -534,9 +532,17 @@ suite('FindController query options persistence', () => {
shouldAnimate: false,
updateSearchScope: true,
loop: true
});
};
editor.setSelection(new Range(1, 1, 2, 1));
findController.start(findConfig);
assert.deepEqual(findController.getState().searchScope, [new Selection(1, 1, 2, 1)]);
findController.closeFindWidget();
assert.deepEqual(findController.getState().searchScope, new Selection(1, 1, 2, 1));
editor.setSelections([new Selection(1, 1, 2, 1), new Selection(2, 1, 2, 5)]);
findController.start(findConfig);
assert.deepEqual(findController.getState().searchScope, [new Selection(1, 1, 2, 1), new Selection(2, 1, 2, 5)]);
});
});
......@@ -584,7 +590,7 @@ suite('FindController query options persistence', () => {
loop: true
});
assert.deepEqual(findController.getState().searchScope, new Selection(1, 2, 1, 3));
assert.deepEqual(findController.getState().searchScope, [new Selection(1, 2, 1, 3)]);
});
});
......@@ -609,7 +615,7 @@ suite('FindController query options persistence', () => {
loop: true
});
assert.deepEqual(findController.getState().searchScope, new Selection(1, 6, 2, 1));
assert.deepEqual(findController.getState().searchScope, [new Selection(1, 6, 2, 1)]);
});
});
});
......@@ -210,7 +210,7 @@ suite('FindModel', () => {
);
// simulate adding a search scope
findState.change({ searchScope: new Range(8, 1, 10, 1) }, true);
findState.change({ searchScope: [new Range(8, 1, 10, 1)] }, true);
assertFindState(
editor,
[8, 14, 8, 19],
......@@ -443,7 +443,7 @@ suite('FindModel', () => {
findTest('find model next stays in scope', (editor) => {
let findState = new FindReplaceState();
findState.change({ searchString: 'hello', wholeWord: true, searchScope: new Range(7, 1, 9, 1) }, false);
findState.change({ searchString: 'hello', wholeWord: true, searchScope: [new Range(7, 1, 9, 1)] }, false);
let findModel = new FindModelBoundToEditorModel(editor, findState);
assertFindState(
......@@ -493,6 +493,79 @@ suite('FindModel', () => {
findState.dispose();
});
findTest('multi-selection find model next stays in scope', (editor) => {
let findState = new FindReplaceState();
findState.change({ searchString: 'hello', matchCase: true, wholeWord: false, searchScope: [new Range(6, 1, 7, 38), new Range(9, 3, 9, 38)] }, false);
let findModel = new FindModelBoundToEditorModel(editor, findState);
assertFindState(
editor,
[1, 1, 1, 1],
null,
[
[6, 14, 6, 19],
// `matchCase: false` would
// find this match as well:
// [6, 27, 6, 32],
[7, 14, 7, 19],
// `wholeWord: true` would
// exclude this match:
[9, 14, 9, 19],
]
);
findModel.moveToNextMatch();
assertFindState(
editor,
[6, 14, 6, 19],
[6, 14, 6, 19],
[
[6, 14, 6, 19],
[7, 14, 7, 19],
[9, 14, 9, 19],
]
);
findModel.moveToNextMatch();
assertFindState(
editor,
[7, 14, 7, 19],
[7, 14, 7, 19],
[
[6, 14, 6, 19],
[7, 14, 7, 19],
[9, 14, 9, 19],
]
);
findModel.moveToNextMatch();
assertFindState(
editor,
[9, 14, 9, 19],
[9, 14, 9, 19],
[
[6, 14, 6, 19],
[7, 14, 7, 19],
[9, 14, 9, 19],
]
);
findModel.moveToNextMatch();
assertFindState(
editor,
[6, 14, 6, 19],
[6, 14, 6, 19],
[
[6, 14, 6, 19],
[7, 14, 7, 19],
[9, 14, 9, 19],
]
);
findModel.dispose();
findState.dispose();
});
findTest('find model prev', (editor) => {
let findState = new FindReplaceState();
findState.change({ searchString: 'hello', wholeWord: true }, false);
......@@ -581,7 +654,7 @@ suite('FindModel', () => {
findTest('find model prev stays in scope', (editor) => {
let findState = new FindReplaceState();
findState.change({ searchString: 'hello', wholeWord: true, searchScope: new Range(7, 1, 9, 1) }, false);
findState.change({ searchString: 'hello', wholeWord: true, searchScope: [new Range(7, 1, 9, 1)] }, false);
let findModel = new FindModelBoundToEditorModel(editor, findState);
assertFindState(
......@@ -2073,7 +2146,7 @@ suite('FindModel', () => {
findTest('issue #27083. search scope works even if it is a single line', (editor) => {
let findState = new FindReplaceState();
findState.change({ searchString: 'hello', wholeWord: true, searchScope: new Range(7, 1, 8, 1) }, false);
findState.change({ searchString: 'hello', wholeWord: true, searchScope: [new Range(7, 1, 8, 1)] }, false);
let findModel = new FindModelBoundToEditorModel(editor, findState);
assertFindState(
......
......@@ -601,13 +601,15 @@ export class MultiCursorSelectionController extends Disposable implements IEdito
}
if (findState.searchScope) {
const state = findState.searchScope;
const states = findState.searchScope;
let inSelection: FindMatch[] | null = [];
for (let i = 0; i < matches.length; i++) {
if (matches[i].range.endLineNumber <= state.endLineNumber && matches[i].range.startLineNumber >= state.startLineNumber) {
inSelection.push(matches[i]);
}
}
matches.forEach((match) => {
states.forEach((state) => {
if (match.range.endLineNumber <= state.endLineNumber && match.range.startLineNumber >= state.startLineNumber) {
inSelection!.push(match);
}
});
});
matches = inSelection;
}
......
......@@ -1758,7 +1758,7 @@ declare namespace monaco.editor {
/**
* Search the model.
* @param searchString The string used to search. If it is a regular expression, set `isRegex` to true.
* @param searchScope Limit the searching to only search inside this range.
* @param searchScope Limit the searching to only search inside these ranges.
* @param isRegex Used to indicate that `searchString` is a regular expression.
* @param matchCase Force the matching to match lower/upper case exactly.
* @param wordSeparators Force the matching to match entire words only. Pass null otherwise.
......@@ -1766,7 +1766,7 @@ declare namespace monaco.editor {
* @param limitResultCount Limit the number of results
* @return The ranges where the matches are. It is empty if no matches have been found.
*/
findMatches(searchString: string, searchScope: IRange, isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean, limitResultCount?: number): FindMatch[];
findMatches(searchString: string, searchScope: IRange | IRange[], isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean, limitResultCount?: number): FindMatch[];
/**
* Search the model for the next match. Loops to the beginning of the model if needed.
* @param searchString The string used to search. If it is a regular expression, set `isRegex` to true.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册