mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge pull request #2078 from Tyriar/1443_selection_api
select and getSelectionPosition APIs
This commit is contained in:
+24
-1
@@ -43,7 +43,7 @@ import { DEFAULT_BELL_SOUND, SoundManager } from './SoundManager';
|
||||
import { MouseZoneManager } from './MouseZoneManager';
|
||||
import { AccessibilityManager } from './AccessibilityManager';
|
||||
import { ScreenDprMonitor } from './ui/ScreenDprMonitor';
|
||||
import { ITheme, IMarker, IDisposable } from 'xterm';
|
||||
import { ITheme, IMarker, IDisposable, ISelectionPosition } from 'xterm';
|
||||
import { removeTerminalFromCache } from './renderer/atlas/CharAtlasCache';
|
||||
import { DomRenderer } from './renderer/dom/DomRenderer';
|
||||
import { IKeyboardEvent } from './common/Types';
|
||||
@@ -1535,6 +1535,16 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
||||
return this.selectionManager ? this.selectionManager.hasSelection : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects text within the terminal.
|
||||
* @param column The column the selection starts at..
|
||||
* @param row The row the selection starts at.
|
||||
* @param length The length of the selection.
|
||||
*/
|
||||
public select(column: number, row: number, length: number): void {
|
||||
this.selectionManager.setSelection(column, row, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the terminal's current selection, this is useful for implementing copy
|
||||
* behavior outside of xterm.js.
|
||||
@@ -1543,6 +1553,19 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
||||
return this.selectionManager ? this.selectionManager.selectionText : '';
|
||||
}
|
||||
|
||||
public getSelectionPosition(): ISelectionPosition | undefined {
|
||||
if (!this.selectionManager.hasSelection) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
startColumn: this.selectionManager.selectionStart[0],
|
||||
startRow: this.selectionManager.selectionStart[1],
|
||||
endColumn: this.selectionManager.selectionEnd[0],
|
||||
endRow: this.selectionManager.selectionEnd[1]
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the current terminal selection.
|
||||
*/
|
||||
|
||||
@@ -9,7 +9,7 @@ import { IBufferLine, ICellData, IAttributeData } from './core/Types';
|
||||
import { ICircularList, XtermListener } from './common/Types';
|
||||
import { Buffer } from './Buffer';
|
||||
import * as Browser from './common/Platform';
|
||||
import { ITheme, IDisposable, IMarker, IEvent } from 'xterm';
|
||||
import { ITheme, IDisposable, IMarker, IEvent, ISelectionPosition } from 'xterm';
|
||||
import { Terminal } from './Terminal';
|
||||
import { AttributeData } from './core/buffer/BufferLine';
|
||||
|
||||
@@ -83,9 +83,15 @@ export class MockTerminal implements ITerminal {
|
||||
getSelection(): string {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
getSelectionPosition(): ISelectionPosition | undefined {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
clearSelection(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
select(column: number, row: number, length: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
selectAll(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
+3
-1
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { ITerminalOptions as IPublicTerminalOptions, IEventEmitter, IDisposable, IMarker } from 'xterm';
|
||||
import { ITerminalOptions as IPublicTerminalOptions, IEventEmitter, IDisposable, IMarker, ISelectionPosition } from 'xterm';
|
||||
import { IColorSet, IRenderer } from './renderer/Types';
|
||||
import { ICharset, IAttributeData, ICellData, IBufferLine, CharData } from './core/Types';
|
||||
import { ICircularList } from './common/Types';
|
||||
@@ -250,7 +250,9 @@ export interface IPublicTerminal extends IDisposable, IEventEmitter {
|
||||
addMarker(cursorYOffset: number): IMarker;
|
||||
hasSelection(): boolean;
|
||||
getSelection(): string;
|
||||
getSelectionPosition(): ISelectionPosition | undefined;
|
||||
clearSelection(): void;
|
||||
select(column: number, row: number, length: number): void;
|
||||
selectAll(): void;
|
||||
selectLines(start: number, end: number): void;
|
||||
dispose(): void;
|
||||
|
||||
@@ -8,7 +8,6 @@ import { Terminal } from 'xterm';
|
||||
// TODO: Don't rely on this private API
|
||||
export interface ITerminalCore {
|
||||
buffer: any;
|
||||
selectionManager: any;
|
||||
}
|
||||
|
||||
export interface ISearchAddonTerminal extends Terminal {
|
||||
|
||||
@@ -35,25 +35,23 @@ export class SearchHelper implements ISearchHelper {
|
||||
* @return Whether a result was found.
|
||||
*/
|
||||
public findNext(term: string, searchOptions?: ISearchOptions): boolean {
|
||||
const selectionManager = this._terminal._core.selectionManager;
|
||||
const {incremental} = searchOptions;
|
||||
let result: ISearchResult;
|
||||
|
||||
if (!term || term.length === 0) {
|
||||
selectionManager.clearSelection();
|
||||
this._terminal.clearSelection();
|
||||
return false;
|
||||
}
|
||||
|
||||
let startCol: number = 0;
|
||||
let startRow = this._terminal._core.buffer.ydisp;
|
||||
|
||||
if (selectionManager.selectionEnd) {
|
||||
if (this._terminal.hasSelection()) {
|
||||
// Start from the selection end if there is a selection
|
||||
// For incremental search, use existing row
|
||||
if (this._terminal.getSelection().length !== 0) {
|
||||
startRow = incremental ? selectionManager.selectionStart[1] : selectionManager.selectionEnd[1];
|
||||
startCol = incremental ? selectionManager.selectionStart[0] : selectionManager.selectionEnd[0];
|
||||
}
|
||||
const currentSelection = this._terminal.getSelectionPosition();
|
||||
startRow = incremental ? currentSelection.startRow : currentSelection.endRow;
|
||||
startCol = incremental ? currentSelection.startColumn : currentSelection.endColumn;
|
||||
}
|
||||
|
||||
this._initLinesCache();
|
||||
@@ -109,11 +107,10 @@ export class SearchHelper implements ISearchHelper {
|
||||
* @return Whether a result was found.
|
||||
*/
|
||||
public findPrevious(term: string, searchOptions?: ISearchOptions): boolean {
|
||||
const selectionManager = this._terminal._core.selectionManager;
|
||||
let result: ISearchResult;
|
||||
|
||||
if (!term || term.length === 0) {
|
||||
selectionManager.clearSelection();
|
||||
this._terminal.clearSelection();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -121,12 +118,11 @@ export class SearchHelper implements ISearchHelper {
|
||||
let startRow = this._terminal._core.buffer.ydisp + this._terminal.rows - 1;
|
||||
let startCol = this._terminal.cols;
|
||||
|
||||
if (selectionManager.selectionStart) {
|
||||
if (this._terminal.hasSelection()) {
|
||||
// Start from the selection start if there is a selection
|
||||
if (this._terminal.getSelection().length !== 0) {
|
||||
startRow = selectionManager.selectionStart[1];
|
||||
startCol = selectionManager.selectionStart[0];
|
||||
}
|
||||
const currentSelection = this._terminal.getSelectionPosition();
|
||||
startRow = currentSelection.startRow;
|
||||
startCol = currentSelection.startColumn;
|
||||
}
|
||||
|
||||
this._initLinesCache();
|
||||
@@ -341,7 +337,7 @@ export class SearchHelper implements ISearchHelper {
|
||||
this._terminal.clearSelection();
|
||||
return false;
|
||||
}
|
||||
this._terminal._core.selectionManager.setSelection(result.col, result.row, result.term.length);
|
||||
this._terminal.select(result.col, result.row, result.term.length);
|
||||
this._terminal.scrollLines(result.row - this._terminal._core.buffer.ydisp);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -89,16 +89,23 @@ describe('API Integration Tests', () => {
|
||||
|
||||
it('selection', async function(): Promise<any> {
|
||||
this.timeout(10000);
|
||||
await openTerminal({ rows: 5 });
|
||||
await openTerminal({ rows: 5, cols: 5 });
|
||||
await page.evaluate(`window.term.write('\\n\\nfoo\\n\\n\\rbar\\n\\n\\rbaz')`);
|
||||
assert.equal(await page.evaluate(`window.term.hasSelection()`), false);
|
||||
assert.equal(await page.evaluate(`window.term.getSelection()`), '');
|
||||
assert.deepEqual(await page.evaluate(`window.term.getSelectionPosition()`), undefined);
|
||||
await page.evaluate(`window.term.selectAll()`);
|
||||
assert.equal(await page.evaluate(`window.term.hasSelection()`), true);
|
||||
assert.equal(await page.evaluate(`window.term.getSelection()`), '\n\nfoo\n\nbar\n\nbaz');
|
||||
assert.deepEqual(await page.evaluate(`window.term.getSelectionPosition()`), { startColumn: 0, startRow: 0, endColumn: 5, endRow: 6 });
|
||||
await page.evaluate(`window.term.clearSelection()`);
|
||||
assert.equal(await page.evaluate(`window.term.hasSelection()`), false);
|
||||
assert.equal(await page.evaluate(`window.term.getSelection()`), '');
|
||||
assert.deepEqual(await page.evaluate(`window.term.getSelectionPosition()`), undefined);
|
||||
await page.evaluate(`window.term.select(1, 2, 2)`);
|
||||
assert.equal(await page.evaluate(`window.term.hasSelection()`), true);
|
||||
assert.equal(await page.evaluate(`window.term.getSelection()`), 'oo');
|
||||
assert.deepEqual(await page.evaluate(`window.term.getSelectionPosition()`), { startColumn: 1, startRow: 2, endColumn: 3, endRow: 2 });
|
||||
});
|
||||
|
||||
it('focus, blur', async function(): Promise<any> {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, IBuffer as IBufferApi, IBufferLine as IBufferLineApi, IBufferCell as IBufferCellApi } from 'xterm';
|
||||
import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, IBuffer as IBufferApi, IBufferLine as IBufferLineApi, IBufferCell as IBufferCellApi, ISelectionPosition } from 'xterm';
|
||||
import { ITerminal, IBuffer } from '../Types';
|
||||
import { IBufferLine } from '../core/Types';
|
||||
import { Terminal as TerminalCore } from '../Terminal';
|
||||
@@ -96,9 +96,15 @@ export class Terminal implements ITerminalApi {
|
||||
public hasSelection(): boolean {
|
||||
return this._core.hasSelection();
|
||||
}
|
||||
public select(column: number, row: number, length: number): void {
|
||||
this._core.select(column, row, length);
|
||||
}
|
||||
public getSelection(): string {
|
||||
return this._core.getSelection();
|
||||
}
|
||||
public getSelectionPosition(): ISelectionPosition | undefined {
|
||||
return this._core.getSelectionPosition();
|
||||
}
|
||||
public clearSelection(): void {
|
||||
this._core.clearSelection();
|
||||
}
|
||||
|
||||
Vendored
+38
@@ -676,11 +676,24 @@ declare module 'xterm' {
|
||||
*/
|
||||
getSelection(): string;
|
||||
|
||||
/**
|
||||
* Gets the selection position or undefined if there is no selection.
|
||||
*/
|
||||
getSelectionPosition(): ISelectionPosition | undefined;
|
||||
|
||||
/**
|
||||
* Clears the current terminal selection.
|
||||
*/
|
||||
clearSelection(): void;
|
||||
|
||||
/**
|
||||
* Selects text within the terminal.
|
||||
* @param column The column the selection starts at..
|
||||
* @param row The row the selection starts at.
|
||||
* @param length The length of the selection.
|
||||
*/
|
||||
select(column: number, row: number, length: number): void;
|
||||
|
||||
/**
|
||||
* Selects all text within the terminal.
|
||||
*/
|
||||
@@ -864,6 +877,31 @@ declare module 'xterm' {
|
||||
static applyAddon(addon: any): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* An object representing a selecrtion within the terminal.
|
||||
*/
|
||||
interface ISelectionPosition {
|
||||
/**
|
||||
* The start column of the selection.
|
||||
*/
|
||||
startColumn: number;
|
||||
|
||||
/**
|
||||
* The start row of the selection.
|
||||
*/
|
||||
startRow: number;
|
||||
|
||||
/**
|
||||
* The end column of the selection.
|
||||
*/
|
||||
endColumn: number;
|
||||
|
||||
/**
|
||||
* The end row of the selection.
|
||||
*/
|
||||
endRow: number;
|
||||
}
|
||||
|
||||
interface IBuffer {
|
||||
/**
|
||||
* The y position of the cursor. This ranges between `0` (when the
|
||||
|
||||
Reference in New Issue
Block a user