mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge branch 'master' into event_emitter_2
This commit is contained in:
+7
-11
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "xterm.winptycompat",
|
||||
"main": "winptyCompat.js",
|
||||
"private": true
|
||||
}
|
||||
@@ -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');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IDisposable } from 'xterm';
|
||||
import { IDisposable } from './Types';
|
||||
|
||||
type Listener<T> = (e: T) => void;
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"extends": "../tsconfig-library-base",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../lib"
|
||||
"outDir": "../../lib",
|
||||
"types": [
|
||||
"../../node_modules/@types/mocha"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"./**/*"
|
||||
]
|
||||
"include": [ "./**/*" ]
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"extends": "../tsconfig-library-base",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../lib"
|
||||
"outDir": "../../lib",
|
||||
"types": [
|
||||
"../../node_modules/@types/mocha"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"./**/*"
|
||||
],
|
||||
"include": [ "./**/*" ],
|
||||
"references": [
|
||||
{ "path": "../common" }
|
||||
]
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user