Merge branch 'master' into event_emitter_2

This commit is contained in:
Daniel Imms
2019-04-04 00:12:07 -04:00
27 changed files with 117 additions and 146 deletions
+7 -11
View File
@@ -13,12 +13,11 @@ import * as fit from '../lib/addons/fit/fit';
import * as fullscreen from '../lib/addons/fullscreen/fullscreen';
import * as search from '../lib/addons/search/search';
import * as webLinks from '../lib/addons/webLinks/webLinks';
import * as winptyCompat from '../lib/addons/winptyCompat/winptyCompat';
import { ISearchOptions } from '../lib/addons/search/Interfaces';
// Pulling in the module's types relies on the <reference> above, it's looks a
// little weird here as we're importing "this" module
import { Terminal as TerminalType } from 'xterm';
import { Terminal as TerminalType, ITerminalOptions } from 'xterm';
export interface IWindowWithTerminal extends Window {
term: TerminalType;
@@ -30,10 +29,6 @@ Terminal.applyAddon(fit);
Terminal.applyAddon(fullscreen);
Terminal.applyAddon(search);
Terminal.applyAddon(webLinks);
const isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].indexOf(navigator.platform) >= 0;
if (isWindows) {
Terminal.applyAddon(winptyCompat);
}
let term;
@@ -86,7 +81,10 @@ function createTerminal(): void {
while (terminalContainer.children.length) {
terminalContainer.removeChild(terminalContainer.children[0]);
}
term = new Terminal({});
const isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].indexOf(navigator.platform) >= 0;
term = new Terminal({
windowsMode: isWindows
} as ITerminalOptions);
window.term = term; // Expose `term` to window for debugging purposes
term.on('resize', (size: { cols: number, rows: number }) => {
if (!pid) {
@@ -102,9 +100,7 @@ function createTerminal(): void {
socketURL = protocol + location.hostname + ((location.port) ? (':' + location.port) : '') + '/terminals/';
term.open(terminalContainer);
if (isWindows) {
term.winptyCompatInit();
}
term.webLinksInit();
term.fit();
term.focus();
@@ -176,7 +172,7 @@ function runFakeTerminal(): void {
term.prompt();
} else if (ev.keyCode === 8) {
// Do not delete the prompt
if (term.x > 2) {
if (term._core.buffer.x > 2) {
term.write('\b \b');
}
} else if (printable) {
+1 -1
View File
@@ -5,7 +5,7 @@
import * as Strings from './Strings';
import { ITerminal, IBuffer } from './Types';
import { isMac } from './core/Platform';
import { isMac } from './common/Platform';
import { RenderDebouncer } from './ui/RenderDebouncer';
import { addDisposableDomListener } from './ui/Lifecycle';
import { Disposable } from './common/Lifecycle';
+1 -1
View File
@@ -252,7 +252,7 @@ export class Buffer implements IBuffer {
}
private get _isReflowEnabled(): boolean {
return this._hasScrollback && !(this._terminal as any).isWinptyCompatEnabled;
return this._hasScrollback && !this._terminal.options.windowsMode;
}
private _reflow(newCols: number, newRows: number): void {
+1 -1
View File
@@ -898,7 +898,7 @@ export class InputHandler extends Disposable implements IInputHandler {
while (param--) {
buffer.lines.splice(buffer.ybase + buffer.scrollBottom, 1);
buffer.lines.splice(buffer.ybase + buffer.scrollBottom, 0, buffer.getBlankLine(DEFAULT_ATTR));
buffer.lines.splice(buffer.ybase + buffer.scrollTop, 0, buffer.getBlankLine(DEFAULT_ATTR));
}
// this.maxRange();
this._terminal.updateRange(buffer.scrollTop);
+1 -1
View File
@@ -5,7 +5,7 @@
import { ITerminal, ISelectionManager, IBuffer, IBufferLine } from './Types';
import { MouseHelper } from './ui/MouseHelper';
import * as Browser from './core/Platform';
import * as Browser from './common/Platform';
import { CharMeasure } from './ui/CharMeasure';
import { EventEmitter } from './common/EventEmitter';
import { SelectionModel } from './SelectionModel';
+25 -2
View File
@@ -36,7 +36,7 @@ import { Renderer } from './renderer/Renderer';
import { Linkifier } from './Linkifier';
import { SelectionManager } from './SelectionManager';
import { CharMeasure } from './ui/CharMeasure';
import * as Browser from './core/Platform';
import * as Browser from './common/Platform';
import { addDisposableDomListener } from './ui/Lifecycle';
import * as Strings from './Strings';
import { MouseHelper } from './ui/MouseHelper';
@@ -53,6 +53,7 @@ import { evaluateKeyboardEvent } from './core/input/Keyboard';
import { KeyboardResultType, ICharset } from './core/Types';
import { clone } from './common/Clone';
import { EventEmitter2, IEvent } from './common/EventEmitter2';
import { applyWindowsMode } from './WindowsMode';
// Let it work inside Node.js for automated testing purposes.
const document = (typeof window !== 'undefined') ? window.document : null;
@@ -111,7 +112,8 @@ const DEFAULT_OPTIONS: ITerminalOptions = {
tabStopWidth: 8,
theme: null,
rightClickSelectsWord: Browser.isMac,
rendererType: 'canvas'
rendererType: 'canvas',
windowsMode: false
};
export class Terminal extends EventEmitter implements ITerminal, IDisposable, IInputHandlingTerminal {
@@ -211,6 +213,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
private _accessibilityManager: AccessibilityManager;
private _screenDprMonitor: ScreenDprMonitor;
private _theme: ITheme;
private _windowsMode: IDisposable | undefined;
// bufferline to clone/copy from for new blank lines
private _blankLine: IBufferLine = null;
@@ -270,6 +273,10 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
public dispose(): void {
super.dispose();
if (this._windowsMode) {
this._windowsMode.dispose();
this._windowsMode = undefined;
}
this._customKeyEventHandler = null;
removeTerminalFromCache(this);
this.handler = () => {};
@@ -352,6 +359,10 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
this.selectionManager.clearSelection();
this.selectionManager.initBuffersListeners();
}
if (this.options.windowsMode) {
this._windowsMode = applyWindowsMode(this);
}
}
/**
@@ -532,6 +543,18 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
}
break;
case 'tabStopWidth': this.buffers.setupTabStops(); break;
case 'windowsMode':
if (value) {
if (!this._windowsMode) {
this._windowsMode = applyWindowsMode(this);
}
} else {
if (this._windowsMode) {
this._windowsMode.dispose();
this._windowsMode = undefined;
}
}
break;
}
// Inform renderer of changes
if (this.renderer) {
+30
View File
@@ -0,0 +1,30 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { IDisposable } from 'xterm';
import { ITerminal } from './Types';
import { CHAR_DATA_CODE_INDEX, NULL_CELL_CODE, WHITESPACE_CELL_CODE } from './Buffer';
export function applyWindowsMode(terminal: ITerminal): IDisposable {
// Winpty does not support wraparound mode which means that lines will never
// be marked as wrapped. This causes issues for things like copying a line
// retaining the wrapped new line characters or if consumers are listening
// in on the data stream.
//
// The workaround for this is to listen to every incoming line feed and mark
// the line as wrapped if the last character in the previous line is not a
// space. This is certainly not without its problems, but generally on
// Windows when text reaches the end of the terminal it's likely going to be
// wrapped.
return terminal.addDisposableListener('linefeed', () => {
const line = terminal.buffer.lines.get(terminal.buffer.ybase + terminal.buffer.y - 1);
const lastChar = line.get(terminal.cols - 1);
if (lastChar[CHAR_DATA_CODE_INDEX] !== NULL_CELL_CODE && lastChar[CHAR_DATA_CODE_INDEX] !== WHITESPACE_CELL_CODE) {
const nextLine = terminal.buffer.lines.get(terminal.buffer.ybase + terminal.buffer.y);
nextLine.isWrapped = true;
}
});
}
-14
View File
@@ -1,14 +0,0 @@
/**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { Terminal } from 'xterm';
export interface ITerminalCore {
buffer: any;
}
export interface IWinptyCompatAddonTerminal extends Terminal {
_core: ITerminalCore;
}
-5
View File
@@ -1,5 +0,0 @@
{
"name": "xterm.winptycompat",
"main": "winptyCompat.js",
"private": true
}
-21
View File
@@ -1,21 +0,0 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": [
"es5"
],
"rootDir": ".",
"outDir": "../../../lib/addons/winptyCompat/",
"sourceMap": true,
"removeComments": true,
"declaration": true,
"types": [
"../../node_modules/@types/mocha"
]
},
"include": [
"**/*.ts",
"../../../typings/xterm.d.ts"
]
}
@@ -1,19 +0,0 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { assert } from 'chai';
import * as winptyCompat from './winptyCompat';
class MockTerminal {}
describe('winptyCompat addon', () => {
describe('apply', () => {
it('should do register the `winptyCompatInit` method', () => {
winptyCompat.apply(<any>MockTerminal);
assert.equal(typeof (<any>MockTerminal).prototype.winptyCompatInit, 'function');
});
});
});
-43
View File
@@ -1,43 +0,0 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { Terminal } from 'xterm';
import { IWinptyCompatAddonTerminal } from './Interfaces';
const CHAR_DATA_CODE_INDEX = 3;
const NULL_CELL_CODE = 0;
const WHITESPACE_CELL_CODE = 32;
export function winptyCompatInit(terminal: Terminal): void {
const addonTerminal = <IWinptyCompatAddonTerminal>terminal;
(addonTerminal._core as any).isWinptyCompatEnabled = true;
// Winpty does not support wraparound mode which means that lines will never
// be marked as wrapped. This causes issues for things like copying a line
// retaining the wrapped new line characters or if consumers are listening
// in on the data stream.
//
// The workaround for this is to listen to every incoming line feed and mark
// the line as wrapped if the last character in the previous line is not a
// space. This is certainly not without its problems, but generally on
// Windows when text reaches the end of the terminal it's likely going to be
// wrapped.
addonTerminal.onLineFeed(() => {
const line = addonTerminal._core.buffer.lines.get(addonTerminal._core.buffer.ybase + addonTerminal._core.buffer.y - 1);
const lastChar = line.get(addonTerminal.cols - 1);
if (lastChar[CHAR_DATA_CODE_INDEX] !== NULL_CELL_CODE && lastChar[CHAR_DATA_CODE_INDEX] !== WHITESPACE_CELL_CODE) {
const nextLine = addonTerminal._core.buffer.lines.get(addonTerminal._core.buffer.ybase + addonTerminal._core.buffer.y);
nextLine.isWrapped = true;
}
});
}
export function apply(terminalConstructor: typeof Terminal): void {
(<any>terminalConstructor.prototype).winptyCompatInit = function (): void {
winptyCompatInit(this);
};
}
+1 -2
View File
@@ -3,8 +3,7 @@
* @license MIT
*/
import { XtermListener } from './Types';
import { IEventEmitter, IDisposable } from 'xterm';
import { IDisposable, IEventEmitter, XtermListener } from './Types';
import { Disposable } from './Lifecycle';
export class EventEmitter extends Disposable implements IEventEmitter, IDisposable {
+1 -1
View File
@@ -3,7 +3,7 @@
* @license MIT
*/
import { IDisposable } from 'xterm';
import { IDisposable } from './Types';
type Listener<T> = (e: T) => void;
+1 -1
View File
@@ -3,7 +3,7 @@
* @license MIT
*/
import { IDisposable } from 'xterm';
import { IDisposable } from './Types';
/**
* A base class that can be extended to provide convenience methods for managing the lifecycle of an
@@ -3,6 +3,16 @@
* @license MIT
*/
interface INavigator {
userAgent: string;
language: string;
platform: string;
}
// We're declaring a navigator global here as we expect it in all runtimes (node and browser), but
// we want this module to live in common.
declare const navigator: INavigator;
const isNode = (typeof navigator === 'undefined') ? true : false;
const userAgent = (isNode) ? 'node' : navigator.userAgent;
const platform = (isNode) ? 'node' : navigator.platform;
+11 -1
View File
@@ -3,10 +3,20 @@
* @license MIT
*/
import { IEventEmitter } from 'xterm';
import { IEvent, EventEmitter2 } from './EventEmitter2';
import { IDeleteEvent, IInsertEvent } from './CircularList';
export interface IDisposable {
dispose(): void;
}
export interface IEventEmitter {
on(type: string, listener: (...args: any[]) => void): void;
off(type: string, listener: (...args: any[]) => void): void;
emit(type: string, data?: any): void;
addDisposableListener(type: string, handler: (...args: any[]) => void): IDisposable;
}
export type XtermListener = (...args: any[]) => void;
/**
+5 -4
View File
@@ -1,9 +1,10 @@
{
"extends": "../tsconfig-library-base",
"compilerOptions": {
"outDir": "../../lib"
"outDir": "../../lib",
"types": [
"../../node_modules/@types/mocha"
]
},
"include": [
"./**/*"
]
"include": [ "./**/*" ]
}
+5 -4
View File
@@ -1,11 +1,12 @@
{
"extends": "../tsconfig-library-base",
"compilerOptions": {
"outDir": "../../lib"
"outDir": "../../lib",
"types": [
"../../node_modules/@types/mocha"
]
},
"include": [
"./**/*"
],
"include": [ "./**/*" ],
"references": [
{ "path": "../common" }
]
+1 -1
View File
@@ -4,7 +4,7 @@
*/
import { FontWeight } from 'xterm';
import { isFirefox, isSafari } from '../../core/Platform';
import { isFirefox, isSafari } from '../../common/Platform';
import { IColor } from '../Types';
import { ICharAtlasConfig, CHAR_ATLAS_CELL_SPACING } from './Types';

Some files were not shown because too many files have changed in this diff Show More