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 { CursorColumns } from '../core/cursorColumns.js';
8
>
9
>
export const enum Direction {
10
>
Left,
11
>
Right,
12
>
Nearest,
13
>
}
14
>
15
>
export class AtomicTabMoveOperations {
16
>
/**
17
>
* Get the visible column at the position. If we get to a non-whitespace character first
18
>
* or past the end of string then return -1.
19
>
*
20
>
* **Note** `position` and the return value are 0-based.
21
>
*/
22
>
public static whitespaceVisibleColumn(lineContent: string, position: number, tabSize: number): [number, number, number] {
23
>
const lineLength = lineContent.length;
24
>
let visibleColumn = 0;
25
>
let prevTabStopPosition = -1;
26
>
let prevTabStopVisibleColumn = -1;
27
>
for (let i = 0; i < lineLength; i++) {
28
>
if (i === position) {
29
>
return [prevTabStopPosition, prevTabStopVisibleColumn, visibleColumn];
30
>
}
31
>
if (visibleColumn % tabSize === 0) {
32
>
prevTabStopPosition = i;
33
>
prevTabStopVisibleColumn = visibleColumn;
34
>
}
35
>
const chCode = lineContent.charCodeAt(i);
36
>
switch (chCode) {
37
>
case CharCode.Space:
38
>
visibleColumn += 1;
39
>
break;
40
>
case CharCode.Tab:
41
>
// Skip to the next multiple of tabSize.
42
>
visibleColumn = CursorColumns.nextRenderTabStop(visibleColumn, tabSize);
43
>
break;
44
>
default:
45
>
return [-1, -1, -1];
46
>
}
47
>
}
48
>
if (position === lineLength) {
49
>
return [prevTabStopPosition, prevTabStopVisibleColumn, visibleColumn];
50
>
}
51
>
return [-1, -1, -1];
52
>
}
53
>
54
>
/**
55
>
* Return the position that should result from a move left, right or to the
56
>
* nearest tab, if atomic tabs are enabled. Left and right are used for the
57
>
* arrow key movements, nearest is used for mouse selection. It returns
58
>
* -1 if atomic tabs are not relevant and you should fall back to normal
59
>
* behaviour.
60
>
*
61
>
* **Note**: `position` and the return value are 0-based.
62
>
*/
63
>
public static atomicPosition(lineContent: string, position: number, tabSize: number, direction: Direction): number {
64
const lineLength = lineContent.length;
65