forked from microsoft/node-pty
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathterminal.ts
More file actions
161 lines (129 loc) · 4.54 KB
/
Copy pathterminal.ts
File metadata and controls
161 lines (129 loc) · 4.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/**
* Copyright (c) 2012-2015, Christopher Jeffrey (MIT License)
* Copyright (c) 2016, Daniel Imms (MIT License).
*/
import * as path from 'path';
import { Socket } from 'net';
import { EventEmitter } from 'events';
import { ITerminal, IPtyForkOptions } from './interfaces';
export const DEFAULT_COLS: number = 80;
export const DEFAULT_ROWS: number = 24;
export abstract class Terminal implements ITerminal {
protected _socket: Socket;
protected _pid: number;
protected _fd: number;
protected _pty: any;
protected _file: string;
protected _name: string;
protected _cols: number;
protected _rows: number;
protected _readable: boolean;
protected _writable: boolean;
protected _internalee: EventEmitter;
public get pid(): number { return this._pid; }
constructor(opt?: IPtyForkOptions) {
// for 'close'
this._internalee = new EventEmitter();
if (!opt) {
return;
}
// Do basic type checks here in case node-pty is being used within JavaScript. If the wrong
// types go through to the C++ side it can lead to hard to diagnose exceptions.
this._checkType('name', opt.name ? opt.name : null, 'string');
this._checkType('cols', opt.cols ? opt.cols : null, 'number');
this._checkType('rows', opt.rows ? opt.rows : null, 'number');
this._checkType('cwd', opt.cwd ? opt.cwd : null, 'string');
this._checkType('env', opt.env ? opt.env : null, 'object');
this._checkType('uid', opt.uid ? opt.uid : null, 'number');
this._checkType('gid', opt.gid ? opt.gid : null, 'number');
this._checkType('encoding', opt.encoding ? opt.encoding : null, 'string');
}
private _checkType(name: string, value: any, type: string): void {
if (value && typeof value !== type) {
throw new Error(`${name} must be a ${type} (not a ${typeof value})`);
}
}
/** See net.Socket.end */
public end(data: string): void {
this._socket.end(data);
}
/** See stream.Readable.pipe */
public pipe(dest: any, options: any): any {
return this._socket.pipe(dest, options);
}
/** See net.Socket.pause */
public pause(): Socket {
return this._socket.pause();
}
/** See net.Socket.resume */
public resume(): Socket {
return this._socket.resume();
}
/** See net.Socket.setEncoding */
public setEncoding(encoding: string): void {
if ((<any>this._socket)._decoder) {
delete (<any>this._socket)._decoder;
}
if (encoding) {
this._socket.setEncoding(encoding);
}
}
public addListener(eventName: string, listener: (...args: any[]) => any): void { this.on(eventName, listener); }
public on(eventName: string, listener: (...args: any[]) => any): void {
if (eventName === 'close') {
this._internalee.on('close', listener);
return;
}
this._socket.on(eventName, listener);
}
public emit(eventName: string, ...args: any[]): any {
if (eventName === 'close') {
return this._internalee.emit.apply(this._internalee, arguments);
}
return this._socket.emit.apply(this._socket, arguments);
}
public listeners(eventName: string): Function[] {
return this._socket.listeners(eventName);
}
public removeListener(eventName: string, listener: (...args: any[]) => any): void {
this._socket.removeListener(eventName, listener);
}
public removeAllListeners(eventName: string): void {
this._socket.removeAllListeners(eventName);
}
public once(eventName: string, listener: (...args: any[]) => any): void {
this._socket.once(eventName, listener);
}
public abstract write(data: string): void;
public abstract resize(cols: number, rows: number): void;
public abstract destroy(): void;
public abstract kill(signal?: string): void;
public abstract get process(): string;
public abstract get master(): Socket;
public abstract get slave(): Socket;
// TODO: Should this be in the API?
public redraw(): void {
let cols = this._cols;
let rows = this._rows;
// We could just send SIGWINCH, but most programs will ignore it if the
// size hasn't actually changed.
this.resize(cols + 1, rows + 1);
setTimeout(() => this.resize(cols, rows), 30);
}
protected _close(): void {
this._socket.writable = false;
this._socket.readable = false;
this.write = () => {};
this.end = () => {};
this._writable = false;
this._readable = false;
}
protected _parseEnv(env: {[key: string]: string}): string[] {
const keys = Object.keys(env || {});
const pairs = [];
for (let i = 0; i < keys.length; i++) {
pairs.push(keys[i] + '=' + env[keys[i]]);
}
return pairs;
}
}