Skip to content

Commit

Permalink
Merge 29cc0bf into fcef4d5
Browse files Browse the repository at this point in the history
  • Loading branch information
PerBothner committed Dec 21, 2018
2 parents fcef4d5 + 29cc0bf commit 6f44495
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 2 deletions.
8 changes: 7 additions & 1 deletion fixtures/typings-test/typings-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

/// <reference path="../../typings/xterm.d.ts" />

import { Terminal } from 'xterm';
import { Terminal, IDisposable } from 'xterm';

namespace constructor {
{
Expand Down Expand Up @@ -119,6 +119,12 @@ namespace methods_core {
const t: Terminal = new Terminal();
t.attachCustomKeyEventHandler((e: KeyboardEvent) => true);
t.attachCustomKeyEventHandler((e: KeyboardEvent) => false);
const d1: IDisposable = t.addCsiHandler("x",
(params: number[], collect: string): boolean => params[0]===1);
d1.dispose();
const d2: IDisposable = t.addOscHandler(199,
(data: string): boolean => true);
d2.dispose();
}
namespace options {
{
Expand Down
50 changes: 49 additions & 1 deletion src/EscapeSequenceParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@
*/

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

interface IHandlerLink extends IDisposable {
nextHandler: IHandlerLink | null;
}

/**
* Returns an array filled with numbers between the low and high parameters (right exclusive).
* @param low The low number.
Expand Down Expand Up @@ -41,7 +46,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 +308,38 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
this._executeHandlerFb = callback;
}

private _linkHandler(handlers: object[], index: number, newCallback: object): IDisposable {
const newHead: any = newCallback;
newHead.nextHandler = handlers[index] as IHandlerLink;
newHead.dispose = function (): void {
let previous = null;
let cur = handlers[index] as IHandlerLink;
for (; cur && cur.nextHandler;
previous = cur, cur = cur.nextHandler) {
if (cur === newHead) {
if (previous) { previous.nextHandler = cur.nextHandler; }
else { handlers[index] = cur.nextHandler; }
break;
}
}
};
handlers[index] = newHead;
return newHead;
}

addCsiHandler(flag: string, callback: (params: number[], collect: string) => boolean): IDisposable {
const index = flag.charCodeAt(0);
const newHead =
(params: number[], collect: string): void => {
if (! callback(params, collect)) {
const next = (newHead as unknown as IHandlerLink).nextHandler;
if (next) { (next as any)(params, collect); }
else { this._csiHandlerFb(collect, params, index); }
}
};
return this._linkHandler(this._csiHandlers, index, newHead);
}

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

addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable {
const newHead =
(data: string): void => {
if (! callback(data)) {
const next = (newHead as unknown as IHandlerLink).nextHandler;
if (next) { (next as any)(data); }
else { this._oscHandlerFb(ident, data); }
}
};
return this._linkHandler(this._oscHandlers, ident, newHead);
}
setOscHandler(ident: number, callback: (data: string) => void): void {
this._oscHandlers[ident] = callback;
}
Expand Down
8 changes: 8 additions & 0 deletions src/InputHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ 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 @@ -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
9 changes: 9 additions & 0 deletions src/Terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1413,6 +1413,15 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
this._customKeyEventHandler = customKeyEventHandler;
}

/** Add handler for CSI escape sequence. See xterm.d.ts for details. */
public addCsiHandler(flag: string, callback: (params: number[], collect: string) => boolean): IDisposable {
return this._inputHandler.addCsiHandler(flag, callback);
}
/** Add handler for OSC escape sequence. See xterm.d.ts for details. */
public addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable {
return this._inputHandler.addOscHandler(ident, callback);
}

/**
* Registers a link matcher, allowing custom link patterns to be matched and
* handled.
Expand Down
2 changes: 2 additions & 0 deletions src/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,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
6 changes: 6 additions & 0 deletions src/public/Terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ export class Terminal implements ITerminalApi {
public attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void {
this._core.attachCustomKeyEventHandler(customKeyEventHandler);
}
public addCsiHandler(flag: string, callback: (params: number[], collect: string) => boolean): IDisposable {
return this._core.addCsiHandler(flag, callback);
}
public addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable {
return this._core.addOscHandler(ident, callback);
}
public registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => void, options?: ILinkMatcherOptions): number {
return this._core.registerLinkMatcher(regex, handler, options);
}
Expand Down
6 changes: 6 additions & 0 deletions src/ui/TestUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ export class MockTerminal implements ITerminal {
attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void {
throw new Error('Method not implemented.');
}
addCsiHandler(flag: string, callback: (params: number[], collect: string) => boolean): IDisposable {
throw new Error('Method not implemented.');
}
addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable {
throw new Error('Method not implemented.');
}
registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => boolean | void, options?: ILinkMatcherOptions): number {
throw new Error('Method not implemented.');
}
Expand Down
25 changes: 25 additions & 0 deletions typings/xterm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,31 @@ declare module 'xterm' {
*/
attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void;

/**
* (EXPERIMENTAL) Adds a handler for CSI escape sequences.
* @param flag The flag should be one-character string, which specifies
* the final character (e.g "m" for SGR) of the CSI sequence.
* @param callback The function to handle the escape sequence.
* The callback is called with the numerical params,
* as well as the special characters (e.g. "$" for DECSCPP).
* Return true if the sequence was handled; false if we should
* try a previous handler (set by addCsiHandler or setCsiHandler).
* The most recently-added handler is tried first.
* @return An IDisposable you can call to remove this handler.
*/
addCsiHandler(flag: string, callback: (params: number[], collect: string) => boolean): IDisposable;

/**
* (EXPERIMENTAL) Adds a handler for OSC escape sequences.
* @param ident The number (first parameter) of the sequence.
* @param callback The function to handle the escape sequence.
* The callback is called with OSC data string.
* Return true if the sequence was handled; false if we should
* try a previous handler (set by addOscHandler or setOscHandler).
* The most recently-added handler is tried first.
* @return An IDisposable you can call to remove this handler.
*/
addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable;
/**
* (EXPERIMENTAL) Registers a link matcher, allowing custom link patterns to
* be matched and handled.
Expand Down

0 comments on commit 6f44495

Please sign in to comment.