mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-15 10:58:31 -05:00
* Merge from vscode 504f934659740e9d41501cad9f162b54d7745ad9 * delete unused folders * distro * Bump build node version * update chokidar * FIx hygiene errors * distro * Fix extension lint issues * Remove strict-vscode * Add copyright header exemptions * Bump vscode-extension-telemetry to fix webpacking issue with zone.js * distro * Fix failing tests (revert marked.js back to current one until we decide to update) * Skip searchmodel test * Fix mac build * temp debug script loading * Try disabling coverage * log error too * Revert "log error too" This reverts commit af0183e5d4ab458fdf44b88fbfab9908d090526f. * Revert "temp debug script loading" This reverts commit 3d687d541c76db2c5b55626c78ae448d3c25089c. * Add comments explaining coverage disabling * Fix ansi_up loading issue * Merge latest from ads * Use newer option * Fix compile * add debug logging warn * Always log stack * log more * undo debug * Update to use correct base path (+cleanup) * distro * fix compile errors * Remove strict-vscode * Fix sql editors not showing * Show db dropdown input & fix styling * Fix more info in gallery * Fix gallery asset requests * Delete unused workflow * Fix tapable resolutions for smoke test compile error * Fix smoke compile * Disable crash reporting * Disable interactive Co-authored-by: ADS Merger <karlb@microsoft.com>
347 lines
15 KiB
TypeScript
347 lines
15 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import { CursorColumns, CursorConfiguration, ICursorSimpleModel, SingleCursorState } from 'vs/editor/common/controller/cursorCommon';
|
|
import { Position } from 'vs/editor/common/core/position';
|
|
import { Range } from 'vs/editor/common/core/range';
|
|
import * as strings from 'vs/base/common/strings';
|
|
import { Constants } from 'vs/base/common/uint';
|
|
import { AtomicTabMoveOperations, Direction } from 'vs/editor/common/controller/cursorAtomicMoveOperations';
|
|
import { PositionAffinity } from 'vs/editor/common/model';
|
|
|
|
export class CursorPosition {
|
|
_cursorPositionBrand: void = undefined;
|
|
|
|
public readonly lineNumber: number;
|
|
public readonly column: number;
|
|
public readonly leftoverVisibleColumns: number;
|
|
|
|
constructor(lineNumber: number, column: number, leftoverVisibleColumns: number) {
|
|
this.lineNumber = lineNumber;
|
|
this.column = column;
|
|
this.leftoverVisibleColumns = leftoverVisibleColumns;
|
|
}
|
|
}
|
|
|
|
export class MoveOperations {
|
|
public static leftPosition(model: ICursorSimpleModel, position: Position): Position {
|
|
if (position.column > model.getLineMinColumn(position.lineNumber)) {
|
|
return position.delta(undefined, -strings.prevCharLength(model.getLineContent(position.lineNumber), position.column - 1));
|
|
} else if (position.lineNumber > 1) {
|
|
const newLineNumber = position.lineNumber - 1;
|
|
return new Position(newLineNumber, model.getLineMaxColumn(newLineNumber));
|
|
} else {
|
|
return position;
|
|
}
|
|
}
|
|
|
|
private static leftPositionAtomicSoftTabs(model: ICursorSimpleModel, position: Position, tabSize: number): Position {
|
|
if (position.column <= model.getLineIndentColumn(position.lineNumber)) {
|
|
const minColumn = model.getLineMinColumn(position.lineNumber);
|
|
const lineContent = model.getLineContent(position.lineNumber);
|
|
const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, position.column - 1, tabSize, Direction.Left);
|
|
if (newPosition !== -1 && newPosition + 1 >= minColumn) {
|
|
return new Position(position.lineNumber, newPosition + 1);
|
|
}
|
|
}
|
|
return this.leftPosition(model, position);
|
|
}
|
|
|
|
private static left(config: CursorConfiguration, model: ICursorSimpleModel, position: Position): CursorPosition {
|
|
const pos = config.stickyTabStops
|
|
? MoveOperations.leftPositionAtomicSoftTabs(model, position, config.tabSize)
|
|
: MoveOperations.leftPosition(model, position);
|
|
return new CursorPosition(pos.lineNumber, pos.column, 0);
|
|
}
|
|
|
|
/**
|
|
* @param noOfColumns Must be either `1`
|
|
* or `Math.round(viewModel.getLineContent(viewLineNumber).length / 2)` (for half lines).
|
|
*/
|
|
public static moveLeft(config: CursorConfiguration, model: ICursorSimpleModel, cursor: SingleCursorState, inSelectionMode: boolean, noOfColumns: number): SingleCursorState {
|
|
let lineNumber: number,
|
|
column: number;
|
|
|
|
if (cursor.hasSelection() && !inSelectionMode) {
|
|
// If the user has a selection and does not want to extend it,
|
|
// put the cursor at the beginning of the selection.
|
|
lineNumber = cursor.selection.startLineNumber;
|
|
column = cursor.selection.startColumn;
|
|
} else {
|
|
// This has no effect if noOfColumns === 1.
|
|
// It is ok to do so in the half-line scenario.
|
|
const pos = cursor.position.delta(undefined, -(noOfColumns - 1));
|
|
// We clip the position before normalization, as normalization is not defined
|
|
// for possibly negative columns.
|
|
const normalizedPos = model.normalizePosition(MoveOperations.clipPositionColumn(pos, model), PositionAffinity.Left);
|
|
const p = MoveOperations.left(config, model, normalizedPos);
|
|
|
|
lineNumber = p.lineNumber;
|
|
column = p.column;
|
|
}
|
|
|
|
return cursor.move(inSelectionMode, lineNumber, column, 0);
|
|
}
|
|
|
|
/**
|
|
* Adjusts the column so that it is within min/max of the line.
|
|
*/
|
|
private static clipPositionColumn(position: Position, model: ICursorSimpleModel): Position {
|
|
return new Position(
|
|
position.lineNumber,
|
|
MoveOperations.clipRange(position.column, model.getLineMinColumn(position.lineNumber),
|
|
model.getLineMaxColumn(position.lineNumber))
|
|
);
|
|
}
|
|
|
|
private static clipRange(value: number, min: number, max: number): number {
|
|
if (value < min) {
|
|
return min;
|
|
}
|
|
if (value > max) {
|
|
return max;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
public static rightPosition(model: ICursorSimpleModel, lineNumber: number, column: number): Position {
|
|
if (column < model.getLineMaxColumn(lineNumber)) {
|
|
column = column + strings.nextCharLength(model.getLineContent(lineNumber), column - 1);
|
|
} else if (lineNumber < model.getLineCount()) {
|
|
lineNumber = lineNumber + 1;
|
|
column = model.getLineMinColumn(lineNumber);
|
|
}
|
|
return new Position(lineNumber, column);
|
|
}
|
|
|
|
public static rightPositionAtomicSoftTabs(model: ICursorSimpleModel, lineNumber: number, column: number, tabSize: number, indentSize: number): Position {
|
|
if (column < model.getLineIndentColumn(lineNumber)) {
|
|
const lineContent = model.getLineContent(lineNumber);
|
|
const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, column - 1, tabSize, Direction.Right);
|
|
if (newPosition !== -1) {
|
|
return new Position(lineNumber, newPosition + 1);
|
|
}
|
|
}
|
|
return this.rightPosition(model, lineNumber, column);
|
|
}
|
|
|
|
public static right(config: CursorConfiguration, model: ICursorSimpleModel, position: Position): CursorPosition {
|
|
const pos = config.stickyTabStops
|
|
? MoveOperations.rightPositionAtomicSoftTabs(model, position.lineNumber, position.column, config.tabSize, config.indentSize)
|
|
: MoveOperations.rightPosition(model, position.lineNumber, position.column);
|
|
return new CursorPosition(pos.lineNumber, pos.column, 0);
|
|
}
|
|
|
|
public static moveRight(config: CursorConfiguration, model: ICursorSimpleModel, cursor: SingleCursorState, inSelectionMode: boolean, noOfColumns: number): SingleCursorState {
|
|
let lineNumber: number,
|
|
column: number;
|
|
|
|
if (cursor.hasSelection() && !inSelectionMode) {
|
|
// If we are in selection mode, move right without selection cancels selection and puts cursor at the end of the selection
|
|
lineNumber = cursor.selection.endLineNumber;
|
|
column = cursor.selection.endColumn;
|
|
} else {
|
|
const pos = cursor.position.delta(undefined, noOfColumns - 1);
|
|
const normalizedPos = model.normalizePosition(MoveOperations.clipPositionColumn(pos, model), PositionAffinity.Right);
|
|
const r = MoveOperations.right(config, model, normalizedPos);
|
|
lineNumber = r.lineNumber;
|
|
column = r.column;
|
|
}
|
|
|
|
return cursor.move(inSelectionMode, lineNumber, column, 0);
|
|
}
|
|
|
|
public static down(config: CursorConfiguration, model: ICursorSimpleModel, lineNumber: number, column: number, leftoverVisibleColumns: number, count: number, allowMoveOnLastLine: boolean): CursorPosition {
|
|
const currentVisibleColumn = CursorColumns.visibleColumnFromColumn(model.getLineContent(lineNumber), column, config.tabSize) + leftoverVisibleColumns;
|
|
const lineCount = model.getLineCount();
|
|
const wasOnLastPosition = (lineNumber === lineCount && column === model.getLineMaxColumn(lineNumber));
|
|
|
|
lineNumber = lineNumber + count;
|
|
if (lineNumber > lineCount) {
|
|
lineNumber = lineCount;
|
|
if (allowMoveOnLastLine) {
|
|
column = model.getLineMaxColumn(lineNumber);
|
|
} else {
|
|
column = Math.min(model.getLineMaxColumn(lineNumber), column);
|
|
}
|
|
} else {
|
|
column = CursorColumns.columnFromVisibleColumn2(config, model, lineNumber, currentVisibleColumn);
|
|
}
|
|
|
|
if (wasOnLastPosition) {
|
|
leftoverVisibleColumns = 0;
|
|
} else {
|
|
leftoverVisibleColumns = currentVisibleColumn - CursorColumns.visibleColumnFromColumn(model.getLineContent(lineNumber), column, config.tabSize);
|
|
}
|
|
|
|
return new CursorPosition(lineNumber, column, leftoverVisibleColumns);
|
|
}
|
|
|
|
public static moveDown(config: CursorConfiguration, model: ICursorSimpleModel, cursor: SingleCursorState, inSelectionMode: boolean, linesCount: number): SingleCursorState {
|
|
let lineNumber: number,
|
|
column: number;
|
|
|
|
if (cursor.hasSelection() && !inSelectionMode) {
|
|
// If we are in selection mode, move down acts relative to the end of selection
|
|
lineNumber = cursor.selection.endLineNumber;
|
|
column = cursor.selection.endColumn;
|
|
} else {
|
|
lineNumber = cursor.position.lineNumber;
|
|
column = cursor.position.column;
|
|
}
|
|
|
|
let r = MoveOperations.down(config, model, lineNumber, column, cursor.leftoverVisibleColumns, linesCount, true);
|
|
|
|
return cursor.move(inSelectionMode, r.lineNumber, r.column, r.leftoverVisibleColumns);
|
|
}
|
|
|
|
public static translateDown(config: CursorConfiguration, model: ICursorSimpleModel, cursor: SingleCursorState): SingleCursorState {
|
|
let selection = cursor.selection;
|
|
|
|
let selectionStart = MoveOperations.down(config, model, selection.selectionStartLineNumber, selection.selectionStartColumn, cursor.selectionStartLeftoverVisibleColumns, 1, false);
|
|
let position = MoveOperations.down(config, model, selection.positionLineNumber, selection.positionColumn, cursor.leftoverVisibleColumns, 1, false);
|
|
|
|
return new SingleCursorState(
|
|
new Range(selectionStart.lineNumber, selectionStart.column, selectionStart.lineNumber, selectionStart.column),
|
|
selectionStart.leftoverVisibleColumns,
|
|
new Position(position.lineNumber, position.column),
|
|
position.leftoverVisibleColumns
|
|
);
|
|
}
|
|
|
|
public static up(config: CursorConfiguration, model: ICursorSimpleModel, lineNumber: number, column: number, leftoverVisibleColumns: number, count: number, allowMoveOnFirstLine: boolean): CursorPosition {
|
|
const currentVisibleColumn = CursorColumns.visibleColumnFromColumn(model.getLineContent(lineNumber), column, config.tabSize) + leftoverVisibleColumns;
|
|
const wasOnFirstPosition = (lineNumber === 1 && column === 1);
|
|
|
|
lineNumber = lineNumber - count;
|
|
if (lineNumber < 1) {
|
|
lineNumber = 1;
|
|
if (allowMoveOnFirstLine) {
|
|
column = model.getLineMinColumn(lineNumber);
|
|
} else {
|
|
column = Math.min(model.getLineMaxColumn(lineNumber), column);
|
|
}
|
|
} else {
|
|
column = CursorColumns.columnFromVisibleColumn2(config, model, lineNumber, currentVisibleColumn);
|
|
}
|
|
|
|
if (wasOnFirstPosition) {
|
|
leftoverVisibleColumns = 0;
|
|
} else {
|
|
leftoverVisibleColumns = currentVisibleColumn - CursorColumns.visibleColumnFromColumn(model.getLineContent(lineNumber), column, config.tabSize);
|
|
}
|
|
|
|
return new CursorPosition(lineNumber, column, leftoverVisibleColumns);
|
|
}
|
|
|
|
public static moveUp(config: CursorConfiguration, model: ICursorSimpleModel, cursor: SingleCursorState, inSelectionMode: boolean, linesCount: number): SingleCursorState {
|
|
let lineNumber: number,
|
|
column: number;
|
|
|
|
if (cursor.hasSelection() && !inSelectionMode) {
|
|
// If we are in selection mode, move up acts relative to the beginning of selection
|
|
lineNumber = cursor.selection.startLineNumber;
|
|
column = cursor.selection.startColumn;
|
|
} else {
|
|
lineNumber = cursor.position.lineNumber;
|
|
column = cursor.position.column;
|
|
}
|
|
|
|
let r = MoveOperations.up(config, model, lineNumber, column, cursor.leftoverVisibleColumns, linesCount, true);
|
|
|
|
return cursor.move(inSelectionMode, r.lineNumber, r.column, r.leftoverVisibleColumns);
|
|
}
|
|
|
|
public static translateUp(config: CursorConfiguration, model: ICursorSimpleModel, cursor: SingleCursorState): SingleCursorState {
|
|
|
|
let selection = cursor.selection;
|
|
|
|
let selectionStart = MoveOperations.up(config, model, selection.selectionStartLineNumber, selection.selectionStartColumn, cursor.selectionStartLeftoverVisibleColumns, 1, false);
|
|
let position = MoveOperations.up(config, model, selection.positionLineNumber, selection.positionColumn, cursor.leftoverVisibleColumns, 1, false);
|
|
|
|
return new SingleCursorState(
|
|
new Range(selectionStart.lineNumber, selectionStart.column, selectionStart.lineNumber, selectionStart.column),
|
|
selectionStart.leftoverVisibleColumns,
|
|
new Position(position.lineNumber, position.column),
|
|
position.leftoverVisibleColumns
|
|
);
|
|
}
|
|
|
|
private static _isBlankLine(model: ICursorSimpleModel, lineNumber: number): boolean {
|
|
if (model.getLineFirstNonWhitespaceColumn(lineNumber) === 0) {
|
|
// empty or contains only whitespace
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static moveToPrevBlankLine(config: CursorConfiguration, model: ICursorSimpleModel, cursor: SingleCursorState, inSelectionMode: boolean): SingleCursorState {
|
|
let lineNumber = cursor.position.lineNumber;
|
|
|
|
// If our current line is blank, move to the previous non-blank line
|
|
while (lineNumber > 1 && this._isBlankLine(model, lineNumber)) {
|
|
lineNumber--;
|
|
}
|
|
|
|
// Find the previous blank line
|
|
while (lineNumber > 1 && !this._isBlankLine(model, lineNumber)) {
|
|
lineNumber--;
|
|
}
|
|
|
|
return cursor.move(inSelectionMode, lineNumber, model.getLineMinColumn(lineNumber), 0);
|
|
}
|
|
|
|
public static moveToNextBlankLine(config: CursorConfiguration, model: ICursorSimpleModel, cursor: SingleCursorState, inSelectionMode: boolean): SingleCursorState {
|
|
const lineCount = model.getLineCount();
|
|
let lineNumber = cursor.position.lineNumber;
|
|
|
|
// If our current line is blank, move to the next non-blank line
|
|
while (lineNumber < lineCount && this._isBlankLine(model, lineNumber)) {
|
|
lineNumber++;
|
|
}
|
|
|
|
// Find the next blank line
|
|
while (lineNumber < lineCount && !this._isBlankLine(model, lineNumber)) {
|
|
lineNumber++;
|
|
}
|
|
|
|
return cursor.move(inSelectionMode, lineNumber, model.getLineMinColumn(lineNumber), 0);
|
|
}
|
|
|
|
public static moveToBeginningOfLine(config: CursorConfiguration, model: ICursorSimpleModel, cursor: SingleCursorState, inSelectionMode: boolean): SingleCursorState {
|
|
let lineNumber = cursor.position.lineNumber;
|
|
let minColumn = model.getLineMinColumn(lineNumber);
|
|
let firstNonBlankColumn = model.getLineFirstNonWhitespaceColumn(lineNumber) || minColumn;
|
|
|
|
let column: number;
|
|
|
|
let relevantColumnNumber = cursor.position.column;
|
|
if (relevantColumnNumber === firstNonBlankColumn) {
|
|
column = minColumn;
|
|
} else {
|
|
column = firstNonBlankColumn;
|
|
}
|
|
|
|
return cursor.move(inSelectionMode, lineNumber, column, 0);
|
|
}
|
|
|
|
public static moveToEndOfLine(config: CursorConfiguration, model: ICursorSimpleModel, cursor: SingleCursorState, inSelectionMode: boolean, sticky: boolean): SingleCursorState {
|
|
let lineNumber = cursor.position.lineNumber;
|
|
let maxColumn = model.getLineMaxColumn(lineNumber);
|
|
return cursor.move(inSelectionMode, lineNumber, maxColumn, sticky ? Constants.MAX_SAFE_SMALL_INTEGER - maxColumn : 0);
|
|
}
|
|
|
|
public static moveToBeginningOfBuffer(config: CursorConfiguration, model: ICursorSimpleModel, cursor: SingleCursorState, inSelectionMode: boolean): SingleCursorState {
|
|
return cursor.move(inSelectionMode, 1, 1, 0);
|
|
}
|
|
|
|
public static moveToEndOfBuffer(config: CursorConfiguration, model: ICursorSimpleModel, cursor: SingleCursorState, inSelectionMode: boolean): SingleCursorState {
|
|
let lastLineNumber = model.getLineCount();
|
|
let lastColumn = model.getLineMaxColumn(lastLineNumber);
|
|
|
|
return cursor.move(inSelectionMode, lastLineNumber, lastColumn, 0);
|
|
}
|
|
}
|