Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/contrib/smartSelect/browser/wordSelections.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { CharCode } from '../../../../base/common/charCode.js';
7
import { isLowerAsciiLetter, isUpperAsciiLetter } from '../../../../base/common/strings.js';
8
import { Position } from '../../../common/core/position.js';
9
import { Range } from '../../../common/core/range.js';
10
import { ITextModel } from '../../../common/model.js';
11
import { SelectionRange, SelectionRangeProvider } from '../../../common/languages.js';
12
13
export class WordSelectionRangeProvider implements SelectionRangeProvider {
14
15
constructor(private readonly selectSubwords = true) { }
16
17
provideSelectionRanges(model: ITextModel, positions: Position[]): SelectionRange[][] {
18
const result: SelectionRange[][] = [];
19
for (const position of positions) {
20
const bucket: SelectionRange[] = [];
21
result.push(bucket);
22
if (this.selectSubwords) {
23
this._addInWordRanges(bucket, model, position);
24
}
25
this._addWordRanges(bucket, model, position);
26
this._addWhitespaceLine(bucket, model, position);
27
bucket.push({ range: model.getFullModelRange() });
28
}
29
return result;
30
}
31
32
private _addInWordRanges(bucket: SelectionRange[], model: ITextModel, pos: Position): void {
33
const obj = model.getWordAtPosition(pos);
34
if (!obj) {
35
return;
36
}
37
38
const { word, startColumn } = obj;
39
const offset = pos.column - startColumn;
40
let start = offset;
41
let end = offset;
42
let lastCh: number = 0;
43
44
// LEFT anchor (start)
45
for (; start >= 0; start--) {
46
const ch = word.charCodeAt(start);
47
if ((start !== offset) && (ch === CharCode.Underline || ch === CharCode.Dash)) {
48
// foo-bar OR foo_bar
49
break;
50
} else if (isLowerAsciiLetter(ch) && isUpperAsciiLetter(lastCh)) {
51
// fooBar
52
break;
53
}
54
lastCh = ch;
55
}
56
start += 1;
57
58
// RIGHT anchor (end)
59
for (; end < word.length; end++) {
60
const ch = word.charCodeAt(end);
61
if (isUpperAsciiLetter(ch) && isLowerAsciiLetter(lastCh)) {
62
// fooBar
63
break;
64
} else if (ch === CharCode.Underline || ch === CharCode.Dash) {
65
// foo-bar OR foo_bar
66
break;
67
}
68
lastCh = ch;
69
}
70
71
if (start < end) {
72
bucket.push({ range: new Range(pos.lineNumber, startColumn + start, pos.lineNumber, startColumn + end) });
73
}
74
}
75
76
private _addWordRanges(bucket: SelectionRange[], model: ITextModel, pos: Position): void {
77
const word = model.getWordAtPosition(pos);
78
if (word) {
79
bucket.push({ range: new Range(pos.lineNumber, word.startColumn, pos.lineNumber, word.endColumn) });
80
}
81
}
82
83
private _addWhitespaceLine(bucket: SelectionRange[], model: ITextModel, pos: Position): void {
84
if (model.getLineLength(pos.lineNumber) > 0
85
&& model.getLineFirstNonWhitespaceColumn(pos.lineNumber) === 0
86
&& model.getLineLastNonWhitespaceColumn(pos.lineNumber) === 0
87
) {
88
bucket.push({ range: new Range(pos.lineNumber, 1, pos.lineNumber, model.getLineMaxColumn(pos.lineNumber)) });
89
}
90
}
91
}
92
93