Change AltClickHandler to be functional
This commit is contained in:
@@ -8,13 +8,13 @@ import { IBuffer } from 'common/buffer/Types';
|
|||||||
import { IBufferLine } from 'common/Types';
|
import { IBufferLine } from 'common/Types';
|
||||||
import * as Browser from 'common/Platform';
|
import * as Browser from 'common/Platform';
|
||||||
import { SelectionModel } from 'browser/selection/SelectionModel';
|
import { SelectionModel } from 'browser/selection/SelectionModel';
|
||||||
import { AltClickHandler } from './handlers/AltClickHandler';
|
|
||||||
import { CellData } from 'common/buffer/CellData';
|
import { CellData } from 'common/buffer/CellData';
|
||||||
import { IDisposable } from 'xterm';
|
import { IDisposable } from 'xterm';
|
||||||
import { EventEmitter, IEvent } from 'common/EventEmitter';
|
import { EventEmitter, IEvent } from 'common/EventEmitter';
|
||||||
import { ICharSizeService, IMouseService } from 'browser/services/Services';
|
import { ICharSizeService, IMouseService } from 'browser/services/Services';
|
||||||
import { IBufferService, IOptionsService } from 'common/services/Services';
|
import { IBufferService, IOptionsService } from 'common/services/Services';
|
||||||
import { getCoordsRelativeToElement } from 'browser/input/Mouse';
|
import { getCoordsRelativeToElement } from 'browser/input/Mouse';
|
||||||
|
import { moveToCellSequence } from 'handlers/AltClickHandler';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of pixels the mouse needs to be above or below the viewport in
|
* The number of pixels the mouse needs to be above or below the viewport in
|
||||||
@@ -659,9 +659,8 @@ export class SelectionManager implements ISelectionManager {
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
if (coordinates && coordinates[0] !== undefined && coordinates[1] !== undefined) {
|
if (coordinates && coordinates[0] !== undefined && coordinates[1] !== undefined) {
|
||||||
this._terminal.handler(
|
const sequence = moveToCellSequence(coordinates[0] - 1, coordinates[1] - 1, this._bufferService, this._terminal.applicationCursor);
|
||||||
(new AltClickHandler()).move(coordinates[0] - 1, coordinates[1] - 1, this._bufferService, this._terminal.applicationCursor)
|
this._terminal.handler(sequence);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (this.hasSelection) {
|
} else if (this.hasSelection) {
|
||||||
|
|||||||
+126
-140
@@ -13,163 +13,149 @@ const enum Direction {
|
|||||||
LEFT = 'D'
|
LEFT = 'D'
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AltClickHandler {
|
/**
|
||||||
|
* Concatenates all the arrow sequences together.
|
||||||
|
* Resets the starting row to an unwrapped row, moves to the requested row,
|
||||||
|
* then moves to requested col.
|
||||||
|
*/
|
||||||
|
export function moveToCellSequence(targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string {
|
||||||
|
const startX = bufferService.buffer.x;
|
||||||
|
const startY = bufferService.buffer.y;
|
||||||
|
|
||||||
constructor(
|
// The alt buffer should try to navigate between rows
|
||||||
) {
|
if (!bufferService.buffer.hasScrollback) {
|
||||||
|
return resetStartingRow(startX, startY, targetX, targetY, bufferService, applicationCursor) +
|
||||||
|
moveToRequestedRow(startY, targetY, bufferService, applicationCursor) +
|
||||||
|
moveToRequestedCol(startX, startY, targetX, targetY, bufferService, applicationCursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// Only move horizontally for the normal buffer
|
||||||
* Writes the escape sequences of arrows to the terminal
|
return moveHorizontallyOnly(startX, startY, targetX, targetY, bufferService, applicationCursor);
|
||||||
*/
|
}
|
||||||
public move(targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string {
|
|
||||||
return this._arrowSequences(targetX, targetY, bufferService, applicationCursor);
|
/**
|
||||||
|
* If the initial position of the cursor is on a row that is wrapped, move the
|
||||||
|
* cursor up to the first row that is not wrapped to have accurate vertical
|
||||||
|
* positioning.
|
||||||
|
*/
|
||||||
|
function resetStartingRow(startX: number, startY: number, targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string {
|
||||||
|
if (moveToRequestedRow(startY, targetY, bufferService, applicationCursor).length === 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return repeat(bufferLine(
|
||||||
|
startX, startY, startX,
|
||||||
|
startY - wrappedRowsForRow(bufferService, startY), false, bufferService
|
||||||
|
).length, sequence(Direction.LEFT, applicationCursor));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Using the reset starting and ending row, move to the requested row,
|
||||||
|
* ignoring wrapped rows
|
||||||
|
*/
|
||||||
|
function moveToRequestedRow(startY: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string {
|
||||||
|
const startRow = startY - wrappedRowsForRow(bufferService, startY);
|
||||||
|
const endRow = targetY - wrappedRowsForRow(bufferService, targetY);
|
||||||
|
|
||||||
|
const rowsToMove = Math.abs(startRow - endRow) - wrappedRowsCount(startY, targetY, bufferService);
|
||||||
|
|
||||||
|
return repeat(rowsToMove, sequence(verticalDirection(startY, targetY), applicationCursor));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move to the requested col on the ending row
|
||||||
|
*/
|
||||||
|
function moveToRequestedCol(startX: number, startY: number, targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string {
|
||||||
|
let startRow;
|
||||||
|
if (moveToRequestedRow(startY, targetY, bufferService, applicationCursor).length > 0) {
|
||||||
|
startRow = targetY - wrappedRowsForRow(bufferService, targetY);
|
||||||
|
} else {
|
||||||
|
startRow = startY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
const endRow = targetY;
|
||||||
* Concatenates all the arrow sequences together.
|
const direction = horizontalDirection(startX, startY, targetX, targetY, bufferService, applicationCursor);
|
||||||
* Resets the starting row to an unwrapped row, moves to the requested row,
|
|
||||||
* then moves to requested col.
|
|
||||||
*/
|
|
||||||
private _arrowSequences(targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string {
|
|
||||||
const startX = bufferService.buffer.x;
|
|
||||||
const startY = bufferService.buffer.y;
|
|
||||||
|
|
||||||
// The alt buffer should try to navigate between rows
|
return repeat(bufferLine(
|
||||||
if (!bufferService.buffer.hasScrollback) {
|
startX, startRow, targetX, endRow,
|
||||||
return this._resetStartingRow(startX, startY, targetX, targetY, bufferService, applicationCursor) +
|
direction === Direction.RIGHT, bufferService
|
||||||
this._moveToRequestedRow(startY, targetY, bufferService, applicationCursor) +
|
).length, sequence(direction, applicationCursor));
|
||||||
this._moveToRequestedCol(startX, startY, targetX, targetY, bufferService, applicationCursor);
|
}
|
||||||
|
|
||||||
|
function moveHorizontallyOnly(startX: number, startY: number, targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string {
|
||||||
|
const direction = horizontalDirection(startX, startY, targetX, targetY, bufferService, applicationCursor);
|
||||||
|
return repeat(Math.abs(startX - targetX), sequence(direction, applicationCursor));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the number of wrapped rows between the unwrapped starting and
|
||||||
|
* ending rows. These rows need to ignored since the cursor skips over them.
|
||||||
|
*/
|
||||||
|
function wrappedRowsCount(startY: number, targetY: number, bufferService: IBufferService): number {
|
||||||
|
let wrappedRows = 0;
|
||||||
|
const startRow = startY - wrappedRowsForRow(bufferService, startY);
|
||||||
|
const endRow = targetY - wrappedRowsForRow(bufferService, targetY);
|
||||||
|
|
||||||
|
for (let i = 0; i < Math.abs(startRow - endRow); i++) {
|
||||||
|
const direction = verticalDirection(startY, targetY) === Direction.UP ? -1 : 1;
|
||||||
|
|
||||||
|
if (bufferService.buffer.lines.get(startRow + (direction * i)).isWrapped) {
|
||||||
|
wrappedRows++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only move horizontally for the normal buffer
|
|
||||||
return this._moveHorizontallyOnly(startX, startY, targetX, targetY, bufferService, applicationCursor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
return wrappedRows;
|
||||||
* If the initial position of the cursor is on a row that is wrapped, move the
|
}
|
||||||
* cursor up to the first row that is not wrapped to have accurate vertical
|
|
||||||
* positioning.
|
/**
|
||||||
*/
|
* Calculates the number of wrapped rows that make up a given row.
|
||||||
private _resetStartingRow(startX: number, startY: number, targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string {
|
* @param currentRow The row to determine how many wrapped rows make it up
|
||||||
if (this._moveToRequestedRow(startY, targetY, bufferService, applicationCursor).length === 0) {
|
*/
|
||||||
return '';
|
function wrappedRowsForRow(bufferService: IBufferService, currentRow: number): number {
|
||||||
}
|
let rowCount = 0;
|
||||||
return repeat(bufferLine(
|
let lineWraps = bufferService.buffer.lines.get(currentRow).isWrapped;
|
||||||
startX, startY, startX,
|
|
||||||
startY - this._wrappedRowsForRow(bufferService, startY), false, bufferService
|
while (lineWraps && currentRow >= 0 && currentRow < bufferService.rows) {
|
||||||
).length, sequence(Direction.LEFT, applicationCursor));
|
rowCount++;
|
||||||
|
currentRow--;
|
||||||
|
lineWraps = bufferService.buffer.lines.get(currentRow).isWrapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
return rowCount;
|
||||||
* Using the reset starting and ending row, move to the requested row,
|
}
|
||||||
* ignoring wrapped rows
|
|
||||||
*/
|
|
||||||
private _moveToRequestedRow(startY: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string {
|
|
||||||
const startRow = startY - this._wrappedRowsForRow(bufferService, startY);
|
|
||||||
const endRow = targetY - this._wrappedRowsForRow(bufferService, targetY);
|
|
||||||
|
|
||||||
const rowsToMove = Math.abs(startRow - endRow) - this._wrappedRowsCount(startY, targetY, bufferService);
|
/**
|
||||||
|
* Direction determiners
|
||||||
|
*/
|
||||||
|
|
||||||
return repeat(rowsToMove, sequence(this._verticalDirection(startY, targetY), applicationCursor));
|
/**
|
||||||
|
* Determines if the right or left arrow is needed
|
||||||
|
*/
|
||||||
|
function horizontalDirection(startX: number, startY: number, targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): Direction {
|
||||||
|
let startRow;
|
||||||
|
if (moveToRequestedRow(targetX, targetY, bufferService, applicationCursor).length > 0) {
|
||||||
|
startRow = targetY - wrappedRowsForRow(bufferService, targetY);
|
||||||
|
} else {
|
||||||
|
startRow = startY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
if ((startX < targetX &&
|
||||||
* Move to the requested col on the ending row
|
startRow <= targetY) || // down/right or same y/right
|
||||||
*/
|
(startX >= targetX &&
|
||||||
private _moveToRequestedCol(startX: number, startY: number, targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string {
|
startRow < targetY)) { // down/left or same y/left
|
||||||
let startRow;
|
return Direction.RIGHT;
|
||||||
if (this._moveToRequestedRow(startY, targetY, bufferService, applicationCursor).length > 0) {
|
|
||||||
startRow = targetY - this._wrappedRowsForRow(bufferService, targetY);
|
|
||||||
} else {
|
|
||||||
startRow = startY;
|
|
||||||
}
|
|
||||||
|
|
||||||
const endRow = targetY;
|
|
||||||
const direction = this._horizontalDirection(startX, startY, targetX, targetY, bufferService, applicationCursor);
|
|
||||||
|
|
||||||
return repeat(bufferLine(
|
|
||||||
startX, startRow, targetX, endRow,
|
|
||||||
direction === Direction.RIGHT, bufferService
|
|
||||||
).length, sequence(direction, applicationCursor));
|
|
||||||
}
|
}
|
||||||
|
return Direction.LEFT;
|
||||||
|
}
|
||||||
|
|
||||||
private _moveHorizontallyOnly(startX: number, startY: number, targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string {
|
/**
|
||||||
const direction = this._horizontalDirection(startX, startY, targetX, targetY, bufferService, applicationCursor);
|
* Determines if the up or down arrow is needed
|
||||||
return repeat(Math.abs(startX - targetX), sequence(direction, applicationCursor));
|
*/
|
||||||
}
|
function verticalDirection(startY: number, targetY: number): Direction {
|
||||||
|
return startY > targetY ? Direction.UP : Direction.DOWN;
|
||||||
/**
|
|
||||||
* Utility functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the number of wrapped rows between the unwrapped starting and
|
|
||||||
* ending rows. These rows need to ignored since the cursor skips over them.
|
|
||||||
*/
|
|
||||||
private _wrappedRowsCount(startY: number, targetY: number, bufferService: IBufferService): number {
|
|
||||||
let wrappedRows = 0;
|
|
||||||
const startRow = startY - this._wrappedRowsForRow(bufferService, startY);
|
|
||||||
const endRow = targetY - this._wrappedRowsForRow(bufferService, targetY);
|
|
||||||
|
|
||||||
for (let i = 0; i < Math.abs(startRow - endRow); i++) {
|
|
||||||
const direction = this._verticalDirection(startY, targetY) === Direction.UP ? -1 : 1;
|
|
||||||
|
|
||||||
if (bufferService.buffer.lines.get(startRow + (direction * i)).isWrapped) {
|
|
||||||
wrappedRows++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return wrappedRows;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the number of wrapped rows that make up a given row.
|
|
||||||
* @param currentRow The row to determine how many wrapped rows make it up
|
|
||||||
*/
|
|
||||||
private _wrappedRowsForRow(bufferService: IBufferService, currentRow: number): number {
|
|
||||||
let rowCount = 0;
|
|
||||||
let lineWraps = bufferService.buffer.lines.get(currentRow).isWrapped;
|
|
||||||
|
|
||||||
while (lineWraps && currentRow >= 0 && currentRow < bufferService.rows) {
|
|
||||||
rowCount++;
|
|
||||||
currentRow--;
|
|
||||||
lineWraps = bufferService.buffer.lines.get(currentRow).isWrapped;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rowCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Direction determiners
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if the right or left arrow is needed
|
|
||||||
*/
|
|
||||||
private _horizontalDirection(startX: number, startY: number, targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): Direction {
|
|
||||||
let startRow;
|
|
||||||
if (this._moveToRequestedRow(targetX, targetY, bufferService, applicationCursor).length > 0) {
|
|
||||||
startRow = targetY - this._wrappedRowsForRow(bufferService, targetY);
|
|
||||||
} else {
|
|
||||||
startRow = startY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((startX < targetX &&
|
|
||||||
startRow <= targetY) || // down/right or same y/right
|
|
||||||
(startX >= targetX &&
|
|
||||||
startRow < targetY)) { // down/left or same y/left
|
|
||||||
return Direction.RIGHT;
|
|
||||||
}
|
|
||||||
return Direction.LEFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if the up or down arrow is needed
|
|
||||||
*/
|
|
||||||
private _verticalDirection(startY: number, targetY: number): Direction {
|
|
||||||
return startY > targetY ? Direction.UP : Direction.DOWN;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user