Merge pull request #32468 from katsanva/master

Add types for terminal-kit
This commit is contained in:
Benjamin Lichtman
2019-01-25 10:40:36 -08:00
committed by GitHub
13 changed files with 1999 additions and 0 deletions

279
types/nextgen-events/index.d.ts vendored Normal file
View File

@@ -0,0 +1,279 @@
// Type definitions for nextgen-events 1.1
// Project: https://github.com/cronvel/nextgen-events#readme
// Definitions by: katsanva <https://github.com/katsanva>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.2
export = NextGenEvents;
declare class NextGenEvents {
static readonly CONTEXT_ENABLED: 0;
static readonly CONTEXT_DISABLED: 1;
static readonly CONTEXT_QUEUED: 2;
constructor();
addListener(
eventName: string,
fn?: any,
options?: NextGenEvents.AddListenerOptions
): this;
on(
eventName: string,
fn?: any,
options?: NextGenEvents.AddListenerOptions
): this;
once(
eventName: string,
fn?: any,
options?: NextGenEvents.AddListenerOptions
): this;
waitFor(eventName: string): Promise<this>;
waitForAll(eventName: string): Promise<this>;
removeListener(eventName: string, id: any): this;
off(eventName: string, id: any): this;
removeAllListeners(eventName: string): this;
emit(nice: number, name: string, ...args: any[]): NextGenEvents.Event;
emit(name: string, ...args: any[]): NextGenEvents.Event;
waitForEmit(nice: number, name: string, ...args: any[]): Promise<any>;
waitForEmit(name: string, ...args: any[]): Promise<any>;
listeners(eventName: string): NextGenEvents.Func[];
listenerCount(eventName: string): number;
setNice(nice: number): void;
desyncUseNextTick(useNextTick: boolean): void;
setInterruptible(isInterruptible: boolean): void;
getMaxListeners(): number;
setMaxListeners(n: number): this;
defineStates(...states: any[]): void;
hasState(state: string): boolean;
getAllStates(): NextGenEvents.States;
addListenerContext(
contextName: string,
options: NextGenEvents.ContextOptions
): this;
disableListenerContext(contextName: string): this;
enableListenerContext(contextName: string): this;
queueListenerContext(contextName: string): this;
serializeListenerContext(contextName: string, value?: boolean): this;
setListenerContextNice(contextName: string, nice: number): this;
destroyListenerContext(contextName: string): this;
static emitEvent(event: NextGenEvents.Event): NextGenEvents.Event;
static init(): void;
static initFrom(from: NextGenEvents): void;
static mergeListeners(foreigners: NextGenEvents.Listeners): void;
static filterOutCallback(what: any, currentElement: any): boolean;
static listenerWrapper(
listener: any,
event: any,
contextScope: string,
serial: any
): void;
static emitToOneListener(
event: NextGenEvents.Event,
listener: any,
removedListeners: any
): void;
static emitCallback(event: NextGenEvents.Event): void;
static listenerCount(emitter: NextGenEvents, eventName: string): number;
static share(source: NextGenEvents, target: NextGenEvents): void;
static reset(emitter: NextGenEvents): void;
static noop(...args: any[]): void;
static groupAddListener(
emitters: NextGenEvents[],
eventName: string,
fn?: NextGenEvents.Func,
options?: NextGenEvents.AddListenerOptions
): any;
static groupOn(
emitters: NextGenEvents[],
eventName: string,
fn?: NextGenEvents.Func,
options?: NextGenEvents.AddListenerOptions
): any;
static groupOnce(
emitters: NextGenEvents[],
eventName: string,
fn?: NextGenEvents.Func,
options?: NextGenEvents.AddListenerOptions
): void;
static groupWaitFor(
emitters: NextGenEvents[],
eventName: string
): Promise<void>;
static groupWaitForAll(
emitters: NextGenEvents[],
eventName: string
): Promise<void>;
static groupOnceFirst(
emitters: NextGenEvents[],
eventName: string,
fn?: NextGenEvents.Func,
options?: NextGenEvents.AddListenerOptions
): void;
static groupGlobalOnce(
emitters: NextGenEvents[],
eventName: string,
fn?: NextGenEvents.Func,
options?: NextGenEvents.AddListenerOptions
): void;
static groupWaitForFirst(
emitters: NextGenEvents[],
eventName: string
): Promise<void>;
static groupWaitForFirstAll(
emitters: NextGenEvents[],
eventName: string
): Promise<void>;
static groupOnceLast(
emitters: NextGenEvents[],
eventName: string,
fn?: NextGenEvents.Func,
options?: NextGenEvents.AddListenerOptions
): void;
static groupGlobalOnceAll(
emitters: NextGenEvents[],
eventName: string,
fn?: NextGenEvents.Func,
options?: NextGenEvents.AddListenerOptions
): void;
static groupWaitForLast(
emitters: NextGenEvents[],
eventName: string
): Promise<void>;
static groupWaitForLastAll(
emitters: NextGenEvents[],
eventName: string
): Promise<void>;
static groupRemoveListener(
emitters: NextGenEvents[],
eventName: string,
id: number
): void;
static groupRemoveAllListeners(
emitters: NextGenEvents[],
eventName: string
): void;
static groupEmit(
emitters: NextGenEvents[],
nice?: number,
...args: any[]
): void;
static groupWaitForEmit(
emitters: NextGenEvents[],
nice?: number,
...args: any[]
): Promise<void>;
static groupDefineStates(emitters: NextGenEvents[], ...args: any[]): void;
static getContextScope(
context: NextGenEvents.Context,
scopeName: string
): NextGenEvents.Scope;
static processScopeQueue(
self: NextGenEvents,
contextScope: NextGenEvents.Scope,
serial: boolean,
isCompletionCallback: boolean
): void;
}
declare namespace NextGenEvents {
interface Event {
emitter: NextGenEvents;
interrupt: null;
sync: boolean;
mice: number;
name: string;
callback: (interrupt: any) => any;
args: any;
}
type AddListenerOptions =
| boolean
| {
fn: any;
id?: any;
once: any;
async: any;
eventObject: any;
nice?: number;
context?: string;
};
const SYNC: number;
const DESYNC: number;
const defaultMaxListeners: number;
type Func = (...args: any[]) => any;
interface Listeners {
error: Func[];
interrupt: Func[];
newListener: Func[];
removeListener: Func[];
}
interface States {
[key: string]: any;
}
interface Context {
nice: typeof SYNC;
ready: boolean;
status: any;
serial: boolean;
scopes: { [key: string]: any };
}
interface Scope {
ready: boolean;
queue: any[];
}
interface ContextOptions {
nice?: typeof SYNC;
ready: boolean;
status?: any;
serial?: any;
scopes: {
[key: string]: Scope;
};
}
class Internal {
nice: typeof SYNC;
interruptible: boolean;
contexts: {
[key: string]: Context;
};
desync: (fn: (...args: any[]) => void, ...args: any[]) => void;
depth: number;
states: States;
stateGroups: { [key: string]: any };
listeners: Listeners;
maxListeners: typeof defaultMaxListeners;
constructor(from?: NextGenEvents);
}
class Proxy {
receive: (raw: any) => void;
send: (message: any) => void;
remoteServices: {
[key: string]: NextGenEvents;
};
addLocalService(
name: string,
heartBeatEmitter: any,
options: { listen: boolean; emit: boolean; ack: boolean }
): void;
addRemoteService(name: string): void;
push(data: any): void;
destroy(): any;
}
}

View File

@@ -0,0 +1,251 @@
import * as NgEmitter from 'nextgen-events';
import * as WebSocket from 'ws';
const emitter = new NgEmitter();
// Normal listener
emitter.on('message', (message: any) => {});
// One time listener:
emitter.once('close', () => {});
// The error listener: if it is not defined, the error event will throw an exception
emitter.on('error', (error: any) => {});
emitter.emit('message', 'Hello world!');
// ...
emitter.on('connection', {
context: 'ctx',
fn: (stream: any) => {},
});
emitter.on('close', {
context: 'ctx',
fn: () => {
// Destroy the context and all listeners tied to it:
emitter.destroyListenerContext('ctx');
},
});
emitter.on('erroHr', {
context: 'ctx',
fn: () => {
// some error handling code
// Destroy the context and all listeners tied to it:
emitter.destroyListenerContext('ctx');
},
});
emitter.once('connection', (stream: any) => {});
emitter.on('connection', {
fn: (stream: any) => {},
once: true,
});
async () => {
const remote = await emitter.waitFor('connect');
emitter.defineStates('connect');
emitter.emit('connect', remote);
// ... somewhere else or in another file...
};
// Now we are sure that we are ready!
// We can connect to the DB or whatever your emitter is for...
const callback1 = (stream: any) => {};
emitter.on('connection', callback1);
// ...
emitter.removeListener('connection', callback1);
const callback2 = (stream: any) => {};
emitter.on('connection', { id: 'foo', fn: callback2 });
emitter.on('connection', { id: 'bar', fn: callback2 });
// ...
// Does nothing! we have used custom IDs!
emitter.removeListener('connection', callback2);
// Remove the first listener only, despite the fact they are sharing the same function
emitter.removeListener('connection', 'foo');
emitter.on('connection', (stream: any) => {});
// output:
// [ { id: [Function], fn: [Function], nice: -Infinity, event: 'connection' } ]
emitter.defineStates('ready');
emitter.emit('ready');
// ... later... ... ...
emitter.once('ready', () => {
// Your listener code fire immediately
});
emitter.on('foo', () => {
return new Error('Dang!');
});
emitter.on('foo', () => {
// Never ever called...
});
emitter.on('interrupt', (interruption: any) => {
// interruption is eql to Error( 'Dang!' )
});
emitter.emit('foo', (interruption: any) => {
// interruption is eql to Error( 'Dang!' )
});
const performSomeCriticalAsyncStuff = (f: any) =>
(async () => {
return f();
})();
emitter.on('maintenance', {
context: 'maintenanceHandlers',
async: true,
fn: (type: any, done: any) => {
performSomeCriticalAsyncStuff(() => {
done();
});
},
});
const maintenanceHandlers = 'foo';
emitter.serializeListenerContext(maintenanceHandlers);
// ...
emitter.emit('maintenance', 'doBackup');
// Despite the fact we emit synchronously, the listener will not be called now,
// it will be queued and called later when the previous call will be finished
emitter.emit('maintenance', 'doUpgrade');
const performBackup = (fn: any) => {};
const performUpgrade = (fn: any) => {};
emitter.on('doBackup', {
context: 'maintenanceHandlers',
async: true,
fn: (done: any) => {
performBackup(() => {
done();
});
},
});
emitter.on('doUpgrade', {
context: 'maintenanceHandlers',
async: true,
fn: (done: any) => {
performUpgrade(() => {
done();
});
},
});
emitter.on('whatever', () => {
// Some actions...
});
emitter.serializeListenerContext(maintenanceHandlers);
// ...
emitter.emit('doBackup');
// Despite the fact we emit synchronously, the second listener will not be called now,
// it will be queued and called later when the first listener will have finished its job
emitter.emit('doUpgrade');
// The third listener is not part of the 'maintenanceHandlers' context, so it will be called
// right now, before the first listener finished, and before the second listener ever start
emitter.emit('whatever');
// Create our service/emitter
const heartBeatEmitter = new NgEmitter();
// Create our server
const server = new WebSocket.Server({ port: 12345 });
// On new connection...
emitter.on('connection', function connection(ws: any) {
// Create a proxy for this client
const proxy = new NgEmitter.Proxy();
// Add the local service exposed to this client and grant it all right
proxy.addLocalService('heartBeatService', heartBeatEmitter, {
listen: true,
emit: true,
ack: true,
});
// message received: just hook to proxy.receive()
ws.on('message', function incoming(message: any) {
proxy.receive(message);
});
// Define the receive method: should call proxy.push()
// after decoding the raw message
proxy.receive = function receive(raw: any) {
try {
proxy.push(JSON.parse(raw));
} catch (error) {}
};
// Define the send method
proxy.send = function send(message: any) {
ws.send(JSON.stringify(message));
};
// Clean up after everything is done
ws.on('close', function close() {
proxy.destroy();
});
});
const ws = new WebSocket('ws://127.0.0.1:12345');
// Create a proxy
const proxy = new NgEmitter.Proxy();
// Once the connection is established...
ws.on('open', function open() {
// Add the remote service we want to access
proxy.addRemoteService('heartBeatService');
// Listen to the event 'heartBeat' on this service
proxy.remoteServices.heartBeatService.on('heartBeat', (beat: any) => {});
});
// message received: just hook to proxy.receive()
ws.on('message', (message: any) => {
proxy.receive(message);
});
// Define the receive method: should call proxy.push()
// after decoding the raw message
proxy.receive = function receive(raw: any) {
try {
proxy.push(JSON.parse(raw));
} catch (error) {}
};
// Define the send method
proxy.send = function send(message: any) {
ws.send(JSON.stringify(message));
};
// Clean up after everything is done
ws.on('close', function close() {
proxy.destroy();
});

View File

@@ -0,0 +1,16 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": ["es6"],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": ["../"],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true,
"strictFunctionTypes": false
},
"files": ["index.d.ts", "nextgen-events-tests.ts"]
}

View File

@@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }

61
types/terminal-kit/Rect.d.ts vendored Normal file
View File

@@ -0,0 +1,61 @@
import Terminal = require("./Terminal");
import ScreenBuffer = require("./ScreenBuffer");
import TextBuffer = require("./TextBuffer");
declare class Rect {
readonly width: number;
readonly height: number;
readonly xmin: number;
readonly ymin: number;
readonly xmax: number;
readonly ymax: number;
readonly isNull: boolean;
constructor(
options:
| Rect.AbsoluteOptions
| Rect.Region
| Rect
| Terminal
| ScreenBuffer
| TextBuffer
);
constructor(xmin: number, xmax: number, ymin: number, ymax: number);
static wrappingRect(params: {
srcRect: Rect;
dstRect: Rect;
offsetX: number;
offsetY: number;
wrapOnly?: "x" | "y";
}): void;
set(obj: Rect.Region): void;
clip(
dstRect: Rect,
offsetX: number,
offsetY: number,
dstClipping: boolean
): void;
}
export = Rect;
declare namespace Rect {
type Options = AbsoluteOptions | Region;
interface AbsoluteOptions {
width: number;
height: number;
x?: number;
y?: number;
}
interface Region {
xmin: number;
ymin: number;
xmax: number;
ymax: number;
}
}

139
types/terminal-kit/ScreenBuffer.d.ts vendored Normal file
View File

@@ -0,0 +1,139 @@
import NextGenEvents = require("nextgen-events");
import Terminal = require("./Terminal");
import ScreenBufferHD = require("./ScreenBufferHD");
import Rect = require("./Rect");
declare class ScreenBuffer extends NextGenEvents {
readonly dst: Terminal | ScreenBuffer;
readonly x: number;
readonly y: number;
readonly blending: boolean | ScreenBufferHD.IsBlending;
constructor(options: ScreenBuffer.Options);
static create(options: ScreenBuffer.Options): ScreenBuffer;
static createFromString(
options: {
attr: number | ScreenBuffer.Attributes;
transparencyChar: string;
transparencyType: number;
},
str: string
): ScreenBuffer;
static loadImage(
url: string,
options: {
terminal: Terminal;
shrink?: {
width: number;
height: number;
};
},
calback: (error: any, image: ScreenBufferHD) => void
): void;
static loadImage(
url: string,
calback: (error?: any, image?: ScreenBufferHD) => void
): void;
static attr2object(attrFlags: number): void;
attr2object(attrFlags: number): void;
static object2attr(attrObject: ScreenBuffer.Attributes): void;
object2attr(attrObject: ScreenBuffer.Attributes): void;
static loadSync(filepath: string): ScreenBuffer;
fill(options?: {
attr: ScreenBuffer.Attributes | number;
char?: string;
}): void;
clear(): void;
put(
options: ScreenBuffer.PutOptions,
format: string,
...formatArgumets: any[]
): void;
get(options?: {
x: number;
y: number;
}): { char: string; attr: ScreenBuffer.Attributes };
resize(fromRect: Rect | Rect.Options): void;
draw(options?: ScreenBuffer.DrawOptions): void;
drawCursor(options?: { dst: Terminal | ScreenBuffer }): void;
moveTo(x: number, y: number): void;
vScroll(offset: number, drawToTerminal: boolean): void;
dumpChars(): string;
saveSync(filepath: string): void;
}
export = ScreenBuffer;
declare namespace ScreenBuffer {
interface Options {
width?: number;
height?: number;
dst: Terminal | ScreenBuffer;
x?: number;
y?: number;
blending?: boolean;
wrap?: boolean;
noFill?: boolean;
}
interface DrawOptions {
dst?: Terminal | ScreenBuffer;
x?: number;
y?: number;
srcClipRect?: Rect;
dstClipRect?: Rect;
blending?: boolean;
delta?: boolean;
wrap?: boolean | "x" | "y";
tile?: boolean;
}
interface Attributes {
color?: number;
defaultColor?: boolean;
bgColor?: number;
bgDefaultColor?: boolean;
bold?: boolean;
dim?: boolean;
italic?: boolean;
underline?: boolean;
blink?: boolean;
inverse?: boolean;
hidden?: boolean;
strike?: boolean;
transparency?: boolean;
fgTransparency?: boolean;
bgTransparency?: boolean;
styleTransparency?: boolean;
charTransparency?: boolean;
}
interface PutOptions {
x: number;
y: number;
attr: Attributes | number;
wrap: boolean;
direction?: "right" | "left" | "up" | "down" | null;
dx: number;
dy: number;
}
}

83
types/terminal-kit/ScreenBufferHD.d.ts vendored Normal file
View File

@@ -0,0 +1,83 @@
import ScreenBuffer = require("./ScreenBuffer");
declare class ScreenBufferHD extends ScreenBuffer {
constructor(
options: { blending: ScreenBufferHD.IsBlending } | ScreenBuffer.Options
);
readonly blending: ScreenBufferHD.IsBlending;
static loadImage(
url: string,
calback: (error?: any, image?: ScreenBufferHD) => void
): void;
static loadImage(
url: string,
options: { shrink?: { height: number; width: number } },
callback: (error: any, image: ScreenBufferHD) => void
): void;
draw(
options?: ScreenBuffer.DrawOptions | { blending: ScreenBufferHD.IsBlending }
): void;
fill(
options?:
| {
attr: ScreenBuffer.Attributes | number;
char?: string;
}
| {
attr: ScreenBufferHD.Attributes | number;
char?: string;
}
): void;
}
export = ScreenBufferHD;
declare namespace ScreenBufferHD {
interface Attributes {
r: number;
g: number;
b: number;
a?: number;
defaultColor?: boolean;
bgR: number;
bgG: number;
bgB: number;
bgA?: number;
bgDefaultColor?: boolean;
bold?: boolean;
dim?: boolean;
italic?: boolean;
underline?: boolean;
blink?: boolean;
inverse?: boolean;
hidden?: boolean;
strike?: boolean;
transparency?: boolean;
styleTransparency?: boolean;
charTransparency?: boolean;
}
type IsBlending = false | Blending;
interface Blending {
fn: BlendFunction;
opacity: number;
blendSrcFgWithDstBg: boolean;
}
type BlendFunction = (src: number, dst: number) => number;
interface BlendFn {
normal: BlendFunction;
multiply: BlendFunction;
screen: BlendFunction;
overlay: BlendFunction;
hardLight: BlendFunction;
softLight: BlendFunction;
}
}

545
types/terminal-kit/Terminal.d.ts vendored Normal file
View File

@@ -0,0 +1,545 @@
import EventEmitter = require("nextgen-events");
type Terminal = Terminal.Impl & EventEmitter;
export = Terminal;
type Callback<T> = ((err: any) => void) | ((err: undefined, arg: T) => void);
declare namespace Terminal {
interface Impl {
width: number;
height: number;
appName: string;
app: string;
generic: string;
termconfigFile: string;
(str?: string): Terminal;
(...args: any[]): Terminal;
defaultColor: CTerminal;
black: CTerminal;
red: CTerminal;
green: CTerminal;
yellow: CTerminal;
blue: CTerminal;
magenta: CTerminal;
cyan: CTerminal;
white: CTerminal;
brightBlack: CTerminal;
gray: CTerminal;
grey: CTerminal;
brightRed: CTerminal;
brightGreen: CTerminal;
brightYellow: CTerminal;
brightBlue: CTerminal;
brightMagenta: CTerminal;
brightCyan: CTerminal;
brightWhite: CTerminal;
color: (register: number) => Terminal;
darkColor: (register: number) => Terminal;
brightColor: (register: number) => Terminal;
color256: (register: number) => Terminal;
colorRgb: (r: number, g: number, b: number) => Terminal;
colorRgbHex: (rgb: string) => Terminal;
colorGrayscale: (I: number) => Terminal;
bgDefaultColor: CTerminal;
bgBlack: CTerminal;
bgRed: CTerminal;
bgGreen: CTerminal;
bgYellow: CTerminal;
bgBlue: CTerminal;
bgMagenta: CTerminal;
bgCyan: CTerminal;
bgWhite: CTerminal;
bgBrightBlack: CTerminal;
bgGray: CTerminal;
bgGrey: CTerminal;
bgBrightRed: CTerminal;
bgBrightGreen: CTerminal;
bgBrightYellow: CTerminal;
bgBrightBlue: CTerminal;
bgBrightMagenta: CTerminal;
bgBrightCyan: CTerminal;
bgBrightWhite: CTerminal;
bgColor: (register: number) => Terminal;
bgDarkColor: (register: number) => Terminal;
bgBrightColor: (register: number) => Terminal;
bgColor256: (register: number) => Terminal;
bgColorRgb: (r: number, g: number, b: number) => Terminal;
bgColorRgbHex: (rgb: string) => Terminal;
bgColorGrayscale: (I: number) => Terminal;
styleReset: CTerminal;
bold: CTerminal;
dim: CTerminal;
italic: CTerminal;
underline: CTerminal;
blink: CTerminal;
inverse: CTerminal;
hidden: CTerminal;
strike: CTerminal;
saveCursor: Terminal;
restoreCursor: Terminal;
up: ((n: number) => Terminal) | ((n: number, ...args: any[]) => Terminal);
down: (n: number) => Terminal;
right: (n: number) => Terminal;
left: (n: number) => Terminal;
nextLine: (n: number) => Terminal;
previousLine: (n: number) => Terminal;
column: (x: number) => Terminal;
scrollUp: (n: number) => Terminal;
scrollDown: (n: number) => Terminal;
scrollingRegion: (top: number, bottom: number) => Terminal;
resetScrollingRegion: Terminal;
moveTo: CTerminal;
move: (x: number, y: number) => Terminal;
hideCursor: Terminal;
tabSet: Terminal;
tabClear: Terminal;
tabClearAll: Terminal;
forwardTab: (n: number) => Terminal;
backwardTab: (n: number) => Terminal;
clear: Terminal;
eraseDisplayBelow: Terminal;
eraseDisplayAbove: Terminal;
eraseDisplay: Terminal;
eraseScrollback: Terminal;
eraseLineAfter: Terminal;
eraseLineBefore: Terminal;
eraseLine: Terminal;
eraseArea: (
x: number,
y: number,
width?: number,
height?: number
) => Terminal;
insertLine: (n: number) => Terminal;
deleteLine: (n: number) => Terminal;
insert: (n: number) => Terminal;
delete: (n: number) => Terminal;
backDelete: Terminal;
alternateScreenBuffer: Terminal;
requestCursorLocation: Terminal;
requestScreenSize: Terminal;
requestColor: (n: number) => Terminal;
applicationKeypad: Terminal;
mouseButton: Terminal;
mouseDrag: Terminal;
mouseMotion: Terminal;
mouseSGR: Terminal;
focusEvent: Terminal;
cwd: (uri: string) => Terminal;
windowTitle: (str: string) => Terminal;
iconName: (str: string) => Terminal;
notify: (title: string, text: string) => Terminal;
error: Terminal;
str: Terminal;
noFormat: (str: string) => Terminal;
markupOnly: (str: string) => Terminal;
wrap: CTerminal;
bindArgs: (...args: any[]) => Terminal;
reset: Terminal;
bell: Terminal;
setCursorColor: (register: number) => Terminal;
setCursorColorRgb: (r: number, g: number, b: number) => Terminal;
resetCursorColorRgb: Terminal;
setDefaultColorRgb: (r: number, g: number, b: number) => Terminal;
resetDefaultColorRgb: Terminal;
setDefaultBgColorRgb: (r: number, g: number, b: number) => Terminal;
resetDefaultBgColorRgb: Terminal;
setHighlightBgColorRgb: (r: number, g: number, b: number) => Terminal;
resetHighlightBgColorRgb: Terminal;
fullscreen: (options: boolean | { noAlternate: boolean }) => void;
processExit: (code: number) => void;
grabInput(
options:
| boolean
| {
mouse?: "button" | "drag" | "motion";
safe?: boolean;
},
safeCallback?: boolean
): void;
getCursorLocation: (
callback: (error: any, x?: number, y?: number) => void
) => void;
getColor(
register: number,
callback?: Callback<{ r: number; g: number; b: number }>
): void;
setColor(
register: number,
r: number,
g: number,
b: number,
names?: ReadonlyArray<string>
): void;
setColor(
register: number,
rgb: { r: number; g: number; b: number },
names?: ReadonlyArray<string>
): void;
getPalette(register: number, callback?: Callback<Palette>): void;
setPalette(palette: string | Palette): void;
wrapColumn(options?: {
width: null | number;
x: number;
continue?: boolean;
offset?: number;
}): void;
wrapColumn(x: undefined | number, width: number): void;
yesOrNo(options: YesOrNoOptions, callback: Callback<boolean>): void;
yesOrNo(
options?: YesOrNoOptions
): {
abort: () => void;
promise?: Promise<boolean>;
};
inputField(options: InputFieldOptions, callback: Callback<string>): void;
inputField(callback: Callback<string>): void;
inputField(
options?: InputFieldOptions
): {
abort: () => void;
promise?: Promise<boolean>;
};
fileInput(options: IFileInputOptions, callback: Callback<string>): void;
fileInput(options?: IFileInputOptions): Promise<string>;
singleLineMenu(
menuItems: ReadonlyArray<string>,
options: SingleLineMenuOptions,
callback: Callback<SingleLineMenuResponse>
): void;
singleLineMenu(
menuItems: ReadonlyArray<string>,
callback: Callback<SingleLineMenuResponse>
): void;
singleLineMenu(
menuItems: ReadonlyArray<string>,
options?: SingleLineMenuOptions
): {
promise: Promise<SingleLineMenuResponse>;
};
singleRowMenu(
menuItems: ReadonlyArray<string>,
options: SingleLineMenuOptions,
callback: Callback<SingleLineMenuResponse>
): void;
singleRowMenu(
menuItems: ReadonlyArray<string>,
callback: Callback<SingleLineMenuResponse>
): void;
singleRowMenu(
menuItems: ReadonlyArray<string>,
options?: SingleLineMenuOptions
): {
promise: Promise<SingleLineMenuResponse>;
};
singleColumnMenu(
menuItems: ReadonlyArray<string>,
options: SingleColumnMenuOptions,
callback: Callback<SingleColumnMenuResponse>
): void;
singleColumnMenu(
menuItems: ReadonlyArray<string>,
callback: Callback<SingleColumnMenuResponse>
): void;
singleColumnMenu(
menuItems: ReadonlyArray<string>,
options?: SingleColumnMenuOptions
): {
promise: Promise<SingleColumnMenuResponse>;
};
gridMenu(
menuItems: ReadonlyArray<string>,
options: GridMenuOptions,
callback: Callback<GridMenuResponse>
): void;
gridMenu(
menuItems: ReadonlyArray<string>,
callback: Callback<GridMenuResponse>
): void;
gridMenu(
menuItems: ReadonlyArray<string>,
options?: GridMenuOptions
): {
promise: Promise<GridMenuResponse>;
};
progressBar(options?: ProgressBarOptions): ProgressBarController;
bar(
value: number,
options?: { innerSize?: number; barStyle?: CTerminal }
): void;
slowTyping(
str: string,
options: {
style?: CTerminal;
flashStyle?: CTerminal;
delay?: number;
flashDelay?: number;
},
callback: Callback<void>
): void;
slowTyping(str: string, callback: Callback<void>): void;
slowTyping(
str: string,
options?: {
style?: CTerminal;
flashStyle?: CTerminal;
delay?: number;
flashDelay?: number;
}
): Promise<void>;
drawImage(
url: string,
options: {
shrink?: {
width: number;
height: number;
};
},
callback: Callback<void>
): void;
drawImage(url: string, callback: Callback<void>): void;
drawImage(
url: string,
options?: {
shrink?: {
width: number;
height: number;
};
}
): Promise<void>;
}
interface ChainableInterface<T> {
(str: string, ...args: any[]): T;
(...args: any[]): T;
}
type Chainable<T> = T & ChainableInterface<T>;
type CTerminal = Terminal & ((...args: any[]) => Terminal);
type Palette = Array<{
r: number;
g: number;
b: number;
names: ReadonlyArray<string>;
}>;
interface YesOrNoOptions {
yes: string | ReadonlyArray<string>;
no: string | ReadonlyArray<string>;
echoYes?: string;
echoNo?: string;
}
type Autocompletion =
| ((
inputString: string,
callback: Callback<string | AutocompletionArray<string>>
) => void)
| ((inputString: string) => Promise<string | AutocompletionArray<string>>);
interface CreateOptions {
stdin?: NodeJS.Process;
stdout?: NodeJS.Process;
stderr?: NodeJS.Process;
generic?: string;
appId: string;
appName: string;
isTTY?: boolean;
isSSH?: boolean;
pid?: any;
preferProcessSigwinch?: boolean;
processSigwinch?: boolean;
}
class AutocompletionArray<T> extends Array<T> {
prefix?: string;
postfix?: string;
}
interface HookConfig {
style?: CTerminal;
hintStyle?: CTerminal;
tokenRegExp?: RegExp;
autoComplete?: string[] | Autocompletion;
autoCompleteMenu?: boolean | Autocompletion;
autoCompleteHint?: boolean;
}
interface InputFieldOptions {
echo?: boolean;
echoChar?: string | true;
default?: string;
cursorPosition?: number;
cancelable?: boolean;
style?: CTerminal;
hintStyle?: CTerminal;
maxLength?: number;
minLength?: number;
history?: string[];
autoComplete?: string[] | Autocompletion;
autoCompleteMenu?: boolean | Autocompletion;
autoCompleteHint?: boolean;
keyBindings?: { [key: string]: string };
tokenHook?: (
token: string,
isEndOfInput: boolean,
previousTokens: ReadonlyArray<string>,
term: Terminal,
config: HookConfig
) => string | CTerminal | null | void;
tokenResetHook?: (
term: Terminal,
config?: HookConfig
) => string | CTerminal;
tokenRegExp?: RegExp;
}
type IFileInputOptions = InputFieldOptions & { baseDir: string };
interface SingleLineMenuResponse {
selectedIndex: number;
selectedText: string;
x: number;
y: number;
canceled: boolean;
unexpectedKey: string;
}
interface SingleLineMenuOptions {
y?: number;
separator?: string;
nextPageHint?: string;
previousPageHint?: string;
style?: CTerminal;
selectedStyle?: CTerminal;
keyBindings?: { [key: string]: string };
cancelable?: boolean;
exitOnUnexpectedKey?: boolean;
}
interface SingleColumnMenuOptions {
y?: number;
style?: CTerminal;
selectedStyle?: CTerminal;
submittedStyle?: CTerminal;
leftPadding?: string;
selectedLeftPadding?: string;
submittedLeftPadding?: string;
extraLines?: number;
oneLineItem?: boolean;
itemMaxWidth?: number;
continueOnSubmit?: boolean;
selectedIndex?: number;
keyBindings?: { [key: string]: string };
cancelable?: boolean;
exitOnUnexpectedKey?: boolean;
}
interface SingleColumnMenuResponse {
selectedIndex: number;
selectedText: string;
submitted: boolean;
x: number;
y: number;
canceled: boolean;
unexpectedKey: string;
}
interface GridMenuOptions {
y?: number;
x?: number;
width: number;
style?: CTerminal;
selectedStyle?: CTerminal;
leftPadding?: string;
selectedLeftPadding?: string;
rightPadding?: string;
selectedRightPadding?: string;
itemMaxWidth?: number;
keyBindings?: { [key: string]: string };
exitOnUnexpectedKey?: boolean;
}
interface GridMenuResponse {
selectedIndex: number;
selectedText: string;
x: number;
y: number;
unexpectedKey: string;
}
interface ProgressBarOptions {
width?: number;
percent?: boolean;
eta?: boolean;
items?: number;
title?: string;
barStyle?: CTerminal;
barBracketStyle?: CTerminal;
percentStyle?: CTerminal;
etaStyle?: CTerminal;
itemStyle?: CTerminal;
titleStyle?: CTerminal;
itemSize?: number;
titleSize?: number;
barChar?: string;
barHeadChar?: string;
maxRefreshTime?: number;
minRefreshTime?: number;
inline?: boolean;
syncMode?: boolean;
}
interface ProgressBarController {
update: (
updateObject:
| number
| { progress: number | null; items?: number; title?: string }
) => void;
startItem: (name: string) => void;
itemDone: (name: string) => void;
stop: () => void;
resume: () => void;
reset: () => void;
}
}

94
types/terminal-kit/TextBuffer.d.ts vendored Normal file
View File

@@ -0,0 +1,94 @@
import ScreenBuffer = require("./ScreenBuffer");
import Rect = require("./Rect");
export as namespace TextBuffer;
declare class TextBuffer {
readonly x: number;
readonly y: number;
constructor(options: TextBuffer.Options);
getText(): string;
setText(text: string): void;
getHidden(): boolean;
setHidden(state: boolean): void;
getContentSize(): { width: number; height: number };
setEmptyCellAttr(attr: ScreenBuffer.Attributes | number): void;
setAttrAt(attr: ScreenBuffer.Attributes | number, x: number, y: number): void;
setAttrCodeAt(attr: number, x: number, y: number): void;
setAttrRegion(
attr: ScreenBuffer.Attributes | number,
region?: Rect.Region
): void;
setAttrCodeRegion(attr: number, region?: Rect.Region): void;
getMisc(): any;
getMiscAt(x: number, y: number): any;
moveTo(x: number, y: number): void;
moveToColumn(x: number): void;
moveToLine(y: number): void;
moveToRow(y: number): void;
move(x: number, y: number): void;
moveUp(): void;
moveDown(): void;
moveLeft(): void;
moveRight(): void;
moveForward(justSkipNullCells: boolean): void;
moveBackward(justSkipNullCells: boolean): void;
moveToEndOfLine(): void;
moveInBound(ignoreCx: boolean): void;
insert(text: string, attr?: ScreenBuffer.Attributes | number): void;
delete(n?: number): void;
bulkDelete(n?: number): void;
newLine(): void;
joinLine(): void;
iterate(
options: { finalCall: boolean },
callback: (
cellData: {
offset: number;
x: number;
y: number;
text: string;
attr: number;
misc: any;
}
) => void
): void;
draw(options?: ScreenBuffer.DrawOptions): void;
drawCursor(options?: { dst: ScreenBuffer }): void;
load(filepath: string, callback: (error?: any) => void): void;
save(filepath: string, callback: (error?: any) => void): void;
}
export = TextBuffer;
declare namespace TextBuffer {
interface Options {
dst: ScreenBuffer;
width?: number;
height?: number;
x?: number;
y?: number;
tabWidth?: number;
forceInBound?: number;
hidden?: boolean;
wrap?: boolean;
}
}

43
types/terminal-kit/index.d.ts vendored Normal file
View File

@@ -0,0 +1,43 @@
// Type definitions for terminal-kit 1.26
// Project: https://github.com/cronvel/terminal-kit#readme
// Definitions by: katsanva <https://github.com/katsanva>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.7
import Rect = require("./Rect");
import ScreenBuffer = require("./ScreenBuffer");
import ScreenBufferHD = require("./ScreenBufferHD");
import Terminal = require("./Terminal");
import TextBuffer = require("./TextBuffer");
export const terminal: Terminal;
export const realTerminal: Terminal;
export function createTerminal(
createOptions?: Terminal.CreateOptions
): Terminal;
export function getParentTerminalInfo(
callback: (error: any, codename?: string, name?: string, pid?: number) => void
): void;
export function getDetectedTerminal(
calback: (error: any, term: Terminal) => void
): void;
export function autoComplete(
array: ReadonlyArray<string>,
startString: string,
returnAlternatives?: boolean,
prefix?: string,
postfix?: string
): string;
export function stripEscapeSequences(str: string): string;
export function stringWidth(str: string): number;
export function truncateString(str: string, maxWidth: number): string;
export { Rect, ScreenBuffer, ScreenBufferHD, Terminal, TextBuffer };

View File

@@ -0,0 +1,469 @@
// Require the lib, get a working terminal
import t, {
terminal as term,
autoComplete as ac,
getDetectedTerminal,
ScreenBufferHD,
ScreenBuffer,
Terminal
} from "terminal-kit";
import "node";
import * as fs from "fs";
new t.Rect({width: 4, height: 4});
// The term() function simply output a string to stdout, using current style
// output "Hello world!" in default terminal's colors
t.terminal("Hello world!\n");
// This output 'red' in red
term.red("red");
// This output 'bold' in bold
term.bold("bold");
// output 'mixed' using bold, underlined & red, exposing the style-mixing syntax
term.bold.underline.red("mixed");
// printf() style formatting everywhere:
// this will output 'My name is Jack, I'm 32.' in green
term.green("My name is %s, I'm %d.\n", "Jack", 32);
// Since v0.16.x, style markup are supported as a shorthand.
// Those two lines produce the same result.
term("My name is ")
.red("Jack")(" and I'm ")
.green("32\n");
term("My name is ^rJack^ and I'm ^g32\n");
// Width and height of the terminal
term("The terminal size is %dx%d", term.width, term.height);
// Move the cursor at the upper-left corner
term.moveTo(1, 1);
// We can always pass additional arguments that will be displayed...
term.moveTo(1, 1, "Upper-left corner");
// ... and formated
term.moveTo(1, 1, "My name is %s, I'm %d.\n", "Jack", 32);
// ... or even combined with other styles
term.moveTo.cyan(1, 1, "My name is %s, I'm %d.\n", "Jack", 32);
// Get some user input
term.magenta("Enter your name: ");
term.inputField((error: any, input: any) => {
term.green("\nYour name is '%s'\n", input);
});
function terminate() {
term.grabInput(false);
setTimeout(() => {}, 100);
}
term.bold.cyan("Type anything on the keyboard...\n");
term.green("Hit CTRL-C to quit.\n\n");
term.grabInput({ mouse: "button" });
term.on("key", (name: string, matches: any[], data: any) => {
console.log("'key' event:", name);
if (name === "CTRL_C") {
terminate();
}
});
term.on("terminal", (name: string, data: any) => {
console.log("'terminal' event:", name, data);
});
term.on("mouse", (name: string, data: any) => {
console.log("'mouse' event:", name, data);
});
// Word-wrap this along the full terminal width
term.wrap.yellow(
`'Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish'`
);
// Word-wrap this inside a column starting at x=10 with a width of 25 terminal cells
term.wrapColumn({ x: 10, width: 25 });
term.wrap.green(
`'Permission is hereby granted, free of charge, to any person obtaining a copy of this software an
d associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish'`
);
// This reset the offset
term("\n");
// term.wrapColumn() could be used as well, but the next text would overwrite the last line
// Text continuation: the second text start at the end of line of the first text
term.wrap.blue("^GP^re^Yr^um^Mi^bs^bs^ci^ro^mn^ is ");
term.wrap.red("hereby granted");
function question() {
term("Do you like javascript? [Y|n]\n");
// Exit on y and ENTER key
// Ask again on n
term.yesOrNo(
{ yes: ["y", "ENTER"], no: ["n"] },
(error: any, result: any) => {
if (result) {
term.green("'Yes' detected! Good bye!\n");
} else {
term.red("'No' detected, are you sure?\n");
question();
}
}
);
}
question();
const history = ["John", "Jack", "Joey", "Billy", "Bob"];
const autoComplete = [
"Barack Obama",
"George W. Bush",
"Bill Clinton",
"George Bush",
"Ronald W. Reagan",
"Jimmy Carter",
"Gerald Ford",
"Richard Nixon",
"Lyndon Johnson",
"John F. Kennedy",
"Dwight Eisenhower",
"Harry Truman",
"Franklin Roosevelt"
];
term("Please enter your name: ");
term.inputField(
{ history, autoComplete, autoCompleteMenu: true },
(error: any, input: string) => {
term.green("\nYour name is '%s'\n", input);
}
);
const history1 = ["John", "Jack", "Joey", "Billy", "Bob"];
const autoComplete1 = [
"Barack Obama",
"George W. Bush",
"Bill Clinton",
"George Bush",
"Ronald W. Reagan",
"Jimmy Carter",
"Gerald Ford",
"Richard Nixon",
"Lyndon Johnson",
"John F. Kennedy",
"Dwight Eisenhower",
"Harry Truman",
"Franklin Roosevelt"
];
term("Please enter your name: ");
() => {
const input = term.inputField({
history: history1,
autoComplete: autoComplete1,
autoCompleteMenu: true
}).promise;
term.green("\nYour name is '%s'\n", input);
};
const autoCompleter = function autoCompleter(
inputString: string,
callback: (err: any, input: string) => void
) {
fs.readdir(__dirname, (error, files) => {
callback(undefined, ac(files, inputString, true));
});
};
term("Choose a file: ");
term.inputField(
{ autoComplete: autoCompleter, autoCompleteMenu: true },
(error: any, input: any) => {
if (error) {
term.red.bold(`'\nAn error occurs: ' + ${error} + '\n'`);
} else {
term.green("\nYour file is '%s'\n", input);
}
}
);
const autoComplete2 = [
"dnf install",
"dnf install nodejs",
"dnf search",
"sudo",
"sudo dnf install",
"sudo dnf install nodejs",
"sudo dnf search"
];
term.inputField(
{
autoComplete: autoComplete2,
autoCompleteHint: true,
autoCompleteMenu: true,
tokenHook: (
token: any,
isEndOfInput: any,
previousTokens: any,
term: any,
config: any
) => {
const previousText = previousTokens.join(" ");
switch (token) {
case "sudo":
config.style = term.red;
return previousTokens.length ? null : term.bold.red;
case "dnf":
return previousText === "" || previousText === "sudo"
? term.brightMagenta
: null;
case "install":
config.style = term.brightBlue;
config.hintStyle = term.brightBlack.italic;
return previousText === "dnf" || previousText === "sudo dnf"
? term.brightYellow
: null;
case "search":
config.style = term.brightBlue;
return previousText === "dnf" || previousText === "sudo dnf"
? term.brightCyan
: null;
default:
return;
}
}
},
(error: any, input: any) => {
term.green("\nYour command is: '%s'\n", input);
}
);
term("Choose a file: ");
term.fileInput({ baseDir: "../" }, (error: any, input: any) => {
if (error) {
term.red.bold(`'\nAn error occurs: ' + ${error} + '\n'`);
} else {
term.green("\nYour file is '%s'\n", input);
}
});
const items1 = [
"File",
"Edit",
"View",
"History",
"Bookmarks",
"Tools",
"Help"
];
const options = {
y: 1, // the menu will be on the top of the terminal
style: term.inverse,
selectedStyle: term.dim.blue.bgGreen
};
term.clear();
term.singleLineMenu(items1, options, (error: any, response: any) => {
term("\n").eraseLineAfter.green(
"#%s selected: %s (%s,%s)\n",
response.selectedIndex,
response.selectedText,
response.x,
response.y
);
});
term.cyan("The hall is spacious. Someone lighted few chandeliers.\n");
term.cyan("There are doorways south and west.\n");
const items2 = ["a. Go south", "b. Go west", "c. Go back to the street"];
term.singleColumnMenu(items2, (error: any, response: any) => {
term("\n").eraseLineAfter.green(
"#%s selected: %s (%s,%s)\n",
response.selectedIndex,
response.selectedText,
response.x,
response.y
);
});
term.cyan("Choose a file:\n");
const items = fs.readdirSync(process.cwd());
term.gridMenu(items, (error: any, response: any) => {
term("\n").eraseLineAfter.green(
"#%s selected: %s (%s,%s)\n",
response.selectedIndex,
response.selectedText,
response.x,
response.y
);
});
let progressBar: Terminal.ProgressBarController;
let progress = 0;
function doProgress() {
// Add random progress
progress += Math.random() / 10;
progressBar.update(progress);
if (progress >= 1) {
// Cleanup and exit
setTimeout(() => {
term("\n");
}, 200);
} else {
setTimeout(doProgress, 100 + Math.random() * 400);
}
}
progressBar = term.progressBar({
width: 80,
title: "Serious stuff in progress:",
eta: true,
percent: true
});
doProgress();
const thingsToDo = [
"update my lib",
"data analyzing",
"serious business",
"decrunching data",
"do my laundry",
"optimizing"
];
let countDown = thingsToDo.length;
function start() {
const task = thingsToDo.shift();
if (!task) {
return;
}
progressBar.startItem(task);
// Finish the task in...
setTimeout(done.bind(null, task), 500 + Math.random() * 1200);
// Start another parallel task in...
setTimeout(start, 400 + Math.random() * 400);
}
function done(task: string) {
progressBar.itemDone(task);
countDown--;
// Cleanup and exit
if (!countDown) {
setTimeout(() => {
term("\n");
}, 200);
}
}
progressBar = term.progressBar({
width: 80,
title: "Daily tasks:",
eta: true,
percent: true,
items: thingsToDo.length
});
start();
term.slowTyping(
"What a wonderful world!\n",
{ flashStyle: term.brightWhite },
() => {}
);
// low level
term("My name is ")
.red("Jack")(" and I'm ")
.green("32\n");
term("My name is ^rJack^ and I'm ^g32\n");
getDetectedTerminal((error: any, term: any) => {
term.cyan("Terminal name: %s\n", term.appName);
term.cyan("Terminal app: %s\n", term.app);
term.cyan("Terminal generic: %s\n", term.generic);
term.cyan("Config file: %s\n", term.termconfigFile);
});
const screen = new ScreenBufferHD({ dst: term, noFill: true });
screen.fill({
attr: {
// Both foreground and background must have the same color
r: 40,
g: 20,
b: 0,
bgR: 40,
bgG: 20,
bgB: 0
}
});
const path_to_image = "/home/imoti/Downloads/photo_2019-01-24_13-15-50.jpg";
ScreenBufferHD.loadImage(
path_to_image,
{ shrink: { width: term.width, height: term.height * 2 } },
(error: any, image: any) => {
if (error) {
throw error;
} // Doh!
image.draw({ dst: screen, blending: true });
screen.draw();
}
);
const screen1 = new ScreenBuffer({ dst: term, noFill: true });
screen1.fill({
attr: {
// Both foreground and background must have the same color
color: 0,
bgColor: 0
}
});
ScreenBuffer.loadImage(
path_to_image,
{ terminal: term, shrink: { width: term.width, height: term.height * 2 } },
(error: any, image: any) => {
if (error) {
throw error;
} // Doh!
image.draw({ dst: screen, blending: true });
screen.draw();
}
);

View File

@@ -0,0 +1,17 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": ["es2017"],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"esModuleInterop": true,
"baseUrl": "../",
"typeRoots": ["../"],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true,
"strictFunctionTypes": false
},
"files": ["index.d.ts", "terminal-kit-tests.ts"]
}

View File

@@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }