Skip to content

Commit

Permalink
add word based provider #64004, add multi-provider merge logic #63935
Browse files Browse the repository at this point in the history
  • Loading branch information
jrieken committed Nov 30, 2018
1 parent aa3ea85 commit 4b7614f
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 6 deletions.
3 changes: 2 additions & 1 deletion src/tsconfig.strictNullChecks.json
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@
"./vs/editor/contrib/rename/rename.ts",
"./vs/editor/contrib/rename/renameInputField.ts",
"./vs/editor/contrib/smartSelect/smartSelect.ts",
"./vs/editor/contrib/smartSelect/wordSelections.ts",
"./vs/editor/contrib/smartSelect/tokenTree.ts",
"./vs/editor/contrib/snippet/snippetParser.ts",
"./vs/editor/contrib/snippet/snippetVariables.ts",
Expand Down Expand Up @@ -731,4 +732,4 @@
"exclude": [
"./typings/require-monaco.d.ts"
]
}
}
62 changes: 57 additions & 5 deletions src/vs/editor/contrib/smartSelect/smartSelect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/

import * as arrays from 'vs/base/common/arrays';
import { asThenable, first } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
Expand All @@ -20,6 +19,7 @@ import { MenuId } from 'vs/platform/actions/common/actions';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { TokenTreeSelectionRangeProvider } from 'vs/editor/contrib/smartSelect/tokenTree';
import { WordSelectionRangeProvider } from 'vs/editor/contrib/smartSelect/wordSelections';

class SelectionRanges {

Expand Down Expand Up @@ -200,9 +200,61 @@ registerEditorContribution(SmartSelectController);
registerEditorAction(GrowSelectionAction);
registerEditorAction(ShrinkSelectionAction);

modes.SelectionRangeRegistry.register('*', new WordSelectionRangeProvider());
modes.SelectionRangeRegistry.register('*', new TokenTreeSelectionRangeProvider());

export function provideSelectionRanges(model: ITextModel, position: Position, token: CancellationToken): Promise<Range[] | undefined | null> {
const provider = modes.SelectionRangeRegistry.ordered(model);
return first(provider.map(pro => () => asThenable(() => pro.provideSelectionRanges(model, position, token))), arrays.isNonEmptyArray);
}

modes.SelectionRangeRegistry.register('*', new TokenTreeSelectionRangeProvider());
const provider = modes.SelectionRangeRegistry.orderedGroups(model);

interface RankedRange {
rank: number;
range: Range;
}

let work: Promise<any>[] = [];
let ranges: RankedRange[] = [];
let rank = 0;

for (const group of provider) {
rank += 1;
for (const prov of group) {
work.push(Promise.resolve(prov.provideSelectionRanges(model, position, token)).then(res => {
if (arrays.isNonEmptyArray(res)) {
for (const range of res) {
if (Range.isIRange(range) && Range.containsPosition(range, position)) {
ranges.push({ range, rank });
}
}
}
}));
}
}

return Promise.all(work).then(() => {
ranges.sort((a, b) => {
if (Position.isBefore(a.range.getStartPosition(), b.range.getStartPosition())) {
return 1;
} else if (Position.isBefore(b.range.getStartPosition(), a.range.getStartPosition())) {
return -1;
} else if (Position.isBefore(a.range.getEndPosition(), b.range.getEndPosition())) {
return -1;
} else if (Position.isBefore(b.range.getEndPosition(), a.range.getEndPosition())) {
return 1;
} else {
return b.rank - a.rank;
}
});

// ranges.sort((a, b) => Range.compareRangesUsingStarts(b.range, a.range));
let result: Range[] = [];
let last: Range | undefined;
for (const { range } of ranges) {
if (!last || Range.containsRange(range, last)) {
result.push(range);
last = range;
}
}
return result;
});
}
31 changes: 31 additions & 0 deletions src/vs/editor/contrib/smartSelect/wordSelections.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { SelectionRangeProvider } from 'vs/editor/common/modes';
import { ITextModel } from 'vs/editor/common/model';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';

export class WordSelectionRangeProvider implements SelectionRangeProvider {

provideSelectionRanges(model: ITextModel, position: Position): Range[] {
let result: Range[] = [];
this._addWordRanges(result, model, position);
this._addLineRanges(result, model, position);
return result;
}

private _addWordRanges(bucket: Range[], model: ITextModel, pos: Position): void {
const word = model.getWordAtPosition(pos);
if (word) {
bucket.push(new Range(pos.lineNumber, word.startColumn, pos.lineNumber, word.endColumn));
}
}

private _addLineRanges(bucket: Range[], model: ITextModel, pos: Position): void {
bucket.push(new Range(pos.lineNumber, model.getLineFirstNonWhitespaceColumn(pos.lineNumber), pos.lineNumber, model.getLineLastNonWhitespaceColumn(pos.lineNumber)));
bucket.push(new Range(pos.lineNumber, model.getLineMinColumn(pos.lineNumber), pos.lineNumber, model.getLineMaxColumn(pos.lineNumber)));
}
}

0 comments on commit 4b7614f

Please sign in to comment.