Use Terminal type in attach, fit and fullscreen
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*
|
||||
* Implements the attach method, that attaches the terminal to a WebSocket stream.
|
||||
*/
|
||||
|
||||
import { Terminal } from 'xterm';
|
||||
|
||||
export interface IAttachAddonTerminal extends Terminal {
|
||||
__socket?: WebSocket;
|
||||
__attachSocketBuffer?: string;
|
||||
|
||||
__getMessage?(ev: MessageEvent): void;
|
||||
__flushBuffer?(): void;
|
||||
__pushToBuffer?(data: string): void;
|
||||
__sendData?(data: string): void;
|
||||
}
|
||||
@@ -12,7 +12,7 @@ class MockTerminal {}
|
||||
describe('attach addon', () => {
|
||||
describe('apply', () => {
|
||||
it('should do register the `attach` and `detach` methods', () => {
|
||||
attach.apply(MockTerminal);
|
||||
attach.apply(<any>MockTerminal);
|
||||
assert.equal(typeof (<any>MockTerminal).prototype.attach, 'function');
|
||||
assert.equal(typeof (<any>MockTerminal).prototype.detach, 'function');
|
||||
});
|
||||
|
||||
+45
-44
@@ -5,38 +5,42 @@
|
||||
* Implements the attach method, that attaches the terminal to a WebSocket stream.
|
||||
*/
|
||||
|
||||
/// <reference path="../../../typings/xterm.d.ts"/>
|
||||
|
||||
import { Terminal } from 'xterm';
|
||||
import { IAttachAddonTerminal } from './Intefaces';
|
||||
|
||||
/**
|
||||
* Attaches the given terminal to the given socket.
|
||||
*
|
||||
* @param {Terminal} term - The terminal to be attached to the given socket.
|
||||
* @param {WebSocket} socket - The socket to attach the current terminal.
|
||||
* @param {boolean} bidirectional - Whether the terminal should send data
|
||||
* to the socket as well.
|
||||
* @param {boolean} buffered - Whether the rendering of incoming data
|
||||
* should happen instantly or at a maximum
|
||||
* frequency of 1 rendering per 10ms.
|
||||
* @param term The terminal to be attached to the given socket.
|
||||
* @param socket The socket to attach the current terminal.
|
||||
* @param bidirectional Whether the terminal should send data to the socket as well.
|
||||
* @param buffered Whether the rendering of incoming data should happen instantly or at a maximum
|
||||
* frequency of 1 rendering per 10ms.
|
||||
*/
|
||||
export function attach(term: any, socket: WebSocket, bidirectional: boolean, buffered: boolean): void {
|
||||
export function attach(term: Terminal, socket: WebSocket, bidirectional: boolean, buffered: boolean): void {
|
||||
const addonTerminal = <IAttachAddonTerminal>term;
|
||||
bidirectional = (typeof bidirectional === 'undefined') ? true : bidirectional;
|
||||
term.socket = socket;
|
||||
addonTerminal.__socket = socket;
|
||||
|
||||
term._flushBuffer = () => {
|
||||
term.write(term._attachSocketBuffer);
|
||||
term._attachSocketBuffer = null;
|
||||
addonTerminal.__flushBuffer = () => {
|
||||
addonTerminal.write(addonTerminal.__attachSocketBuffer);
|
||||
addonTerminal.__attachSocketBuffer = null;
|
||||
};
|
||||
|
||||
term._pushToBuffer = (data: string) => {
|
||||
if (term._attachSocketBuffer) {
|
||||
term._attachSocketBuffer += data;
|
||||
addonTerminal.__pushToBuffer = (data: string) => {
|
||||
if (addonTerminal.__attachSocketBuffer) {
|
||||
addonTerminal.__attachSocketBuffer += data;
|
||||
} else {
|
||||
term._attachSocketBuffer = data;
|
||||
setTimeout(term._flushBuffer, 10);
|
||||
addonTerminal.__attachSocketBuffer = data;
|
||||
setTimeout(addonTerminal.__flushBuffer, 10);
|
||||
}
|
||||
};
|
||||
|
||||
let myTextDecoder;
|
||||
|
||||
term._getMessage = function(ev: MessageEvent): void {
|
||||
addonTerminal.__getMessage = function(ev: MessageEvent): void {
|
||||
let str;
|
||||
if (typeof ev.data === 'object') {
|
||||
if (ev.data instanceof ArrayBuffer) {
|
||||
@@ -51,71 +55,68 @@ export function attach(term: any, socket: WebSocket, bidirectional: boolean, buf
|
||||
}
|
||||
|
||||
if (buffered) {
|
||||
term._pushToBuffer(str || ev.data);
|
||||
addonTerminal.__pushToBuffer(str || ev.data);
|
||||
} else {
|
||||
term.write(str || ev.data);
|
||||
addonTerminal.write(str || ev.data);
|
||||
}
|
||||
};
|
||||
|
||||
term._sendData = (data: string) => {
|
||||
addonTerminal.__sendData = (data: string) => {
|
||||
if (socket.readyState !== 1) {
|
||||
return;
|
||||
}
|
||||
socket.send(data);
|
||||
};
|
||||
|
||||
socket.addEventListener('message', term._getMessage);
|
||||
socket.addEventListener('message', addonTerminal.__getMessage);
|
||||
|
||||
if (bidirectional) {
|
||||
term.on('data', term._sendData);
|
||||
addonTerminal.on('data', addonTerminal.__sendData);
|
||||
}
|
||||
|
||||
socket.addEventListener('close', term.detach.bind(term, socket));
|
||||
socket.addEventListener('error', term.detach.bind(term, socket));
|
||||
socket.addEventListener('close', () => detach(addonTerminal, socket));
|
||||
socket.addEventListener('error', () => detach(addonTerminal, socket));
|
||||
}
|
||||
|
||||
/**
|
||||
* Detaches the given terminal from the given socket
|
||||
*
|
||||
* @param {Terminal} term - The terminal to be detached from the given socket.
|
||||
* @param {WebSocket} socket - The socket from which to detach the current
|
||||
* terminal.
|
||||
* @param term The terminal to be detached from the given socket.
|
||||
* @param socket The socket from which to detach the current terminal.
|
||||
*/
|
||||
export function detach(term: any, socket: WebSocket): void {
|
||||
term.off('data', term._sendData);
|
||||
export function detach(term: Terminal, socket: WebSocket): void {
|
||||
const addonTerminal = <IAttachAddonTerminal>term;
|
||||
addonTerminal.off('data', addonTerminal.__sendData);
|
||||
|
||||
socket = (typeof socket === 'undefined') ? term.socket : socket;
|
||||
socket = (typeof socket === 'undefined') ? addonTerminal.__socket : socket;
|
||||
|
||||
if (socket) {
|
||||
socket.removeEventListener('message', term._getMessage);
|
||||
socket.removeEventListener('message', addonTerminal.__getMessage);
|
||||
}
|
||||
|
||||
delete term.socket;
|
||||
delete addonTerminal.__socket;
|
||||
}
|
||||
|
||||
|
||||
export function apply(terminalConstructor: any): void {
|
||||
export function apply(terminalConstructor: typeof Terminal): void {
|
||||
/**
|
||||
* Attaches the current terminal to the given socket
|
||||
*
|
||||
* @param {WebSocket} socket - The socket to attach the current terminal.
|
||||
* @param {boolean} bidirectional - Whether the terminal should send data
|
||||
* to the socket as well.
|
||||
* @param {boolean} buffered - Whether the rendering of incoming data
|
||||
* should happen instantly or at a maximum
|
||||
* frequency of 1 rendering per 10ms.
|
||||
* @param socket The socket to attach the current terminal.
|
||||
* @param bidirectional Whether the terminal should send data to the socket as well.
|
||||
* @param buffered Whether the rendering of incoming data should happen instantly or at a maximum
|
||||
* frequency of 1 rendering per 10ms.
|
||||
*/
|
||||
terminalConstructor.prototype.attach = function (socket: WebSocket, bidirectional: boolean, buffered: boolean): void {
|
||||
(<any>terminalConstructor.prototype).attach = function (socket: WebSocket, bidirectional: boolean, buffered: boolean): void {
|
||||
attach(this, socket, bidirectional, buffered);
|
||||
};
|
||||
|
||||
/**
|
||||
* Detaches the current terminal from the given socket.
|
||||
*
|
||||
* @param {WebSocket} socket - The socket from which to detach the current
|
||||
* terminal.
|
||||
* @param socket The socket from which to detach the current terminal.
|
||||
*/
|
||||
terminalConstructor.prototype.detach = function (socket: WebSocket): void {
|
||||
(<any>terminalConstructor.prototype).detach = function (socket: WebSocket): void {
|
||||
detach(this, socket);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ class MockTerminal {}
|
||||
describe('fit addon', () => {
|
||||
describe('apply', () => {
|
||||
it('should do register the `proposeGeometry` and `fit` methods', () => {
|
||||
fit.apply(MockTerminal);
|
||||
fit.apply(<any>MockTerminal);
|
||||
assert.equal(typeof (<any>MockTerminal).prototype.proposeGeometry, 'function');
|
||||
assert.equal(typeof (<any>MockTerminal).prototype.fit, 'function');
|
||||
});
|
||||
|
||||
+12
-8
@@ -13,12 +13,16 @@
|
||||
* row and truncate its width with the current number of columns).
|
||||
*/
|
||||
|
||||
/// <reference path="../../../typings/xterm.d.ts"/>
|
||||
|
||||
import { Terminal } from 'xterm';
|
||||
|
||||
export interface IGeometry {
|
||||
rows: number;
|
||||
cols: number;
|
||||
}
|
||||
|
||||
export function proposeGeometry(term: any): IGeometry {
|
||||
export function proposeGeometry(term: Terminal): IGeometry {
|
||||
if (!term.element.parentElement) {
|
||||
return null;
|
||||
}
|
||||
@@ -31,30 +35,30 @@ export function proposeGeometry(term: any): IGeometry {
|
||||
const availableHeight = parentElementHeight - elementPaddingVer;
|
||||
const availableWidth = parentElementWidth - elementPaddingHor;
|
||||
const geometry = {
|
||||
cols: Math.floor(availableWidth / term.renderer.dimensions.actualCellWidth),
|
||||
rows: Math.floor(availableHeight / term.renderer.dimensions.actualCellHeight)
|
||||
cols: Math.floor(availableWidth / (<any>term).renderer.dimensions.actualCellWidth),
|
||||
rows: Math.floor(availableHeight / (<any>term).renderer.dimensions.actualCellHeight)
|
||||
};
|
||||
|
||||
return geometry;
|
||||
}
|
||||
|
||||
export function fit(term: any): void {
|
||||
export function fit(term: Terminal): void {
|
||||
const geometry = proposeGeometry(term);
|
||||
if (geometry) {
|
||||
// Force a full render
|
||||
if (term.rows !== geometry.rows || term.cols !== geometry.cols) {
|
||||
term.renderer.clear();
|
||||
(<any>term).renderer.clear();
|
||||
term.resize(geometry.cols, geometry.rows);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function apply(terminalConstructor: any): void {
|
||||
terminalConstructor.prototype.proposeGeometry = function (): IGeometry {
|
||||
export function apply(terminalConstructor: typeof Terminal): void {
|
||||
(<any>terminalConstructor.prototype).proposeGeometry = function (): IGeometry {
|
||||
return proposeGeometry(this);
|
||||
};
|
||||
|
||||
terminalConstructor.prototype.fit = function (): void {
|
||||
(<any>terminalConstructor.prototype).fit = function (): void {
|
||||
fit(this);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ class MockTerminal {}
|
||||
describe('fullscreen addon', () => {
|
||||
describe('apply', () => {
|
||||
it('should do register the `toggleFullscreen` method', () => {
|
||||
fullscreen.apply(MockTerminal);
|
||||
fullscreen.apply(<any>MockTerminal);
|
||||
assert.equal(typeof (<any>MockTerminal).prototype.toggleFullScreen, 'function');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,13 +3,17 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/// <reference path="../../../typings/xterm.d.ts"/>
|
||||
|
||||
import { Terminal } from 'xterm';
|
||||
|
||||
/**
|
||||
* Toggle the given terminal's fullscreen mode.
|
||||
* @param {Terminal} term - The terminal to toggle full screen mode
|
||||
* @param {boolean} fullscreen - Toggle fullscreen on (true) or off (false)
|
||||
* @param term The terminal to toggle full screen mode
|
||||
* @param fullscreen Toggle fullscreen on (true) or off (false)
|
||||
*/
|
||||
export function toggleFullScreen(term: any, fullscreen: boolean): void {
|
||||
let fn;
|
||||
export function toggleFullScreen(term: Terminal, fullscreen: boolean): void {
|
||||
let fn: string;
|
||||
|
||||
if (typeof fullscreen === 'undefined') {
|
||||
fn = (term.element.classList.contains('fullscreen')) ? 'remove' : 'add';
|
||||
@@ -22,8 +26,8 @@ export function toggleFullScreen(term: any, fullscreen: boolean): void {
|
||||
term.element.classList[fn]('fullscreen');
|
||||
}
|
||||
|
||||
export function apply(terminalConstructor: any): void {
|
||||
terminalConstructor.prototype.toggleFullScreen = function (fullscreen: boolean): void {
|
||||
export function apply(terminalConstructor: typeof Terminal): void {
|
||||
(<any>terminalConstructor.prototype).toggleFullScreen = function (fullscreen: boolean): void {
|
||||
toggleFullScreen(this, fullscreen);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { Terminal } from 'xterm';
|
||||
|
||||
export interface ISearchAddonTerminal extends Terminal {
|
||||
__searchHelper: ISearchHelper;
|
||||
__searchHelper?: ISearchHelper;
|
||||
|
||||
// TODO: Reuse ITerminal from core
|
||||
buffer: any;
|
||||
|
||||
@@ -16,7 +16,7 @@ import { ISearchAddonTerminal } from './Interfaces';
|
||||
* @return Whether a result was found.
|
||||
*/
|
||||
export function findNext(terminal: Terminal, term: string): boolean {
|
||||
const addonTerminal = (<ISearchAddonTerminal>terminal);
|
||||
const addonTerminal = <ISearchAddonTerminal>terminal;
|
||||
if (!addonTerminal.__searchHelper) {
|
||||
addonTerminal.__searchHelper = new SearchHelper(addonTerminal);
|
||||
}
|
||||
@@ -30,19 +30,19 @@ export function findNext(terminal: Terminal, term: string): boolean {
|
||||
* @return Whether a result was found.
|
||||
*/
|
||||
export function findPrevious(terminal: Terminal, term: string): boolean {
|
||||
const addonTerminal = (<ISearchAddonTerminal>terminal);
|
||||
const addonTerminal = <ISearchAddonTerminal>terminal;
|
||||
if (!addonTerminal.__searchHelper) {
|
||||
addonTerminal.__searchHelper = new SearchHelper(addonTerminal);
|
||||
}
|
||||
return addonTerminal.__searchHelper.findPrevious(term);
|
||||
}
|
||||
|
||||
export function apply(terminalConstructor: any): void {
|
||||
terminalConstructor.prototype.findNext = function(term: string): boolean {
|
||||
export function apply(terminalConstructor: typeof Terminal): void {
|
||||
(<any>terminalConstructor.prototype).findNext = function(term: string): boolean {
|
||||
return findNext(this, term);
|
||||
};
|
||||
|
||||
terminalConstructor.prototype.findPrevious = function(term: string): boolean {
|
||||
(<any>terminalConstructor.prototype).findPrevious = function(term: string): boolean {
|
||||
return findPrevious(this, term);
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user