Type InputHandler._terminal

This commit is contained in:
Daniel Imms
2017-08-05 12:57:29 -07:00
parent 8a0bcf6b79
commit aee474b53e
7 changed files with 139 additions and 70 deletions
+2 -2
View File
@@ -2,7 +2,7 @@
* @license MIT
*/
import { ITerminal } from './Interfaces';
import { ITerminal, IBuffer } from './Interfaces';
import { CircularList } from './utils/CircularList';
/**
@@ -12,7 +12,7 @@ import { CircularList } from './utils/CircularList';
* - cursor position
* - scroll position
*/
export class Buffer {
export class Buffer implements IBuffer {
public lines: CircularList<[number, string, number][]>;
public savedY: number;
+3 -2
View File
@@ -5,7 +5,8 @@ import { wcwidth } from './InputHandler';
describe('InputHandler', () => {
describe('save and restore cursor', () => {
let terminal = { buffer: { x: 1, y: 2 } };
let inputHandler = new InputHandler(terminal);
// TODO: Create proper mock IInputHandlingTerminal test util object
let inputHandler = new InputHandler(<any>terminal);
// Save cursor position
inputHandler.saveCursor([]);
assert.equal(terminal.buffer.x, 1);
@@ -24,7 +25,7 @@ describe('InputHandler', () => {
let terminal = {
setOption: (option, value) => options[option] = value
};
let inputHandler = new InputHandler(terminal);
let inputHandler = new InputHandler(<any>terminal);
inputHandler.setCursorStyle([0]);
assert.equal(options['cursorStyle'], 'block');
+10 -10
View File
@@ -2,7 +2,7 @@
* @license MIT
*/
import { IInputHandler, ITerminal } from './Interfaces';
import { IInputHandler, ITerminal, IInputHandlingTerminal } from './Interfaces';
import { C0 } from './EscapeSequences';
import { DEFAULT_CHARSET } from './Charsets';
@@ -15,7 +15,7 @@ import { DEFAULT_CHARSET } from './Charsets';
*/
export class InputHandler implements IInputHandler {
// TODO: We want to type _terminal when it's pulled into TS
constructor(private _terminal: any) { }
constructor(private _terminal: IInputHandlingTerminal) { }
public addChar(char: string, code: number): void {
if (char >= ' ') {
@@ -61,7 +61,7 @@ export class InputHandler implements IInputHandler {
} else {
// The line already exists (eg. the initial viewport), mark it as a
// wrapped line
this._terminal.buffer.lines.get(this._terminal.buffer.y).isWrapped = true;
(<any>this._terminal.buffer.lines.get(this._terminal.buffer.y)).isWrapped = true;
}
} else {
if (ch_width === 2) // FIXME: check for xterm behavior
@@ -105,12 +105,12 @@ export class InputHandler implements IInputHandler {
* Bell (Ctrl-G).
*/
public bell(): void {
if (!this._terminal.visualBell) {
if (!this._terminal.options.visualBell) {
return;
}
this._terminal.element.style.borderColor = 'white';
setTimeout(() => this._terminal.element.style.borderColor = '', 10);
if (this._terminal.popOnBell) {
if (this._terminal.options.popOnBell) {
this._terminal.focus();
}
}
@@ -194,7 +194,7 @@ export class InputHandler implements IInputHandler {
const row = this._terminal.buffer.y + this._terminal.buffer.ybase;
let j = this._terminal.buffer.x;
const ch = [this._terminal.eraseAttr(), ' ', 1]; // xterm
const ch: [number, string, number] = [this._terminal.eraseAttr(), ' ', 1]; // xterm
while (param-- && j < this._terminal.cols) {
this._terminal.buffer.lines.get(row).splice(j++, 0, ch);
@@ -510,7 +510,7 @@ export class InputHandler implements IInputHandler {
}
const row = this._terminal.buffer.y + this._terminal.buffer.ybase;
const ch = [this._terminal.eraseAttr(), ' ', 1]; // xterm
const ch: [number, string, number] = [this._terminal.eraseAttr(), ' ', 1]; // xterm
while (param--) {
this._terminal.buffer.lines.get(row).splice(this._terminal.buffer.x, 1);
@@ -558,7 +558,7 @@ export class InputHandler implements IInputHandler {
const row = this._terminal.buffer.y + this._terminal.buffer.ybase;
let j = this._terminal.buffer.x;
const ch = [this._terminal.eraseAttr(), ' ', 1]; // xterm
const ch: [number, string, number] = [this._terminal.eraseAttr(), ' ', 1]; // xterm
while (param-- && j < this._terminal.cols) {
this._terminal.buffer.lines.get(row)[j++] = ch;
@@ -858,7 +858,7 @@ export class InputHandler implements IInputHandler {
this._terminal.insertMode = true;
break;
case 20:
// this._terminal.convertEol = true;
// this._t.convertEol = true;
break;
}
} else if (this._terminal.prefix === '?') {
@@ -1050,7 +1050,7 @@ export class InputHandler implements IInputHandler {
this._terminal.insertMode = false;
break;
case 20:
// this._terminal.convertEol = false;
// this._t.convertEol = false;
break;
}
} else if (this._terminal.prefix === '?') {
+77 -3
View File
@@ -3,7 +3,7 @@
*/
import { LinkMatcherOptions } from './Interfaces';
import { LinkMatcherHandler, LinkMatcherValidationCallback } from './Types';
import { LinkMatcherHandler, LinkMatcherValidationCallback, Charset } from './Types';
export interface IBrowser {
isNode: boolean;
@@ -17,7 +17,7 @@ export interface IBrowser {
isMSWindows: boolean;
}
export interface ITerminal {
export interface ITerminal extends IEventEmitter {
element: HTMLElement;
rowContainer: HTMLElement;
selectionContainer: HTMLElement;
@@ -45,11 +45,73 @@ export interface ITerminal {
scrollDisp(disp: number, suppressScrollEvent: boolean);
cancel(ev: Event, force?: boolean);
log(text: string): void;
emit(event: string, data: any);
reset(): void;
showCursor(): void;
}
/**
* This interface encapsulates everything needed from the Terminal by the
* InputHandler. This cleanly separates the large amount of methods needed by
* InputHandler cleanly from the ITerminal interface.
*/
export interface IInputHandlingTerminal extends IEventEmitter {
element: HTMLElement;
options: ITerminalOptions;
cols: number;
rows: number;
charset: Charset;
gcharset: number;
glevel: number;
charsets: Charset[];
applicationKeypad: boolean;
applicationCursor: boolean;
originMode: boolean;
insertMode: boolean;
wraparoundMode: boolean;
defAttr: number;
curAttr: number;
prefix: string;
savedCols: number;
x10Mouse: boolean;
vt200Mouse: boolean;
normalMouse: boolean;
mouseEvents: boolean;
sendFocus: boolean;
utfMouse: boolean;
sgrMouse: boolean;
urxvtMouse: boolean;
cursorHidden: boolean;
buffers: IBufferSet;
buffer: IBuffer;
viewport: IViewport;
selectionManager: ISelectionManager;
focus(): void;
convertEol: boolean;
updateRange(y: number): void;
scroll(isWrapped?: boolean): void;
nextStop(x?: number): number;
setgLevel(g: number): void;
eraseAttr(): any;
eraseRight(x: number, y: number): void;
eraseLine(y: number): void;
eraseLeft(x: number, y: number): void;
blankLine(cur?: boolean, isWrapped?: boolean): [number, string, number][];
prevStop(x?: number): number;
is(term: string): boolean;
send(data: string): void;
setgCharset(g: number, charset: Charset): void;
resize(x: number, y: number): void;
log(text: string, data?: any): void;
reset(): void;
showCursor(): void;
refresh(start: number, end: number): void;
matchColor(r1, g1, b1): any;
error(text: string, data?: any): void;
setOption(key: string, value: any): void;
}
export interface ITerminalOptions {
cancelEvents?: boolean;
colors?: string[];
@@ -78,6 +140,10 @@ export interface IBuffer {
y: number;
x: number;
tabs: any;
scrollBottom: number;
scrollTop: number;
savedY: number;
savedX: number;
}
export interface IBufferSet {
@@ -89,11 +155,18 @@ export interface IBufferSet {
activateAltBuffer(): void;
}
export interface IViewport {
syncScrollArea(): void;
}
export interface ISelectionManager {
selectionText: string;
selectionStart: [number, number];
selectionEnd: [number, number];
disable(): void;
enable(): void;
setBuffer(buffer: ICircularList<[number, string, number][]>): void;
setSelection(row: number, col: number, length: number);
}
@@ -127,6 +200,7 @@ export interface ICircularList<T> extends IEventEmitter {
export interface IEventEmitter {
on(type, listener): void;
off(type, listener): void;
emit(type: string, data?: any): void;
}
export interface LinkMatcherOptions {
+2 -2
View File
@@ -133,7 +133,7 @@ export class SelectionManager extends EventEmitter {
* Disables the selection manager. This is useful for when terminal mouse
* are enabled.
*/
public disable() {
public disable(): void {
this.clearSelection();
this._enabled = false;
}
@@ -141,7 +141,7 @@ export class SelectionManager extends EventEmitter {
/**
* Enable the selection manager.
*/
public enable() {
public enable(): void {
this._enabled = true;
}
+43 -49
View File
@@ -30,7 +30,7 @@ import { CHARSETS } from './Charsets';
import { getRawByteCoords } from './utils/Mouse';
import { translateBufferLineToString } from './utils/BufferLine';
import { CustomKeyEventHandler, Charset } from './Types';
import { ITerminal, IBrowser, ITerminalOptions } from './Interfaces';
import { ITerminal, IBrowser, ITerminalOptions, IInputHandlingTerminal } from './Interfaces';
// Declare for RequireJS in loadAddon
declare var define: any;
@@ -163,7 +163,7 @@ const DEFAULT_OPTIONS: ITerminalOptions = {
// focusKeys: false,
};
export class Terminal extends EventEmitter implements ITerminal {
export class Terminal extends EventEmitter implements ITerminal, IInputHandlingTerminal {
public textarea: HTMLTextAreaElement;
public element: HTMLElement;
public rowContainer: HTMLElement;
@@ -193,7 +193,7 @@ export class Terminal extends EventEmitter implements ITerminal {
// TODO: This can be changed to an enum or boolean, 0 and 1 seem to be the only options
public cursorState: number;
public cursorHidden: boolean;
private convertEol: boolean;
public convertEol: boolean;
// TODO: This is the data queue for send, improve name and documentation
private queue: string;
private customKeyEventHandler: CustomKeyEventHandler;
@@ -203,36 +203,36 @@ export class Terminal extends EventEmitter implements ITerminal {
private cursorBlinkInterval: NodeJS.Timer;
// modes
private applicationKeypad: boolean;
private applicationCursor: boolean;
private originMode: boolean;
private insertMode: boolean;
private wraparoundMode: boolean; // defaults: xterm - true, vt100 - false
public applicationKeypad: boolean;
public applicationCursor: boolean;
public originMode: boolean;
public insertMode: boolean;
public wraparoundMode: boolean; // defaults: xterm - true, vt100 - false
// charset
// The current charset
private charset: Charset;
private gcharset: number;
private glevel: number;
private charsets: Charset[];
public charset: Charset;
public gcharset: number;
public glevel: number;
public charsets: Charset[];
// mouse properties
private decLocator: boolean; // This is unstable and never set
private x10Mouse: boolean;
private vt200Mouse: boolean;
public x10Mouse: boolean;
public vt200Mouse: boolean;
private vt300Mouse: boolean; // This is unstable and never set
private normalMouse: boolean;
private mouseEvents: boolean;
private sendFocus: boolean;
private utfMouse: boolean;
private sgrMouse: boolean;
private urxvtMouse: boolean;
public normalMouse: boolean;
public mouseEvents: boolean;
public sendFocus: boolean;
public utfMouse: boolean;
public sgrMouse: boolean;
public urxvtMouse: boolean;
// misc
public children: HTMLElement[];
private refreshStart: number;
private refreshEnd: number;
private savedCols: boolean;
public savedCols: number;
// stream
private readable: boolean;
@@ -274,7 +274,7 @@ export class Terminal extends EventEmitter implements ITerminal {
private linkifier: Linkifier;
public buffers: BufferSet;
public buffer: Buffer;
private viewport: Viewport;
public viewport: Viewport;
private compositionHelper: CompositionHelper;
public charMeasure: CharMeasure;
@@ -440,7 +440,7 @@ export class Terminal extends EventEmitter implements ITerminal {
* @param {string} key The option key.
* @param {any} value The option value.
*/
public setOption(key: string, value: any) {
public setOption(key: string, value: any): void {
// TODO: Give value a better type (boolean | string, ...)
if (!(key in DEFAULT_OPTIONS)) {
throw new Error('No option with key "' + key + '"');
@@ -453,7 +453,7 @@ export class Terminal extends EventEmitter implements ITerminal {
msg += `(${this.rows}) is not allowed.`;
console.warn(msg);
return false;
return;
}
if (this.options[key] !== value) {
@@ -1167,7 +1167,7 @@ export class Terminal extends EventEmitter implements ITerminal {
/**
* Display the cursor element
*/
public showCursor() {
public showCursor(): void {
if (!this.cursorState) {
this.cursorState = 1;
this.refresh(this.buffer.y, this.buffer.y);
@@ -1882,7 +1882,7 @@ export class Terminal extends EventEmitter implements ITerminal {
* Send data for handling to the terminal
* @param {string} data
*/
private send(data) {
public send(data: string): void {
if (!this.queue) {
setTimeout(() => {
this.handler(this.queue);
@@ -1909,21 +1909,19 @@ export class Terminal extends EventEmitter implements ITerminal {
/**
* Log the current state to the console.
*/
public log(): void {
public log(text: string, data?: any): void {
if (!this.options.debug) return;
if (!this.context.console || !this.context.console.log) return;
const args = Array.prototype.slice.call(arguments);
this.context.console.log.apply(this.context.console, args);
this.context.console.log(text, data);
}
/**
* Log the current state as error to the console.
*/
public error(): void {
public error(text: string, data?: any): void {
if (!this.options.debug) return;
if (!this.context.console || !this.context.console.error) return;
const args = Array.prototype.slice.call(arguments);
this.context.console.error.apply(this.context.console, args);
this.context.console.error(text, data);
}
/**
@@ -1932,7 +1930,7 @@ export class Terminal extends EventEmitter implements ITerminal {
* @param {number} x The number of columns to resize to.
* @param {number} y The number of rows to resize to.
*/
public resize(x: number, y: number) {
public resize(x: number, y: number): void {
if (isNaN(x) || isNaN(y)) {
return;
}
@@ -2052,7 +2050,7 @@ export class Terminal extends EventEmitter implements ITerminal {
* Updates the range of rows to refresh
* @param {number} y The number of rows to refresh next.
*/
public updateRange(y) {
public updateRange(y: number): void {
if (y < this.refreshStart) this.refreshStart = y;
if (y > this.refreshEnd) this.refreshEnd = y;
// if (y > this.refreshEnd) {
@@ -2094,7 +2092,7 @@ export class Terminal extends EventEmitter implements ITerminal {
* Move the cursor to the previous tab stop from the given position (default is current).
* @param {number} x The position to move the cursor to the previous tab stop.
*/
public prevStop(x) {
public prevStop(x?: number): number {
if (x == null) x = this.buffer.x;
while (!this.buffer.tabs[--x] && x > 0);
return x >= this.cols ? this.cols - 1 : x < 0 ? 0 : x;
@@ -2104,12 +2102,10 @@ export class Terminal extends EventEmitter implements ITerminal {
* Move the cursor one tab stop forward from the given position (default is current).
* @param {number} x The position to move the cursor one tab stop forward.
*/
public nextStop(x) {
public nextStop(x?: number): number {
if (x == null) x = this.buffer.x;
while (!this.buffer.tabs[++x] && x < this.cols);
return x >= this.cols
? this.cols - 1
: x < 0 ? 0 : x;
return x >= this.cols ? this.cols - 1 : x < 0 ? 0 : x;
}
/**
@@ -2134,7 +2130,7 @@ export class Terminal extends EventEmitter implements ITerminal {
* @param {number} x The column from which to start erasing to the start of the line.
* @param {number} y The line in which to operate.
*/
public eraseLeft(x: number, y: number) {
public eraseLeft(x: number, y: number): void {
const line = this.buffer.lines.get(this.buffer.ybase + y);
if (!line) {
return;
@@ -2171,7 +2167,7 @@ export class Terminal extends EventEmitter implements ITerminal {
* Erase all content in the given line
* @param {number} y The line to erase all of its contents.
*/
public eraseLine(y): void {
public eraseLine(y: number): void {
this.eraseRight(0, y);
}
@@ -2180,7 +2176,7 @@ export class Terminal extends EventEmitter implements ITerminal {
* @param {boolean} cur First bunch of data for each "blank" character.
* @param {boolean} isWrapped Whether the new line is wrapped from the previous line.
*/
public blankLine(cur?, isWrapped?: boolean) {
public blankLine(cur?: boolean, isWrapped?: boolean): [number, string, number][] {
const attr = cur ? this.eraseAttr() : this.defAttr;
const ch = [attr, ' ', 1]; // width defaults to 1 halfwidth character
@@ -2209,12 +2205,10 @@ export class Terminal extends EventEmitter implements ITerminal {
/**
* Evaluate if the current terminal is the given argument.
* @param {object} term The terminal to evaluate
* @param term The terminal name to evaluate
*/
private is(term) {
// TODO: Do we need this?
const name = this.options.termName;
return (name + '').indexOf(term) === 0;
public is(term: string): boolean {
return (this.options.termName + '').indexOf(term) === 0;
}
/**
@@ -2294,7 +2288,7 @@ export class Terminal extends EventEmitter implements ITerminal {
/**
* ESC c Full Reset (RIS).
*/
public reset() {
public reset(): void {
this.options.rows = this.rows;
this.options.cols = this.cols;
const customKeyEventHandler = this.customKeyEventHandler;
@@ -2329,7 +2323,7 @@ export class Terminal extends EventEmitter implements ITerminal {
// Expose to InputHandler
// TODO: Revise when truecolor is introduced.
public matchColor(r1, g1, b1) {
public matchColor(r1, g1, b1): any {
const hash = (r1 << 16) | (g1 << 8) | b1;
if (matchColorCache[hash] != null) {
+2 -2
View File
@@ -2,14 +2,14 @@
* @license MIT
*/
import { ITerminal } from './Interfaces';
import { ITerminal, IViewport } from './Interfaces';
import { CharMeasure } from './utils/CharMeasure';
/**
* Represents the viewport of a terminal, the visible area within the larger buffer of output.
* Logic for the virtual scroll bar is included in this object.
*/
export class Viewport {
export class Viewport implements IViewport {
private currentRowHeight: number;
private lastRecordedBufferLength: number;
private lastRecordedViewportHeight: number;