Skip to content

Commit

Permalink
hooks for custom control sequences
Browse files Browse the repository at this point in the history
This re-implements addCsiHandler/addOscHandler to return an IDisposable.
  • Loading branch information
PerBothner committed Dec 12, 2018
1 parent 53fd04a commit 8ceea11
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 5 deletions.
53 changes: 52 additions & 1 deletion src/EscapeSequenceParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

import { ParserState, ParserAction, IParsingState, IDcsHandler, IEscapeSequenceParser } from './Types';
import { IDisposable } from 'xterm';
import { Disposable } from './common/Lifecycle';

/**
Expand Down Expand Up @@ -41,7 +42,7 @@ export class TransitionTable {
* @param action parser action to be done
* @param next next parser state
*/
add(code: number, state: number, action: number | null, next: number | null): void {
add(code: number, state: number, action: number | null, next: number | null): void {
this.table[state << 8 | code] = ((action | 0) << 4) | ((next === undefined) ? state : next);
}

Expand Down Expand Up @@ -303,6 +304,32 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
this._executeHandlerFb = callback;
}

addCsiHandler(flag: string, callback: (params: number[], collect: string) => boolean): IDisposable {
const index = flag.charCodeAt(0);
const oldHead = this._csiHandlers[index];
const newHead = Object.assign(
(params: number[], collect: string): void => {
if (callback(params, collect)) { }
else if (newHead.nextHandler) { newHead.nextHandler(params, collect); }
else { this._csiHandlerFb(collect, params, index); }
},
{ nextHandler: oldHead,
dispose(): void {
let previous = null; let cur = this._csiHandlers[index];
for (; cur && cur.nextHandler;
previous = cur, cur = cur.nextHandler) {
if (cur === newHead) {
if (previous) { previous.nextHandler = cur.nextHandler; }
else { this._csiHandlers[index] = cur.nextHandler; }
break;
}
}
}
});
this._csiHandlers[index] = newHead;
return newHead;
}

setCsiHandler(flag: string, callback: (params: number[], collect: string) => void): void {
this._csiHandlers[flag.charCodeAt(0)] = callback;
}
Expand All @@ -323,6 +350,30 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
this._escHandlerFb = callback;
}

addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable {
const oldHead = this._oscHandlers[ident];
const newHead = Object.assign(
(data: string): void => {
if (callback(data)) { }
else if (newHead.nextHandler) { newHead.nextHandler(data); }
else { this._oscHandlerFb(ident, data); }
},
{ nextHandler: oldHead,
dispose(): void {
let previous = null; let cur = this._oscHandlers[ident];
for (; cur && cur.nextHandler;
previous = cur, cur = cur.nextHandler) {
if (cur === newHead) {
if (previous) { previous.nextHandler = cur.nextHandler; }
else { this._oscHandlers[ident] = cur.nextHandler; }
break;
}
}
}
});
this._oscHandlers[ident] = newHead;
return newHead;
}
setOscHandler(ident: number, callback: (data: string) => void): void {
this._oscHandlers[ident] = callback;
}
Expand Down
12 changes: 10 additions & 2 deletions src/InputHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
* @license MIT
*/

import { IInputHandler, IDcsHandler, IEscapeSequenceParser, IBuffer, IInputHandlingTerminal } from './Types';
import { IVtInputHandler, IDcsHandler, IEscapeSequenceParser, IBuffer, IInputHandlingTerminal } from './Types';
import { C0, C1 } from './common/data/EscapeSequences';
import { CHARSETS, DEFAULT_CHARSET } from './core/data/Charsets';
import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CODE_INDEX, DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE } from './Buffer';
import { FLAGS } from './renderer/Types';
import { wcwidth } from './CharWidth';
import { EscapeSequenceParser } from './EscapeSequenceParser';
import { ICharset } from './core/Types';
import { IDisposable } from 'xterm';
import { Disposable } from './common/Lifecycle';

/**
Expand Down Expand Up @@ -112,7 +113,7 @@ class DECRQSS implements IDcsHandler {
* Refer to http://invisible-island.net/xterm/ctlseqs/ctlseqs.html to understand
* each function's header comment.
*/
export class InputHandler extends Disposable implements IInputHandler {
export class InputHandler extends Disposable implements IVtInputHandler {
private _surrogateFirst: string;

constructor(
Expand Down Expand Up @@ -465,6 +466,13 @@ export class InputHandler extends Disposable implements IInputHandler {
this._terminal.updateRange(buffer.y);
}

addCsiHandler(flag: string, callback: (params: number[], collect: string) => boolean): IDisposable {
return this._parser.addCsiHandler(flag, callback);
}
addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable {
return this._parser.addOscHandler(ident, callback);
}

/**
* BEL
* Bell (Ctrl-G).
Expand Down
6 changes: 5 additions & 1 deletion src/Terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
* http://linux.die.net/man/7/urxvt
*/

import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminalOptions, ITerminal, IBrowser, ILinkifier, ILinkMatcherOptions, CustomKeyEventHandler, LinkMatcherHandler, CharData, CharacterJoinerHandler, IBufferLine } from './Types';
import { IInputHandlingTerminal, IInputHandler, IViewport, ICompositionHelper, ITerminalOptions, ITerminal, IBrowser, ILinkifier, ILinkMatcherOptions, CustomKeyEventHandler, LinkMatcherHandler, CharData, CharacterJoinerHandler, IBufferLine } from './Types';
import { IMouseZoneManager } from './ui/Types';
import { IRenderer } from './renderer/Types';
import { BufferSet } from './BufferSet';
Expand Down Expand Up @@ -1287,6 +1287,10 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
this.refresh(0, this.rows - 1);
}

public get inputHandler(): IInputHandler {
return this._inputHandler;
}

/**
* Scroll the display of the terminal by a number of pages.
* @param pageCount The number of pages to scroll (negative scrolls up).
Expand Down
10 changes: 10 additions & 0 deletions src/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,14 @@ export interface IInputHandler {
ESC ~ */ setgLevel(level: number): void;
}

/*
* An InputHandler for VT-style terminals
*/
export interface IVtInputHandler extends IInputHandler {
addCsiHandler(flag: string, callback: (params: number[], collect: string) => boolean): IDisposable;
addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable;
}

export interface ILinkMatcher {
id: number;
regex: RegExp;
Expand Down Expand Up @@ -492,6 +500,8 @@ export interface IEscapeSequenceParser extends IDisposable {
setCsiHandler(flag: string, callback: (params: number[], collect: string) => void): void;
clearCsiHandler(flag: string): void;
setCsiHandlerFallback(callback: (collect: string, params: number[], flag: number) => void): void;
addCsiHandler(flag: string, callback: (params: number[], collect: string) => boolean): IDisposable;
addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable;

setEscHandler(collectAndFlag: string, callback: () => void): void;
clearEscHandler(collectAndFlag: string): void;
Expand Down
5 changes: 4 additions & 1 deletion src/public/Terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings } from 'xterm';
import { ITerminal } from '../Types';
import { ITerminal, IInputHandler } from '../Types';
import { Terminal as TerminalCore } from '../Terminal';
import * as Strings from '../Strings';

Expand All @@ -15,6 +15,9 @@ export class Terminal implements ITerminalApi {
this._core = new TerminalCore(options);
}

public get inputHandler(): IInputHandler {
return (this._core as TerminalCore).inputHandler;
}
public get element(): HTMLElement { return this._core.element; }
public get textarea(): HTMLTextAreaElement { return this._core.textarea; }
public get rows(): number { return this._core.rows; }
Expand Down

0 comments on commit 8ceea11

Please sign in to comment.