mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge pull request #2247 from Tyriar/core_service
Move handler into CoreService and adopt
This commit is contained in:
@@ -7,6 +7,7 @@ import { assert } from 'chai';
|
||||
import { CompositionHelper } from './CompositionHelper';
|
||||
import { ITerminal } from './Types';
|
||||
import { MockCharSizeService } from 'browser/TestUtils.test';
|
||||
import { MockCoreService } from '../out/common/TestUtils.test';
|
||||
|
||||
describe('CompositionHelper', () => {
|
||||
let terminal: ITerminal;
|
||||
@@ -54,7 +55,7 @@ describe('CompositionHelper', () => {
|
||||
}
|
||||
} as any;
|
||||
handledText = '';
|
||||
compositionHelper = new CompositionHelper(textarea, compositionView, terminal, new MockCharSizeService(10, 10));
|
||||
compositionHelper = new CompositionHelper(textarea, compositionView, terminal, new MockCharSizeService(10, 10), new MockCoreService());
|
||||
});
|
||||
|
||||
describe('Input', () => {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import { ITerminal } from './Types';
|
||||
import { ICharSizeService } from 'browser/services/Services';
|
||||
import { ICoreService } from 'common/services/Services';
|
||||
|
||||
interface IPosition {
|
||||
start: number;
|
||||
@@ -41,10 +42,11 @@ export class CompositionHelper {
|
||||
* @param _terminal The Terminal to forward the finished composition to.
|
||||
*/
|
||||
constructor(
|
||||
private _textarea: HTMLTextAreaElement,
|
||||
private _compositionView: HTMLElement,
|
||||
private _terminal: ITerminal,
|
||||
private _charSizeService: ICharSizeService
|
||||
private readonly _textarea: HTMLTextAreaElement,
|
||||
private readonly _compositionView: HTMLElement,
|
||||
private readonly _terminal: ITerminal,
|
||||
private readonly _charSizeService: ICharSizeService,
|
||||
private readonly _coreService: ICoreService
|
||||
) {
|
||||
this._isComposing = false;
|
||||
this._isSendingComposition = false;
|
||||
@@ -127,7 +129,7 @@ export class CompositionHelper {
|
||||
// Cancel any delayed composition send requests and send the input immediately.
|
||||
this._isSendingComposition = false;
|
||||
const input = this._textarea.value.substring(this._compositionPosition.start, this._compositionPosition.end);
|
||||
this._terminal.handler(input);
|
||||
this._coreService.triggerDataEvent(input, true);
|
||||
} else {
|
||||
// Make a deep copy of the composition position here as a new compositionstart event may
|
||||
// fire before the setTimeout executes.
|
||||
@@ -159,7 +161,7 @@ export class CompositionHelper {
|
||||
// (eg. 2) after a composition character.
|
||||
input = this._textarea.value.substring(currentCompositionPosition.start);
|
||||
}
|
||||
this._terminal.handler(input);
|
||||
this._coreService.triggerDataEvent(input, true);
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
@@ -179,7 +181,7 @@ export class CompositionHelper {
|
||||
const newValue = this._textarea.value;
|
||||
const diff = newValue.replace(oldValue, '');
|
||||
if (diff.length > 0) {
|
||||
this._terminal.handler(diff);
|
||||
this._coreService.triggerDataEvent(diff, true);
|
||||
}
|
||||
}
|
||||
}, 0);
|
||||
|
||||
@@ -12,6 +12,7 @@ import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
|
||||
import { CellData } from 'common/buffer/CellData';
|
||||
import { Attributes } from 'common/buffer/Constants';
|
||||
import { AttributeData } from 'common/buffer/AttributeData';
|
||||
import { MockCoreService } from 'common/TestUtils.test';
|
||||
|
||||
describe('InputHandler', () => {
|
||||
describe('save and restore cursor', () => {
|
||||
@@ -20,7 +21,7 @@ describe('InputHandler', () => {
|
||||
terminal.buffer.y = 2;
|
||||
terminal.buffer.ybase = 0;
|
||||
terminal.curAttrData.fg = 3;
|
||||
const inputHandler = new InputHandler(terminal);
|
||||
const inputHandler = new InputHandler(terminal, new MockCoreService());
|
||||
// Save cursor position
|
||||
inputHandler.saveCursor([]);
|
||||
assert.equal(terminal.buffer.x, 1);
|
||||
@@ -39,7 +40,7 @@ describe('InputHandler', () => {
|
||||
describe('setCursorStyle', () => {
|
||||
it('should call Terminal.setOption with correct params', () => {
|
||||
const terminal = new MockInputHandlingTerminal();
|
||||
const inputHandler = new InputHandler(terminal);
|
||||
const inputHandler = new InputHandler(terminal, new MockCoreService());
|
||||
const collect = ' ';
|
||||
|
||||
inputHandler.setCursorStyle([0], collect);
|
||||
@@ -82,7 +83,7 @@ describe('InputHandler', () => {
|
||||
const terminal = new MockInputHandlingTerminal();
|
||||
const collect = '?';
|
||||
terminal.bracketedPasteMode = false;
|
||||
const inputHandler = new InputHandler(terminal);
|
||||
const inputHandler = new InputHandler(terminal, new MockCoreService());
|
||||
// Set bracketed paste mode
|
||||
inputHandler.setMode([2004], collect);
|
||||
assert.equal(terminal.bracketedPasteMode, true);
|
||||
@@ -100,7 +101,7 @@ describe('InputHandler', () => {
|
||||
|
||||
it('insertChars', function(): void {
|
||||
const term = new Terminal();
|
||||
const inputHandler = new InputHandler(term);
|
||||
const inputHandler = new InputHandler(term, new MockCoreService());
|
||||
|
||||
// insert some data in first and second line
|
||||
inputHandler.parse(Array(term.cols - 9).join('a'));
|
||||
@@ -137,7 +138,7 @@ describe('InputHandler', () => {
|
||||
});
|
||||
it('deleteChars', function(): void {
|
||||
const term = new Terminal();
|
||||
const inputHandler = new InputHandler(term);
|
||||
const inputHandler = new InputHandler(term, new MockCoreService());
|
||||
|
||||
// insert some data in first and second line
|
||||
inputHandler.parse(Array(term.cols - 9).join('a'));
|
||||
@@ -177,7 +178,7 @@ describe('InputHandler', () => {
|
||||
});
|
||||
it('eraseInLine', function(): void {
|
||||
const term = new Terminal();
|
||||
const inputHandler = new InputHandler(term);
|
||||
const inputHandler = new InputHandler(term, new MockCoreService());
|
||||
|
||||
// fill 6 lines to test 3 different states
|
||||
inputHandler.parse(Array(term.cols + 1).join('a'));
|
||||
@@ -205,7 +206,7 @@ describe('InputHandler', () => {
|
||||
});
|
||||
it('eraseInDisplay', function(): void {
|
||||
const term = new Terminal({cols: 80, rows: 7});
|
||||
const inputHandler = new InputHandler(term);
|
||||
const inputHandler = new InputHandler(term, new MockCoreService());
|
||||
|
||||
// fill display with a's
|
||||
for (let i = 0; i < term.rows; ++i) inputHandler.parse(Array(term.cols + 1).join('a'));
|
||||
@@ -340,7 +341,7 @@ describe('InputHandler', () => {
|
||||
describe('print', () => {
|
||||
it('should not cause an infinite loop (regression test)', () => {
|
||||
const term = new Terminal();
|
||||
const inputHandler = new InputHandler(term);
|
||||
const inputHandler = new InputHandler(term, new MockCoreService());
|
||||
const container = new Uint32Array(10);
|
||||
container[0] = 0x200B;
|
||||
inputHandler.print(container, 0, 1);
|
||||
@@ -353,7 +354,7 @@ describe('InputHandler', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
term = new Terminal();
|
||||
handler = new InputHandler(term);
|
||||
handler = new InputHandler(term, new MockCoreService());
|
||||
});
|
||||
it('should handle DECSET/DECRST 47 (alt screen buffer)', () => {
|
||||
handler.parse('\x1b[?47h\r\n\x1b[31mJUNK\x1b[?47lTEST');
|
||||
|
||||
+11
-11
@@ -19,6 +19,7 @@ import { IParsingState, IDcsHandler, IEscapeSequenceParser } from 'common/parser
|
||||
import { NULL_CELL_CODE, NULL_CELL_WIDTH, Attributes, FgFlags, BgFlags } from 'common/buffer/Constants';
|
||||
import { CellData } from 'common/buffer/CellData';
|
||||
import { AttributeData } from 'common/buffer/AttributeData';
|
||||
import { ICoreService } from 'common/services/Services';
|
||||
|
||||
/**
|
||||
* Map collect to glevel. Used in `selectCharset`.
|
||||
@@ -113,8 +114,6 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
|
||||
private _onCursorMove = new EventEmitter<void>();
|
||||
public get onCursorMove(): IEvent<void> { return this._onCursorMove.event; }
|
||||
private _onData = new EventEmitter<string>();
|
||||
public get onData(): IEvent<string> { return this._onData.event; }
|
||||
private _onLineFeed = new EventEmitter<void>();
|
||||
public get onLineFeed(): IEvent<void> { return this._onLineFeed.event; }
|
||||
private _onScroll = new EventEmitter<number>();
|
||||
@@ -122,6 +121,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
|
||||
constructor(
|
||||
protected _terminal: IInputHandlingTerminal,
|
||||
private _coreService: ICoreService,
|
||||
private _parser: IEscapeSequenceParser = new EscapeSequenceParser())
|
||||
{
|
||||
super();
|
||||
@@ -1098,24 +1098,24 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
|
||||
if (!collect) {
|
||||
if (this._terminal.is('xterm') || this._terminal.is('rxvt-unicode') || this._terminal.is('screen')) {
|
||||
this._terminal.handler(C0.ESC + '[?1;2c');
|
||||
this._coreService.triggerDataEvent(C0.ESC + '[?1;2c');
|
||||
} else if (this._terminal.is('linux')) {
|
||||
this._terminal.handler(C0.ESC + '[?6c');
|
||||
this._coreService.triggerDataEvent(C0.ESC + '[?6c');
|
||||
}
|
||||
} else if (collect === '>') {
|
||||
// xterm and urxvt
|
||||
// seem to spit this
|
||||
// out around ~370 times (?).
|
||||
if (this._terminal.is('xterm')) {
|
||||
this._terminal.handler(C0.ESC + '[>0;276;0c');
|
||||
this._coreService.triggerDataEvent(C0.ESC + '[>0;276;0c');
|
||||
} else if (this._terminal.is('rxvt-unicode')) {
|
||||
this._terminal.handler(C0.ESC + '[>85;95;0c');
|
||||
this._coreService.triggerDataEvent(C0.ESC + '[>85;95;0c');
|
||||
} else if (this._terminal.is('linux')) {
|
||||
// not supported by linux console.
|
||||
// linux console echoes parameters.
|
||||
this._terminal.handler(params[0] + 'c');
|
||||
this._coreService.triggerDataEvent(params[0] + 'c');
|
||||
} else if (this._terminal.is('screen')) {
|
||||
this._terminal.handler(C0.ESC + '[>83;40003;0c');
|
||||
this._coreService.triggerDataEvent(C0.ESC + '[>83;40003;0c');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1799,13 +1799,13 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
switch (params[0]) {
|
||||
case 5:
|
||||
// status report
|
||||
this._onData.fire(`${C0.ESC}[0n`);
|
||||
this._coreService.triggerDataEvent(`${C0.ESC}[0n`);
|
||||
break;
|
||||
case 6:
|
||||
// cursor position
|
||||
const y = this._terminal.buffer.y + 1;
|
||||
const x = this._terminal.buffer.x + 1;
|
||||
this._onData.fire(`${C0.ESC}[${y};${x}R`);
|
||||
this._coreService.triggerDataEvent(`${C0.ESC}[${y};${x}R`);
|
||||
break;
|
||||
}
|
||||
} else if (collect === '?') {
|
||||
@@ -1816,7 +1816,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
// cursor position
|
||||
const y = this._terminal.buffer.y + 1;
|
||||
const x = this._terminal.buffer.x + 1;
|
||||
this._onData.fire(`${C0.ESC}[?${y};${x}R`);
|
||||
this._coreService.triggerDataEvent(`${C0.ESC}[?${y};${x}R`);
|
||||
break;
|
||||
case 15:
|
||||
// no printer
|
||||
|
||||
@@ -10,7 +10,7 @@ import { ITerminal } from './Types';
|
||||
import { IBuffer } from 'common/buffer/Types';
|
||||
import { IBufferLine } from 'common/Types';
|
||||
import { MockTerminal } from './TestUtils.test';
|
||||
import { MockBufferService, MockOptionsService } from 'common/TestUtils.test';
|
||||
import { MockBufferService, MockOptionsService, MockCoreService } from 'common/TestUtils.test';
|
||||
import { BufferLine } from 'common/buffer/BufferLine';
|
||||
import { IBufferService, IOptionsService } from 'common/services/Services';
|
||||
import { MockCharSizeService, MockMouseService } from 'browser/TestUtils.test';
|
||||
@@ -26,7 +26,7 @@ class TestSelectionManager extends SelectionManager {
|
||||
bufferService: IBufferService,
|
||||
optionsService: IOptionsService
|
||||
) {
|
||||
super(terminal, null, new MockCharSizeService(10, 10), bufferService, new MockMouseService(), optionsService);
|
||||
super(terminal, null, new MockCharSizeService(10, 10), bufferService, new MockCoreService(), new MockMouseService(), optionsService);
|
||||
}
|
||||
|
||||
public get model(): SelectionModel { return this._model; }
|
||||
|
||||
@@ -13,7 +13,7 @@ import { CellData } from 'common/buffer/CellData';
|
||||
import { IDisposable } from 'xterm';
|
||||
import { EventEmitter, IEvent } from 'common/EventEmitter';
|
||||
import { ICharSizeService, IMouseService } from 'browser/services/Services';
|
||||
import { IBufferService, IOptionsService } from 'common/services/Services';
|
||||
import { IBufferService, IOptionsService, ICoreService } from 'common/services/Services';
|
||||
import { getCoordsRelativeToElement } from 'browser/input/Mouse';
|
||||
import { moveToCellSequence } from 'browser/input/MoveToCell';
|
||||
|
||||
@@ -117,6 +117,7 @@ export class SelectionManager implements ISelectionManager {
|
||||
private readonly _screenElement: HTMLElement,
|
||||
private readonly _charSizeService: ICharSizeService,
|
||||
private readonly _bufferService: IBufferService,
|
||||
private readonly _coreService: ICoreService,
|
||||
private readonly _mouseService: IMouseService,
|
||||
private readonly _optionsService: IOptionsService
|
||||
) {
|
||||
@@ -137,7 +138,11 @@ export class SelectionManager implements ISelectionManager {
|
||||
private _initListeners(): void {
|
||||
this._mouseMoveListener = event => this._onMouseMove(<MouseEvent>event);
|
||||
this._mouseUpListener = event => this._onMouseUp(<MouseEvent>event);
|
||||
|
||||
this._coreService.onUserInput(() => {
|
||||
if (this.hasSelection) {
|
||||
this.clearSelection();
|
||||
}
|
||||
});
|
||||
this.initBuffersListeners();
|
||||
}
|
||||
|
||||
@@ -661,7 +666,7 @@ export class SelectionManager implements ISelectionManager {
|
||||
);
|
||||
if (coordinates && coordinates[0] !== undefined && coordinates[1] !== undefined) {
|
||||
const sequence = moveToCellSequence(coordinates[0] - 1, coordinates[1] - 1, this._bufferService, this._terminal.applicationCursor);
|
||||
this._terminal.handler(sequence);
|
||||
this._coreService.triggerDataEvent(sequence, true);
|
||||
}
|
||||
}
|
||||
} else if (this.hasSelection) {
|
||||
|
||||
@@ -53,10 +53,11 @@ describe('Terminal', () => {
|
||||
});
|
||||
|
||||
describe('events', () => {
|
||||
it('should fire the onData evnet', (done) => {
|
||||
term.onData(() => done());
|
||||
term.handler('fake');
|
||||
});
|
||||
// TODO: Add an onData test back
|
||||
// it('should fire the onData evnet', (done) => {
|
||||
// term.onData(() => done());
|
||||
// term.handler('fake');
|
||||
// });
|
||||
it('should fire the onCursorMove event', (done) => {
|
||||
term.onCursorMove(() => done());
|
||||
term.write('foo');
|
||||
@@ -142,7 +143,6 @@ describe('Terminal', () => {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
term.handler = () => { };
|
||||
term.showCursor = () => { };
|
||||
term.clearSelection = () => { };
|
||||
});
|
||||
@@ -520,7 +520,6 @@ describe('Terminal', () => {
|
||||
let evKeyPress: any;
|
||||
|
||||
beforeEach(() => {
|
||||
term.handler = () => { };
|
||||
term.showCursor = () => { };
|
||||
term.clearSelection = () => { };
|
||||
// term.compositionHelper = {
|
||||
|
||||
+41
-38
@@ -47,7 +47,7 @@ import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
|
||||
import { applyWindowsMode } from './WindowsMode';
|
||||
import { ColorManager } from 'browser/ColorManager';
|
||||
import { RenderService } from 'browser/services/RenderService';
|
||||
import { IOptionsService, IBufferService } from 'common/services/Services';
|
||||
import { IOptionsService, IBufferService, ICoreService } from 'common/services/Services';
|
||||
import { OptionsService } from 'common/services/OptionsService';
|
||||
import { ICharSizeService, IRenderService, IMouseService } from 'browser/services/Services';
|
||||
import { CharSizeService } from 'browser/services/CharSizeService';
|
||||
@@ -56,6 +56,7 @@ import { Disposable } from 'common/Lifecycle';
|
||||
import { IBufferSet, IBuffer } from 'common/buffer/Types';
|
||||
import { Attributes } from 'common/buffer/Constants';
|
||||
import { MouseService } from 'browser/services/MouseService';
|
||||
import { CoreService } from 'common/services/CoreService';
|
||||
|
||||
// Let it work inside Node.js for automated testing purposes.
|
||||
const document = (typeof window !== 'undefined') ? window.document : null;
|
||||
@@ -107,6 +108,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
|
||||
// common services
|
||||
private _bufferService: IBufferService;
|
||||
private _coreService: ICoreService;
|
||||
public optionsService: IOptionsService;
|
||||
|
||||
// browser services
|
||||
@@ -237,6 +239,9 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
// Setup and initialize common services
|
||||
this.optionsService = new OptionsService(options);
|
||||
this._bufferService = new BufferService(this.optionsService);
|
||||
this._coreService = new CoreService(() => this.scrollToBottom(), this._bufferService, this.optionsService);
|
||||
this._coreService.onData(e => this._onData.fire(e));
|
||||
|
||||
this._setupOptionsListeners();
|
||||
this._setup();
|
||||
}
|
||||
@@ -249,7 +254,6 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
}
|
||||
this._customKeyEventHandler = null;
|
||||
removeTerminalFromCache(this);
|
||||
this.handler = () => {};
|
||||
this.write = () => {};
|
||||
if (this.element && this.element.parentNode) {
|
||||
this.element.parentNode.removeChild(this.element);
|
||||
@@ -294,10 +298,9 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
this._userScrolling = false;
|
||||
|
||||
// Register input handler and refire/handle events
|
||||
this._inputHandler = new InputHandler(this);
|
||||
this._inputHandler = new InputHandler(this, this._coreService);
|
||||
this._inputHandler.onCursorMove(() => this._onCursorMove.fire());
|
||||
this._inputHandler.onLineFeed(() => this._onLineFeed.fire());
|
||||
this._inputHandler.onData(e => this._onData.fire(e));
|
||||
this.register(this._inputHandler);
|
||||
|
||||
this.selectionManager = this.selectionManager || null;
|
||||
@@ -434,7 +437,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
*/
|
||||
private _onTextAreaFocus(ev: KeyboardEvent): void {
|
||||
if (this.sendFocus) {
|
||||
this.handler(C0.ESC + '[I');
|
||||
this._coreService.triggerDataEvent(C0.ESC + '[I');
|
||||
}
|
||||
this.updateCursorStyle(ev);
|
||||
this.element.classList.add('focus');
|
||||
@@ -459,7 +462,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
this.textarea.value = '';
|
||||
this.refresh(this.buffer.y, this.buffer.y);
|
||||
if (this.sendFocus) {
|
||||
this.handler(C0.ESC + '[O');
|
||||
this._coreService.triggerDataEvent(C0.ESC + '[O');
|
||||
}
|
||||
this.element.classList.remove('focus');
|
||||
this._onBlur.fire();
|
||||
@@ -480,7 +483,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
}
|
||||
copyHandler(event, this.selectionManager);
|
||||
}));
|
||||
const pasteHandlerWrapper = (event: ClipboardEvent) => pasteHandler(event, this.textarea, this.bracketedPasteMode, e => this.handler(e));
|
||||
const pasteHandlerWrapper = (event: ClipboardEvent) => pasteHandler(event, this.textarea, this.bracketedPasteMode, e => this._coreService.triggerDataEvent(e, true));
|
||||
this.register(addDisposableDomListener(this.textarea, 'paste', pasteHandlerWrapper));
|
||||
this.register(addDisposableDomListener(this.element, 'paste', pasteHandlerWrapper));
|
||||
|
||||
@@ -607,7 +610,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
|
||||
this._compositionView = document.createElement('div');
|
||||
this._compositionView.classList.add('composition-view');
|
||||
this._compositionHelper = new CompositionHelper(this.textarea, this._compositionView, this, this._charSizeService);
|
||||
this._compositionHelper = new CompositionHelper(this.textarea, this._compositionView, this, this._charSizeService, this._coreService);
|
||||
this._helperContainer.appendChild(this._compositionView);
|
||||
|
||||
// Performance: Add viewport and helper elements from the fragment
|
||||
@@ -640,7 +643,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
this.register(this.onFocus(() => this._renderService.onFocus()));
|
||||
this.register(this._renderService.onDimensionsChange(() => this.viewport.syncScrollArea()));
|
||||
|
||||
this.selectionManager = new SelectionManager(this, this.screenElement, this._charSizeService, this._bufferService, this._mouseService, this.optionsService);
|
||||
this.selectionManager = new SelectionManager(this, this.screenElement, this._charSizeService, this._bufferService, this._coreService, this._mouseService, this.optionsService);
|
||||
this.register(this.selectionManager.onSelectionChange(() => this._onSelectionChange.fire()));
|
||||
this.register(addDisposableDomListener(this.element, 'mousedown', (e: MouseEvent) => this.selectionManager.onMouseDown(e)));
|
||||
this.register(this.selectionManager.onRedrawRequest(e => this._renderService.onSelectionChanged(e.start, e.end, e.columnSelectMode)));
|
||||
@@ -814,7 +817,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
else if (button === 3) return;
|
||||
else data += '0';
|
||||
data += '~[' + pos.x + ',' + pos.y + ']\r';
|
||||
self.handler(data);
|
||||
self._coreService.triggerDataEvent(data, true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -827,7 +830,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
else if (button === 1) button = 4;
|
||||
else if (button === 2) button = 6;
|
||||
else if (button === 3) button = 3;
|
||||
self.handler(C0.ESC + '['
|
||||
self._coreService.triggerDataEvent(C0.ESC + '['
|
||||
+ button
|
||||
+ ';'
|
||||
+ (button === 3 ? 4 : 0)
|
||||
@@ -838,7 +841,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
+ ';'
|
||||
// Not sure what page is meant to be
|
||||
+ (<any>pos).page || 0
|
||||
+ '&w');
|
||||
+ '&w', true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -847,20 +850,20 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
pos.y -= 32;
|
||||
pos.x++;
|
||||
pos.y++;
|
||||
self.handler(C0.ESC + '[' + button + ';' + pos.x + ';' + pos.y + 'M');
|
||||
self._coreService.triggerDataEvent(C0.ESC + '[' + button + ';' + pos.x + ';' + pos.y + 'M', true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.sgrMouse) {
|
||||
pos.x -= 32;
|
||||
pos.y -= 32;
|
||||
self.handler(C0.ESC + '[<'
|
||||
self._coreService.triggerDataEvent(C0.ESC + '[<'
|
||||
+ (((button & 3) === 3 ? button & ~3 : button) - 32)
|
||||
+ ';'
|
||||
+ pos.x
|
||||
+ ';'
|
||||
+ pos.y
|
||||
+ ((button & 3) === 3 ? 'm' : 'M'));
|
||||
+ ((button & 3) === 3 ? 'm' : 'M'), true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -870,7 +873,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
encode(data, pos.x);
|
||||
encode(data, pos.y);
|
||||
|
||||
self.handler(C0.ESC + '[M' + String.fromCharCode.apply(String, data));
|
||||
self._coreService.triggerDataEvent(C0.ESC + '[M' + String.fromCharCode.apply(String, data), true);
|
||||
}
|
||||
|
||||
function getButton(ev: MouseEvent): number {
|
||||
@@ -1015,7 +1018,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
for (let i = 0; i < Math.abs(amount); i++) {
|
||||
data += sequence;
|
||||
}
|
||||
this.handler(data);
|
||||
this._coreService.triggerDataEvent(data, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1240,7 +1243,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
if (this.options.useFlowControl && !this._xoffSentToCatchUp && this.writeBufferUtf8.length >= WRITE_BUFFER_PAUSE_THRESHOLD) {
|
||||
// XOFF - stop pty pipe
|
||||
// XON will be triggered by emulator before processing data chunk
|
||||
this.handler(C0.DC3);
|
||||
this._coreService.triggerDataEvent(C0.DC3);
|
||||
this._xoffSentToCatchUp = true;
|
||||
}
|
||||
|
||||
@@ -1268,7 +1271,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
// If XOFF was sent in order to catch up with the pty process, resume it if
|
||||
// we reached the end of the writeBuffer to allow more data to come in.
|
||||
if (this._xoffSentToCatchUp && this.writeBufferUtf8.length === bufferOffset) {
|
||||
this.handler(C0.DC1);
|
||||
this._coreService.triggerDataEvent(C0.DC1);
|
||||
this._xoffSentToCatchUp = false;
|
||||
}
|
||||
|
||||
@@ -1327,7 +1330,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
if (this.options.useFlowControl && !this._xoffSentToCatchUp && this.writeBuffer.length >= WRITE_BUFFER_PAUSE_THRESHOLD) {
|
||||
// XOFF - stop pty pipe
|
||||
// XON will be triggered by emulator before processing data chunk
|
||||
this.handler(C0.DC3);
|
||||
this._coreService.triggerDataEvent(C0.DC3);
|
||||
this._xoffSentToCatchUp = true;
|
||||
}
|
||||
|
||||
@@ -1355,7 +1358,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
// If XOFF was sent in order to catch up with the pty process, resume it if
|
||||
// we reached the end of the writeBuffer to allow more data to come in.
|
||||
if (this._xoffSentToCatchUp && this.writeBuffer.length === bufferOffset) {
|
||||
this.handler(C0.DC1);
|
||||
this._coreService.triggerDataEvent(C0.DC1);
|
||||
this._xoffSentToCatchUp = false;
|
||||
}
|
||||
|
||||
@@ -1587,7 +1590,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
|
||||
this._onKey.fire({ key: result.key, domEvent: event });
|
||||
this.showCursor();
|
||||
this.handler(result.key);
|
||||
this._coreService.triggerDataEvent(result.key, true);
|
||||
|
||||
return this.cancel(event, true);
|
||||
}
|
||||
@@ -1665,7 +1668,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
|
||||
this._onKey.fire({ key, domEvent: ev });
|
||||
this.showCursor();
|
||||
this.handler(key);
|
||||
this._coreService.triggerDataEvent(key, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1796,23 +1799,23 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
||||
* Emit the data event and populate the given data.
|
||||
* @param data The data to populate in the event.
|
||||
*/
|
||||
public handler(data: string): void {
|
||||
// Prevents all events to pty process if stdin is disabled
|
||||
if (this.options.disableStdin) {
|
||||
return;
|
||||
}
|
||||
// public handler(data: string): void {
|
||||
// // Prevents all events to pty process if stdin is disabled
|
||||
// if (this.options.disableStdin) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Clear the selection if the selection manager is available and has an active selection
|
||||
if (this.selectionManager && this.selectionManager.hasSelection) {
|
||||
this.selectionManager.clearSelection();
|
||||
}
|
||||
// // Clear the selection if the selection manager is available and has an active selection
|
||||
// if (this.selectionManager && this.selectionManager.hasSelection) {
|
||||
// this.selectionManager.clearSelection();
|
||||
// }
|
||||
|
||||
// Input is being sent to the terminal, the terminal should focus the prompt.
|
||||
if (this.buffer.ybase !== this.buffer.ydisp) {
|
||||
this.scrollToBottom();
|
||||
}
|
||||
this._onData.fire(data);
|
||||
}
|
||||
// // Input is being sent to the terminal, the terminal should focus the prompt.
|
||||
// if (this.buffer.ybase !== this.buffer.ydisp) {
|
||||
// this.scrollToBottom();
|
||||
// }
|
||||
// this._onData.fire(data);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Emit the 'title' event and populate the given title.
|
||||
|
||||
Vendored
-2
@@ -73,7 +73,6 @@ export interface IInputHandlingTerminal {
|
||||
refresh(start: number, end: number): void;
|
||||
error(text: string, data?: any): void;
|
||||
tabSet(): void;
|
||||
handler(data: string): void;
|
||||
handleTitle(title: string): void;
|
||||
index(): void;
|
||||
reverseIndex(): void;
|
||||
@@ -217,7 +216,6 @@ export interface ITerminal extends IPublicTerminal, IElementAccessor, IBufferAcc
|
||||
onA11yChar: IEvent<string>;
|
||||
onA11yTab: IEvent<number>;
|
||||
|
||||
handler(data: string): void;
|
||||
scrollLines(disp: number, suppressScrollEvent?: boolean): void;
|
||||
cancel(ev: Event, force?: boolean): boolean | void;
|
||||
log(text: string): void;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { IBufferService, IOptionsService, ITerminalOptions, IPartialTerminalOptions } from 'common/services/Services';
|
||||
import { IBufferService, ICoreService, IOptionsService, ITerminalOptions, IPartialTerminalOptions } from 'common/services/Services';
|
||||
import { IEvent, EventEmitter } from 'common/EventEmitter';
|
||||
import { clone } from 'common/Clone';
|
||||
import { DEFAULT_OPTIONS } from 'common/services/OptionsService';
|
||||
@@ -27,6 +27,12 @@ export class MockBufferService implements IBufferService {
|
||||
reset(): void {}
|
||||
}
|
||||
|
||||
export class MockCoreService implements ICoreService {
|
||||
onData: IEvent<string> = new EventEmitter<string>().event;
|
||||
onUserInput: IEvent<void> = new EventEmitter<void>().event;
|
||||
triggerDataEvent(data: string, wasUserInput?: boolean): void {}
|
||||
}
|
||||
|
||||
export class MockOptionsService implements IOptionsService {
|
||||
options: ITerminalOptions = clone(DEFAULT_OPTIONS);
|
||||
onOptionChange: IEvent<string> = new EventEmitter<string>().event;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { ICoreService, IOptionsService, IBufferService } from 'common/services/Services';
|
||||
import { EventEmitter, IEvent } from 'common/EventEmitter';
|
||||
|
||||
export class CoreService implements ICoreService {
|
||||
private _onData = new EventEmitter<string>();
|
||||
public get onData(): IEvent<string> { return this._onData.event; }
|
||||
private _onUserInput = new EventEmitter<void>();
|
||||
public get onUserInput(): IEvent<void> { return this._onUserInput.event; }
|
||||
|
||||
constructor(
|
||||
// TODO: Move this into a service
|
||||
private readonly _scrollToBottom: () => void,
|
||||
private readonly _bufferService: IBufferService,
|
||||
private readonly _optionsService: IOptionsService
|
||||
) {
|
||||
}
|
||||
|
||||
public triggerDataEvent(data: string, wasUserInput: boolean = false): void {
|
||||
// Prevents all events to pty process if stdin is disabled
|
||||
if (this._optionsService.options.disableStdin) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Input is being sent to the terminal, the terminal should focus the prompt.
|
||||
const buffer = this._bufferService.buffer;
|
||||
if (buffer.ybase !== buffer.ydisp) {
|
||||
this._scrollToBottom();
|
||||
}
|
||||
|
||||
// Fire onUserInput so listeners can react as well (eg. clear selection)
|
||||
if (wasUserInput) {
|
||||
this._onUserInput.fire();
|
||||
}
|
||||
|
||||
// Fire onData API
|
||||
this._onData.fire(data);
|
||||
}
|
||||
}
|
||||
Vendored
+15
@@ -18,6 +18,21 @@ export interface IBufferService {
|
||||
reset(): void;
|
||||
}
|
||||
|
||||
export interface ICoreService {
|
||||
readonly onData: IEvent<string>;
|
||||
readonly onUserInput: IEvent<void>;
|
||||
|
||||
/**
|
||||
* Triggers the onData event in the public API.
|
||||
* @param data The data that is being emitted.
|
||||
* @param wasFromUser Whether the data originated from the user (as opposed to
|
||||
* resulting from parsing incoming data). When true this will also:
|
||||
* - Scroll to the bottom of the buffer.s
|
||||
* - Fire the `onUserInput` event (so selection can be cleared).
|
||||
*/
|
||||
triggerDataEvent(data: string, wasUserInput?: boolean): void;
|
||||
}
|
||||
|
||||
export interface IOptionsService {
|
||||
readonly options: ITerminalOptions;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user