hooks for custom control sequences
This fixes (at least partially) issue #1176 "Add a way to plugin a custom control sequence handler".
This commit is contained in:
+68
-10
@@ -301,9 +301,39 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
|||||||
this._executeHandlerFb = callback;
|
this._executeHandlerFb = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
setCsiHandler(flag: string, callback: (params: number[], collect: string) => void): void {
|
private _removeHandler(array: any[], callback: any): void {
|
||||||
this._csiHandlers[flag.charCodeAt(0)] = callback;
|
if (array) {
|
||||||
|
for (let i = array.length; --i >= 0; ) {
|
||||||
|
if (array[i] == callback) {
|
||||||
|
array.splice(i, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addCsiHandler(flag: string, callback: (params: number[], collect: string) => boolean): void {
|
||||||
|
let index = flag.charCodeAt(0);
|
||||||
|
let array = this._csiHandlers[index];
|
||||||
|
if (! array) { this._csiHandlers[index] = array = new Array(); }
|
||||||
|
array.push(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeCsiHandler(flag: string, callback: (params: number[], collect: string) => boolean): void {
|
||||||
|
let index = flag.charCodeAt(0);
|
||||||
|
let array = this._csiHandlers[index];
|
||||||
|
this._removeHandler(array, callback);
|
||||||
|
if (array && array.length == 0)
|
||||||
|
delete this._csiHandlers[index];
|
||||||
|
}
|
||||||
|
/* deprecated */
|
||||||
|
setCsiHandler(flag: string, callback: (params: number[], collect: string) => void): void {
|
||||||
|
this.clearCsiHandler(flag);
|
||||||
|
this.addCsiHandler(flag, (params: number[], collect: string): boolean => {
|
||||||
|
callback(params, collect); return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/* deprecated */
|
||||||
clearCsiHandler(flag: string): void {
|
clearCsiHandler(flag: string): void {
|
||||||
if (this._csiHandlers[flag.charCodeAt(0)]) delete this._csiHandlers[flag.charCodeAt(0)];
|
if (this._csiHandlers[flag.charCodeAt(0)]) delete this._csiHandlers[flag.charCodeAt(0)];
|
||||||
}
|
}
|
||||||
@@ -321,9 +351,25 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
|||||||
this._escHandlerFb = callback;
|
this._escHandlerFb = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
setOscHandler(ident: number, callback: (data: string) => void): void {
|
addOscHandler(ident: number, callback: (data: string) => boolean): void {
|
||||||
this._oscHandlers[ident] = callback;
|
let array = this._oscHandlers[ident];
|
||||||
|
if (! array) { this._oscHandlers[ident] = array = new Array(); }
|
||||||
|
array.push(callback);
|
||||||
}
|
}
|
||||||
|
removeOscHandler(ident: number, callback: (data: string) => boolean): void {
|
||||||
|
let array = this._oscHandlers[ident];
|
||||||
|
this._removeHandler(array, callback);
|
||||||
|
if (array && array.length == 0)
|
||||||
|
delete this._oscHandlers[ident];
|
||||||
|
}
|
||||||
|
/* deprecated */
|
||||||
|
setOscHandler(ident: number, callback: (data: string) => void): void {
|
||||||
|
this.clearOscHandler(ident);
|
||||||
|
this.addOscHandler(ident, (data: string): boolean => {
|
||||||
|
callback(data); return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/* deprecated */
|
||||||
clearOscHandler(ident: number): void {
|
clearOscHandler(ident: number): void {
|
||||||
if (this._oscHandlers[ident]) delete this._oscHandlers[ident];
|
if (this._oscHandlers[ident]) delete this._oscHandlers[ident];
|
||||||
}
|
}
|
||||||
@@ -463,9 +509,15 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ParserAction.CSI_DISPATCH:
|
case ParserAction.CSI_DISPATCH:
|
||||||
callback = this._csiHandlers[code];
|
let cHandler = this._csiHandlers[code];
|
||||||
if (callback) callback(params, collect);
|
if (cHandler) {
|
||||||
else this._csiHandlerFb(collect, params, code);
|
for (let i = cHandler.length; ;) {
|
||||||
|
if (--i < 0) { cHandler = null; break; }
|
||||||
|
if ((cHandler[i])(params, collect))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (! cHandler) this._csiHandlerFb(collect, params, code);
|
||||||
break;
|
break;
|
||||||
case ParserAction.PARAM:
|
case ParserAction.PARAM:
|
||||||
if (code === 0x3b) params.push(0);
|
if (code === 0x3b) params.push(0);
|
||||||
@@ -532,9 +584,15 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
|
|||||||
// or with an explicit NaN OSC handler
|
// or with an explicit NaN OSC handler
|
||||||
const identifier = parseInt(osc.substring(0, idx));
|
const identifier = parseInt(osc.substring(0, idx));
|
||||||
const content = osc.substring(idx + 1);
|
const content = osc.substring(idx + 1);
|
||||||
callback = this._oscHandlers[identifier];
|
let oHandler = this._oscHandlers[identifier];
|
||||||
if (callback) callback(content);
|
if (oHandler) {
|
||||||
else this._oscHandlerFb(identifier, content);
|
for (let i = oHandler.length; ;) {
|
||||||
|
if (--i < 0) { oHandler = null; break; }
|
||||||
|
if ((oHandler[i])(content))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (! oHandler) this._oscHandlerFb(identifier, content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (code === 0x1b) transition |= ParserState.ESCAPE;
|
if (code === 0x1b) transition |= ParserState.ESCAPE;
|
||||||
|
|||||||
+15
-2
@@ -4,7 +4,7 @@
|
|||||||
* @license MIT
|
* @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 { C0, C1 } from './common/data/EscapeSequences';
|
||||||
import { CHARSETS, DEFAULT_CHARSET } from './core/data/Charsets';
|
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 { 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';
|
||||||
@@ -112,7 +112,7 @@ class DECRQSS implements IDcsHandler {
|
|||||||
* Refer to http://invisible-island.net/xterm/ctlseqs/ctlseqs.html to understand
|
* Refer to http://invisible-island.net/xterm/ctlseqs/ctlseqs.html to understand
|
||||||
* each function's header comment.
|
* each function's header comment.
|
||||||
*/
|
*/
|
||||||
export class InputHandler extends Disposable implements IInputHandler {
|
export class InputHandler extends Disposable implements IVtInputHandler {
|
||||||
private _surrogateFirst: string;
|
private _surrogateFirst: string;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -465,6 +465,19 @@ export class InputHandler extends Disposable implements IInputHandler {
|
|||||||
this._terminal.updateRange(buffer.y);
|
this._terminal.updateRange(buffer.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addCsiHandler(flag: string, callback: (params: number[], collect: string) => boolean): void {
|
||||||
|
this._parser.addCsiHandler(flag, callback);
|
||||||
|
}
|
||||||
|
removeCsiHandler(flag: string, callback: (params: number[], collect: string) => boolean): void {
|
||||||
|
this._parser.removeCsiHandler(flag, callback);
|
||||||
|
}
|
||||||
|
addOscHandler(ident: number, callback: (data: string) => boolean): void {
|
||||||
|
this._parser.setOscHandler(ident, callback);
|
||||||
|
}
|
||||||
|
removeOscHandler(ident: number, callback: (data: string) => boolean): void {
|
||||||
|
this._parser.removeOscHandler(ident, callback);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BEL
|
* BEL
|
||||||
* Bell (Ctrl-G).
|
* Bell (Ctrl-G).
|
||||||
|
|||||||
+5
-1
@@ -21,7 +21,7 @@
|
|||||||
* http://linux.die.net/man/7/urxvt
|
* 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 { IMouseZoneManager } from './ui/Types';
|
||||||
import { IRenderer } from './renderer/Types';
|
import { IRenderer } from './renderer/Types';
|
||||||
import { BufferSet } from './BufferSet';
|
import { BufferSet } from './BufferSet';
|
||||||
@@ -1286,6 +1286,10 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
|||||||
this.refresh(0, this.rows - 1);
|
this.refresh(0, this.rows - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get inputHandler(): IInputHandler {
|
||||||
|
return this._inputHandler;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scroll the display of the terminal by a number of pages.
|
* Scroll the display of the terminal by a number of pages.
|
||||||
* @param pageCount The number of pages to scroll (negative scrolls up).
|
* @param pageCount The number of pages to scroll (negative scrolls up).
|
||||||
|
|||||||
@@ -182,6 +182,16 @@ export interface IInputHandler {
|
|||||||
ESC ~ */ setgLevel(level: number): void;
|
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): void;
|
||||||
|
removeCsiHandler(flag: string, callback: (params: number[], collect: string) => boolean): void;
|
||||||
|
addOscHandler(ident: number, callback: (data: string) => boolean): void;
|
||||||
|
removeOscHandler(ident: number, callback: (data: string) => boolean): void;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ILinkMatcher {
|
export interface ILinkMatcher {
|
||||||
id: number;
|
id: number;
|
||||||
regex: RegExp;
|
regex: RegExp;
|
||||||
@@ -492,6 +502,10 @@ export interface IEscapeSequenceParser extends IDisposable {
|
|||||||
setCsiHandler(flag: string, callback: (params: number[], collect: string) => void): void;
|
setCsiHandler(flag: string, callback: (params: number[], collect: string) => void): void;
|
||||||
clearCsiHandler(flag: string): void;
|
clearCsiHandler(flag: string): void;
|
||||||
setCsiHandlerFallback(callback: (collect: string, params: number[], flag: number) => void): void;
|
setCsiHandlerFallback(callback: (collect: string, params: number[], flag: number) => void): void;
|
||||||
|
addCsiHandler(flag: string, callback: (params: number[], collect: string) => boolean): void;
|
||||||
|
removeCsiHandler(flag: string, callback: (params: number[], collect: string) => boolean): void;
|
||||||
|
addOscHandler(ident: number, callback: (data: string) => boolean): void;
|
||||||
|
removeOscHandler(ident: number, callback: (data: string) => boolean): void;
|
||||||
|
|
||||||
setEscHandler(collectAndFlag: string, callback: () => void): void;
|
setEscHandler(collectAndFlag: string, callback: () => void): void;
|
||||||
clearEscHandler(collectAndFlag: string): void;
|
clearEscHandler(collectAndFlag: string): void;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings } from 'xterm';
|
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 { Terminal as TerminalCore } from '../Terminal';
|
||||||
import * as Strings from '../Strings';
|
import * as Strings from '../Strings';
|
||||||
|
|
||||||
@@ -15,6 +15,9 @@ export class Terminal implements ITerminalApi {
|
|||||||
this._core = new TerminalCore(options);
|
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 element(): HTMLElement { return this._core.element; }
|
||||||
public get textarea(): HTMLTextAreaElement { return this._core.textarea; }
|
public get textarea(): HTMLTextAreaElement { return this._core.textarea; }
|
||||||
public get rows(): number { return this._core.rows; }
|
public get rows(): number { return this._core.rows; }
|
||||||
|
|||||||
Reference in New Issue
Block a user