Path: blob/main/src/vs/editor/contrib/smartSelect/browser/wordSelections.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { CharCode } from '../../../../base/common/charCode.js';6import { isLowerAsciiLetter, isUpperAsciiLetter } from '../../../../base/common/strings.js';7import { Position } from '../../../common/core/position.js';8import { Range } from '../../../common/core/range.js';9import { ITextModel } from '../../../common/model.js';10import { SelectionRange, SelectionRangeProvider } from '../../../common/languages.js';1112export class WordSelectionRangeProvider implements SelectionRangeProvider {1314constructor(private readonly selectSubwords = true) { }1516provideSelectionRanges(model: ITextModel, positions: Position[]): SelectionRange[][] {17const result: SelectionRange[][] = [];18for (const position of positions) {19const bucket: SelectionRange[] = [];20result.push(bucket);21if (this.selectSubwords) {22this._addInWordRanges(bucket, model, position);23}24this._addWordRanges(bucket, model, position);25this._addWhitespaceLine(bucket, model, position);26bucket.push({ range: model.getFullModelRange() });27}28return result;29}3031private _addInWordRanges(bucket: SelectionRange[], model: ITextModel, pos: Position): void {32const obj = model.getWordAtPosition(pos);33if (!obj) {34return;35}3637const { word, startColumn } = obj;38const offset = pos.column - startColumn;39let start = offset;40let end = offset;41let lastCh: number = 0;4243// LEFT anchor (start)44for (; start >= 0; start--) {45const ch = word.charCodeAt(start);46if ((start !== offset) && (ch === CharCode.Underline || ch === CharCode.Dash)) {47// foo-bar OR foo_bar48break;49} else if (isLowerAsciiLetter(ch) && isUpperAsciiLetter(lastCh)) {50// fooBar51break;52}53lastCh = ch;54}55start += 1;5657// RIGHT anchor (end)58for (; end < word.length; end++) {59const ch = word.charCodeAt(end);60if (isUpperAsciiLetter(ch) && isLowerAsciiLetter(lastCh)) {61// fooBar62break;63} else if (ch === CharCode.Underline || ch === CharCode.Dash) {64// foo-bar OR foo_bar65break;66}67lastCh = ch;68}6970if (start < end) {71bucket.push({ range: new Range(pos.lineNumber, startColumn + start, pos.lineNumber, startColumn + end) });72}73}7475private _addWordRanges(bucket: SelectionRange[], model: ITextModel, pos: Position): void {76const word = model.getWordAtPosition(pos);77if (word) {78bucket.push({ range: new Range(pos.lineNumber, word.startColumn, pos.lineNumber, word.endColumn) });79}80}8182private _addWhitespaceLine(bucket: SelectionRange[], model: ITextModel, pos: Position): void {83if (model.getLineLength(pos.lineNumber) > 084&& model.getLineFirstNonWhitespaceColumn(pos.lineNumber) === 085&& model.getLineLastNonWhitespaceColumn(pos.lineNumber) === 086) {87bucket.push({ range: new Range(pos.lineNumber, 1, pos.lineNumber, model.getLineMaxColumn(pos.lineNumber)) });88}89}90}919293