xterm
Version:
Full xterm terminal, in your browser
554 lines (503 loc) • 17.8 kB
TypeScript
/**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { IDeleteEvent, IInsertEvent } from 'common/CircularList';
import { IEvent, IEventEmitter } from 'common/EventEmitter';
import { Attributes, UnderlineStyle } from 'common/buffer/Constants'; // eslint-disable-line no-unused-vars
import { IBufferSet } from 'common/buffer/Types';
import { IParams } from 'common/parser/Types';
import { ICoreMouseService, ICoreService, IOptionsService, IUnicodeService } from 'common/services/Services';
import { IFunctionIdentifier, ITerminalOptions as IPublicTerminalOptions } from 'xterm';
export interface ICoreTerminal {
coreMouseService: ICoreMouseService;
coreService: ICoreService;
optionsService: IOptionsService;
unicodeService: IUnicodeService;
buffers: IBufferSet;
options: Required<ITerminalOptions>;
registerCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean | Promise<boolean>): IDisposable;
registerDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean | Promise<boolean>): IDisposable;
registerEscHandler(id: IFunctionIdentifier, callback: () => boolean | Promise<boolean>): IDisposable;
registerOscHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable;
}
export interface IDisposable {
dispose(): void;
}
// TODO: The options that are not in the public API should be reviewed
export interface ITerminalOptions extends IPublicTerminalOptions {
[key: string]: any;
cancelEvents?: boolean;
convertEol?: boolean;
termName?: string;
}
export type CursorStyle = 'block' | 'underline' | 'bar';
export type CursorInactiveStyle = 'outline' | 'block' | 'bar' | 'underline' | 'none';
export type XtermListener = (...args: any[]) => void;
/**
* A keyboard event interface which does not depend on the DOM, KeyboardEvent implicitly extends
* this event.
*/
export interface IKeyboardEvent {
altKey: boolean;
ctrlKey: boolean;
shiftKey: boolean;
metaKey: boolean;
/** @deprecated See KeyboardEvent.keyCode */
keyCode: number;
key: string;
type: string;
code: string;
}
export interface IScrollEvent {
position: number;
source: ScrollSource;
}
export const enum ScrollSource {
TERMINAL,
VIEWPORT,
}
export interface ICircularList<T> {
length: number;
maxLength: number;
isFull: boolean;
onDeleteEmitter: IEventEmitter<IDeleteEvent>;
onDelete: IEvent<IDeleteEvent>;
onInsertEmitter: IEventEmitter<IInsertEvent>;
onInsert: IEvent<IInsertEvent>;
onTrimEmitter: IEventEmitter<number>;
onTrim: IEvent<number>;
get(index: number): T | undefined;
set(index: number, value: T): void;
push(value: T): void;
recycle(): T;
pop(): T | undefined;
splice(start: number, deleteCount: number, ...items: T[]): void;
trimStart(count: number): void;
shiftElements(start: number, count: number, offset: number): void;
}
export const enum KeyboardResultType {
SEND_KEY,
SELECT_ALL,
PAGE_UP,
PAGE_DOWN
}
export interface IKeyboardResult {
type: KeyboardResultType;
cancel: boolean;
key: string | undefined;
}
export interface ICharset {
[key: string]: string | undefined;
}
export type CharData = [number, string, number, number];
export interface IColor {
css: string;
rgba: number; // 32-bit int with rgba in each byte
}
export type IColorRGB = [number, number, number];
export interface IExtendedAttrs {
ext: number;
underlineStyle: UnderlineStyle;
underlineColor: number;
urlId: number;
clone(): IExtendedAttrs;
isEmpty(): boolean;
}
/**
* Tracks the current hyperlink. Since these are treated as extended attirbutes, these get passed on
* to the linkifier when anything is printed. Doing it this way ensures that even when the cursor
* moves around unexpectedly the link is tracked, as opposed to using a start position and
* finalizing it at the end.
*/
export interface IOscLinkData {
id?: string;
uri: string;
}
/**
* An object that represents all attributes of a cell.
*/
export interface IAttributeData {
/**
* "fg" is a 32-bit unsigned integer that stores the foreground color of the cell in the 24 least
* significant bits and additional flags in the remaining 8 bits.
*/
fg: number;
/**
* "bg" is a 32-bit unsigned integer that stores the background color of the cell in the 24 least
* significant bits and additional flags in the remaining 8 bits.
*/
bg: number;
/**
* "extended", aka "ext", stores extended attributes beyond those available in fg and bg. This
* data is optional on a cell and encodes less common data.
*/
extended: IExtendedAttrs;
clone(): IAttributeData;
// flags
isInverse(): number;
isBold(): number;
isUnderline(): number;
isBlink(): number;
isInvisible(): number;
isItalic(): number;
isDim(): number;
isStrikethrough(): number;
isProtected(): number;
isOverline(): number;
/**
* The color mode of the foreground color which determines how to decode {@link getFgColor},
* possible values include {@link Attributes.CM_DEFAULT}, {@link Attributes.CM_P16},
* {@link Attributes.CM_P256} and {@link Attributes.CM_RGB}.
*/
getFgColorMode(): number;
/**
* The color mode of the background color which determines how to decode {@link getBgColor},
* possible values include {@link Attributes.CM_DEFAULT}, {@link Attributes.CM_P16},
* {@link Attributes.CM_P256} and {@link Attributes.CM_RGB}.
*/
getBgColorMode(): number;
isFgRGB(): boolean;
isBgRGB(): boolean;
isFgPalette(): boolean;
isBgPalette(): boolean;
isFgDefault(): boolean;
isBgDefault(): boolean;
isAttributeDefault(): boolean;
/**
* Gets an integer representation of the foreground color, how to decode the color depends on the
* color mode {@link getFgColorMode}.
*/
getFgColor(): number;
/**
* Gets an integer representation of the background color, how to decode the color depends on the
* color mode {@link getBgColorMode}.
*/
getBgColor(): number;
// extended attrs
hasExtendedAttrs(): number;
updateExtended(): void;
getUnderlineColor(): number;
getUnderlineColorMode(): number;
isUnderlineColorRGB(): boolean;
isUnderlineColorPalette(): boolean;
isUnderlineColorDefault(): boolean;
getUnderlineStyle(): number;
}
/** Cell data */
export interface ICellData extends IAttributeData {
content: number;
combinedData: string;
isCombined(): number;
getWidth(): number;
getChars(): string;
getCode(): number;
setFromCharData(value: CharData): void;
getAsCharData(): CharData;
}
/**
* Interface for a line in the terminal buffer.
*/
export interface IBufferLine {
length: number;
isWrapped: boolean;
get(index: number): CharData;
set(index: number, value: CharData): void;
loadCell(index: number, cell: ICellData): ICellData;
setCell(index: number, cell: ICellData): void;
setCellFromCodePoint(index: number, codePoint: number, width: number, fg: number, bg: number, eAttrs: IExtendedAttrs): void;
addCodepointToCell(index: number, codePoint: number): void;
insertCells(pos: number, n: number, ch: ICellData, eraseAttr?: IAttributeData): void;
deleteCells(pos: number, n: number, fill: ICellData, eraseAttr?: IAttributeData): void;
replaceCells(start: number, end: number, fill: ICellData, eraseAttr?: IAttributeData, respectProtect?: boolean): void;
resize(cols: number, fill: ICellData): boolean;
cleanupMemory(): number;
fill(fillCellData: ICellData, respectProtect?: boolean): void;
copyFrom(line: IBufferLine): void;
clone(): IBufferLine;
getTrimmedLength(): number;
getNoBgTrimmedLength(): number;
translateToString(trimRight?: boolean, startCol?: number, endCol?: number): string;
/* direct access to cell attrs */
getWidth(index: number): number;
hasWidth(index: number): number;
getFg(index: number): number;
getBg(index: number): number;
hasContent(index: number): number;
getCodePoint(index: number): number;
isCombined(index: number): number;
getString(index: number): string;
}
export interface IMarker extends IDisposable {
readonly id: number;
readonly isDisposed: boolean;
readonly line: number;
onDispose: IEvent<void>;
}
export interface IModes {
insertMode: boolean;
}
export interface IDecPrivateModes {
applicationCursorKeys: boolean;
applicationKeypad: boolean;
bracketedPasteMode: boolean;
origin: boolean;
reverseWraparound: boolean;
sendFocus: boolean;
wraparound: boolean; // defaults: xterm - true, vt100 - false
}
export interface IRowRange {
start: number;
end: number;
}
/**
* Interface for mouse events in the core.
*/
export const enum CoreMouseButton {
LEFT = 0,
MIDDLE = 1,
RIGHT = 2,
NONE = 3,
WHEEL = 4,
// additional buttons 1..8
// untested!
AUX1 = 8,
AUX2 = 9,
AUX3 = 10,
AUX4 = 11,
AUX5 = 12,
AUX6 = 13,
AUX7 = 14,
AUX8 = 15
}
export const enum CoreMouseAction {
UP = 0, // buttons, wheel
DOWN = 1, // buttons, wheel
LEFT = 2, // wheel only
RIGHT = 3, // wheel only
MOVE = 32 // buttons only
}
export interface ICoreMouseEvent {
/** column (zero based). */
col: number;
/** row (zero based). */
row: number;
/** xy pixel positions. */
x: number;
y: number;
/**
* Button the action occured. Due to restrictions of the tracking protocols
* it is not possible to report multiple buttons at once.
* Wheel is treated as a button.
* There are invalid combinations of buttons and actions possible
* (like move + wheel), those are silently ignored by the CoreMouseService.
*/
button: CoreMouseButton;
action: CoreMouseAction;
/**
* Modifier states.
* Protocols will add/ignore those based on specific restrictions.
*/
ctrl?: boolean;
alt?: boolean;
shift?: boolean;
}
/**
* CoreMouseEventType
* To be reported to the browser component which events a mouse
* protocol wants to be catched and forwarded as an ICoreMouseEvent
* to CoreMouseService.
*/
export const enum CoreMouseEventType {
NONE = 0,
/** any mousedown event */
DOWN = 1,
/** any mouseup event */
UP = 2,
/** any mousemove event while a button is held */
DRAG = 4,
/** any mousemove event without a button */
MOVE = 8,
/** any wheel event */
WHEEL = 16
}
/**
* Mouse protocol interface.
* A mouse protocol can be registered and activated at the CoreMouseService.
* `events` should contain a list of needed events as a hint for the browser component
* to install/remove the appropriate event handlers.
* `restrict` applies further protocol specific restrictions like not allowed
* modifiers or filtering invalid event types.
*/
export interface ICoreMouseProtocol {
events: CoreMouseEventType;
restrict: (e: ICoreMouseEvent) => boolean;
}
/**
* CoreMouseEncoding
* The tracking encoding can be registered and activated at the CoreMouseService.
* If a ICoreMouseEvent passes all procotol restrictions it will be encoded
* with the active encoding and sent out.
* Note: Returning an empty string will supress sending a mouse report,
* which can be used to skip creating falsey reports in limited encodings
* (DEFAULT only supports up to 223 1-based as coord value).
*/
export type CoreMouseEncoding = (event: ICoreMouseEvent) => string;
/**
* windowOptions
*/
export interface IWindowOptions {
restoreWin?: boolean;
minimizeWin?: boolean;
setWinPosition?: boolean;
setWinSizePixels?: boolean;
raiseWin?: boolean;
lowerWin?: boolean;
refreshWin?: boolean;
setWinSizeChars?: boolean;
maximizeWin?: boolean;
fullscreenWin?: boolean;
getWinState?: boolean;
getWinPosition?: boolean;
getWinSizePixels?: boolean;
getScreenSizePixels?: boolean;
getCellSizePixels?: boolean;
getWinSizeChars?: boolean;
getScreenSizeChars?: boolean;
getIconTitle?: boolean;
getWinTitle?: boolean;
pushTitle?: boolean;
popTitle?: boolean;
setWinLines?: boolean;
}
// color events from common, used for OSC 4/10/11/12 and 104/110/111/112
export const enum ColorRequestType {
REPORT = 0,
SET = 1,
RESTORE = 2
}
// IntRange from https://stackoverflow.com/a/39495173
type Enumerate<N extends number, Acc extends number[] = []> = Acc['length'] extends N
? Acc[number]
: Enumerate<N, [...Acc, Acc['length']]>;
type IntRange<F extends number, T extends number> = Exclude<Enumerate<T>, Enumerate<F>>;
type ColorIndex = IntRange<0, 256>; // number from 0 to 255
type AllColorIndex = ColorIndex | SpecialColorIndex;
export const enum SpecialColorIndex {
FOREGROUND = 256,
BACKGROUND = 257,
CURSOR = 258
}
export interface IColorReportRequest {
type: ColorRequestType.REPORT;
index: AllColorIndex;
}
export interface IColorSetRequest {
type: ColorRequestType.SET;
index: AllColorIndex;
color: IColorRGB;
}
export interface IColorRestoreRequest {
type: ColorRequestType.RESTORE;
index?: AllColorIndex;
}
export type IColorEvent = (IColorReportRequest | IColorSetRequest | IColorRestoreRequest)[];
/**
* Calls the parser and handles actions generated by the parser.
*/
export interface IInputHandler {
onTitleChange: IEvent<string>;
parse(data: string | Uint8Array, promiseResult?: boolean): void | Promise<boolean>;
print(data: Uint32Array, start: number, end: number): void;
registerCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean | Promise<boolean>): IDisposable;
registerDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean | Promise<boolean>): IDisposable;
registerEscHandler(id: IFunctionIdentifier, callback: () => boolean | Promise<boolean>): IDisposable;
registerOscHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable;
/** C0 BEL */ bell(): boolean;
/** C0 LF */ lineFeed(): boolean;
/** C0 CR */ carriageReturn(): boolean;
/** C0 BS */ backspace(): boolean;
/** C0 HT */ tab(): boolean;
/** C0 SO */ shiftOut(): boolean;
/** C0 SI */ shiftIn(): boolean;
/** CSI @ */ insertChars(params: IParams): boolean;
/** CSI SP @ */ scrollLeft(params: IParams): boolean;
/** CSI A */ cursorUp(params: IParams): boolean;
/** CSI SP A */ scrollRight(params: IParams): boolean;
/** CSI B */ cursorDown(params: IParams): boolean;
/** CSI C */ cursorForward(params: IParams): boolean;
/** CSI D */ cursorBackward(params: IParams): boolean;
/** CSI E */ cursorNextLine(params: IParams): boolean;
/** CSI F */ cursorPrecedingLine(params: IParams): boolean;
/** CSI G */ cursorCharAbsolute(params: IParams): boolean;
/** CSI H */ cursorPosition(params: IParams): boolean;
/** CSI I */ cursorForwardTab(params: IParams): boolean;
/** CSI J */ eraseInDisplay(params: IParams): boolean;
/** CSI K */ eraseInLine(params: IParams): boolean;
/** CSI L */ insertLines(params: IParams): boolean;
/** CSI M */ deleteLines(params: IParams): boolean;
/** CSI P */ deleteChars(params: IParams): boolean;
/** CSI S */ scrollUp(params: IParams): boolean;
/** CSI T */ scrollDown(params: IParams, collect?: string): boolean;
/** CSI X */ eraseChars(params: IParams): boolean;
/** CSI Z */ cursorBackwardTab(params: IParams): boolean;
/** CSI ` */ charPosAbsolute(params: IParams): boolean;
/** CSI a */ hPositionRelative(params: IParams): boolean;
/** CSI b */ repeatPrecedingCharacter(params: IParams): boolean;
/** CSI c */ sendDeviceAttributesPrimary(params: IParams): boolean;
/** CSI > c */ sendDeviceAttributesSecondary(params: IParams): boolean;
/** CSI d */ linePosAbsolute(params: IParams): boolean;
/** CSI e */ vPositionRelative(params: IParams): boolean;
/** CSI f */ hVPosition(params: IParams): boolean;
/** CSI g */ tabClear(params: IParams): boolean;
/** CSI h */ setMode(params: IParams, collect?: string): boolean;
/** CSI l */ resetMode(params: IParams, collect?: string): boolean;
/** CSI m */ charAttributes(params: IParams): boolean;
/** CSI n */ deviceStatus(params: IParams, collect?: string): boolean;
/** CSI p */ softReset(params: IParams, collect?: string): boolean;
/** CSI q */ setCursorStyle(params: IParams, collect?: string): boolean;
/** CSI r */ setScrollRegion(params: IParams, collect?: string): boolean;
/** CSI s */ saveCursor(params: IParams): boolean;
/** CSI u */ restoreCursor(params: IParams): boolean;
/** CSI ' } */ insertColumns(params: IParams): boolean;
/** CSI ' ~ */ deleteColumns(params: IParams): boolean;
/** OSC 0
OSC 2 */ setTitle(data: string): boolean;
/** OSC 4 */ setOrReportIndexedColor(data: string): boolean;
/** OSC 10 */ setOrReportFgColor(data: string): boolean;
/** OSC 11 */ setOrReportBgColor(data: string): boolean;
/** OSC 12 */ setOrReportCursorColor(data: string): boolean;
/** OSC 104 */ restoreIndexedColor(data: string): boolean;
/** OSC 110 */ restoreFgColor(data: string): boolean;
/** OSC 111 */ restoreBgColor(data: string): boolean;
/** OSC 112 */ restoreCursorColor(data: string): boolean;
/** ESC E */ nextLine(): boolean;
/** ESC = */ keypadApplicationMode(): boolean;
/** ESC > */ keypadNumericMode(): boolean;
/** ESC % G
ESC % @ */ selectDefaultCharset(): boolean;
/** ESC ( C
ESC ) C
ESC * C
ESC + C
ESC - C
ESC . C
ESC / C */ selectCharset(collectAndFlag: string): boolean;
/** ESC D */ index(): boolean;
/** ESC H */ tabSet(): boolean;
/** ESC M */ reverseIndex(): boolean;
/** ESC c */ fullReset(): boolean;
/** ESC n
ESC o
ESC |
ESC }
ESC ~ */ setgLevel(level: number): boolean;
/** ESC # 8 */ screenAlignmentPattern(): boolean;
}
export interface IParseStack {
paused: boolean;
cursorStartX: number;
cursorStartY: number;
decodedLength: number;
position: number;
}