From 2f60c241ee0b46097fd8e915211dca14ea6f9d7c Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 18 Aug 2017 16:51:40 -0700 Subject: [PATCH 01/17] Use manual typings over automatically generated ones These are pulled from the typings I wrote for vscode Fixes #898 --- package.json | 2 +- tsconfig.json | 3 +- typings/xterm.d.ts | 194 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 typings/xterm.d.ts diff --git a/package.json b/package.json index a5f0bd755..9b550d676 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ ".gitignore" ], "main": "lib/Terminal.js", - "types": "lib/Terminal.d.ts", + "types": "typings/xterm.d.ts", "repository": "https://github.com/sourcelair/xterm.js", "license": "MIT", "files": [ diff --git a/tsconfig.json b/tsconfig.json index a3aa790cf..38bfd2faf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,8 +5,7 @@ "rootDir": "src", "outDir": "lib", "sourceMap": true, - "removeComments": true, - "declaration": true + "removeComments": true }, "include": [ "src/**/*" diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts new file mode 100644 index 000000000..a64f132cd --- /dev/null +++ b/typings/xterm.d.ts @@ -0,0 +1,194 @@ +/** + * @license MIT + */ + +declare module 'xterm' { + type LinkMatcherHandler = (event: MouseEvent, uri: string) => boolean | void; + + export class Terminal { + cols: number; + rows: number; + ydisp: number; + element: HTMLElement; + textarea: HTMLTextAreaElement; + + /** + * Creates a new `Terminal` object. + * + * @param {object} options An object containing a set of options. + */ + constructor(options?: any); + + /** + * Registers an event listener. + * @param eventName The name of the event. + * @param callback The callback. + */ + on(eventName: string, callback: (data: any) => void): void; + + /** + * Resizes the terminal. + * + * @param x The number of columns to resize to. + * @param y The number of rows to resize to. + */ + resize(columns: number, rows: number): void; + + /** + * Emits an event. + * @param eventName The name of the event. + * @param data The data attached to the event. + */ + emit(eventName: string, data: any): void; + + /** + * Writes text to the terminal, followed by a break line character (\n). + * @param data The text to write to the terminal. + */ + writeln(data: string): void; + + /** + * Opens the terminal within an element. + * @param parent The element to create the terminal within. + * @param focus Focus the terminal, after it gets instantiated in the + * DOM. + */ + open(parent: HTMLElement, focus: boolean): void; + + /** + * Attaches a custom key event handler which is run before keys are + * processed, giving consumers of xterm.js ultimate control as to what + * keys should be processed by the terminal and what keys should not. + * @param customKeyEventHandler The custom KeyboardEvent handler to + * attach. This is a function that takes a KeyboardEvent, allowing + * consumers to stop propogation and/or prevent the default action. The + * function returns whether the event should be processed by xterm.js. + */ + attachCustomKeyEventHandler(customKeyEventHandler: (...any) => boolean); + + /** + * Retrieves an option's value from the terminal. + * @param key The option key. + */ + getOption(key: string): any; + + /** + * Registers a link matcher, allowing custom link patterns to be matched and + * handled. + * @param {RegExp} regex The regular expression to search for, specifically + * this searches the textContent of the rows. You will want to use \s to match + * a space ' ' character for example. + * @param {LinkMatcherHandler} handler The callback when the link is called. + * @param {LinkMatcherOptions} [options] Options for the link matcher. + * @return {number} The ID of the new matcher, this can be used to deregister. + */ + registerLinkMatcher(regex: RegExp, handler: LinkMatcherHandler , options?: any); + + /** + * Deregisters a link matcher if it has been registered. + * @param matcherId The link matcher's ID (returned after register) + */ + deregisterLinkMatcher(matcherId: number): void; + + /** + * Gets whether the terminal has an active selection. + */ + hasSelection(): boolean; + + /** + * Gets the terminal's current selection, this is useful for implementing copy + * behavior outside of xterm.js. + */ + getSelection(): string; + + /** + * Clears the current terminal selection. + */ + clearSelection(): void; + + /** + * Selects all text within the terminal. + */ + selectAll(): void; + + /** + * Focus the terminal. Delegates focus handling to the terminal's DOM element. + */ + focus(): void; + + /** + * Find the next instance of the term, then scroll to and select it. If it + * doesn't exist, do nothing. + * @param term Tne search term. + * @return Whether a result was found. + */ + findNext(term: string): boolean; + + /** + * Find the previous instance of the term, then scroll to and select it. If it + * doesn't exist, do nothing. + * @param term Tne search term. + * @return Whether a result was found. + */ + findPrevious(term: string): boolean; + + /** + * Destroys the terminal. + */ + destroy(): void; + + /** + * Scroll the display of the terminal + * @param disp The number of lines to scroll down (negatives scroll up). + */ + scrollDisp(disp: number): void; + + /** + * Scroll the display of the terminal by a number of pages. + * @param {number} pageCount The number of pages to scroll (negative scrolls up). + */ + scrollPages(pageCount: number): void; + + /** + * Scrolls the display of the terminal to the top. + */ + scrollToTop(): void; + + /** + * Scrolls the display of the terminal to the bottom. + */ + scrollToBottom(): void; + + /** + * Clears the entire buffer, making the prompt line the new first line. + */ + clear(): void; + + /** + * Writes text to the terminal. + * @param data The text to write to the terminal. + */ + write(data: string): void; + + /** + * Sets an option on the terminal. + * @param key The option key. + * @param value The option value. + */ + setOption(key: string, value: any): void; + + /** + * Tells the renderer to refresh terminal content between two rows (inclusive) at the next + * opportunity. + * @param start The row to start from (between 0 and this.rows - 1). + * @param end The row to end at (between start and this.rows - 1). + */ + refresh(start: number, end: number): void; + + /** + * Loads an addon, attaching it to the Terminal prototype. + * @param addon The addon to load. + */ + static loadAddon(addon: string): void; + } +} From 3ba3638ab7ae16c8eb8e6bf2dc1984f7cb155308 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 18 Aug 2017 17:25:40 -0700 Subject: [PATCH 02/17] Include all APIs from website --- src/Terminal.ts | 24 +-- typings/xterm.d.ts | 454 +++++++++++++++++++++++++++------------------ 2 files changed, 284 insertions(+), 194 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index 8edb406d0..96aced253 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -524,9 +524,10 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT }; /** - * Blur the terminal. Delegates blur handling to the terminal's DOM element. + * Blur the terminal, calling the blur function on the terminal's underlying + * textarea. */ - private blur(): void { + public blur(): void { return this.textarea.blur(); } @@ -1225,9 +1226,9 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT /** * Scroll the display of the terminal - * @param {number} disp The number of lines to scroll down (negatives scroll up). + * @param {number} disp The number of lines to scroll down (negative scroll up). * @param {boolean} suppressScrollEvent Don't emit the scroll event as scrollDisp. This is used - * to avoid unwanted events being handled by the veiwport when the event was triggered from the + * to avoid unwanted events being handled by the viewport when the event was triggered from the * viewport originally. */ public scrollDisp(disp: number, suppressScrollEvent?: boolean): void { @@ -1347,12 +1348,13 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT } /** - * Attaches a custom key event handler which is run before keys are processed, giving consumers of - * xterm.js ultimate control as to what keys should be processed by the terminal and what keys - * should not. - * @param {function} customKeyEventHandler The custom KeyboardEvent handler to attach. This is a - * function that takes a KeyboardEvent, allowing consumers to stop propogation and/or prevent - * the default action. The function returns whether the event should be processed by xterm.js. + * Attaches a custom key event handler which is run before keys are processed, + * giving consumers of xterm.js ultimate control as to what keys should be + * processed by the terminal and what keys should not. + * @param customKeyEventHandler The custom KeyboardEvent handler to attach. + * This is a function that takes a KeyboardEvent, allowing consumers to stop + * propogation and/or prevent the default action. The function returns whether + * the event should be processed by xterm.js. */ public attachCustomKeyEventHandler(customKeyEventHandler: CustomKeyEventHandler): void { this.customKeyEventHandler = customKeyEventHandler; @@ -2051,7 +2053,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT } /** - * Clears the entire buffer, making the prompt line the new first line. + * Clear the entire buffer, making the prompt line the new first line. */ public clear(): void { if (this.buffer.ybase === 0 && this.buffer.y === 0) { diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index a64f132cd..5e942ad59 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -1,194 +1,282 @@ /** * @license MIT + * + * This contains the type declarations for the xterm.js library. Note that + * some interfaces differ between this file and the actual implementation in + * src/, that's because this file declares the *public* API which is intended + * to be stable and consumed by external programs. */ -declare module 'xterm' { - type LinkMatcherHandler = (event: MouseEvent, uri: string) => boolean | void; +/** + * An object containing start up options for the terminal. + */ +interface ITerminalOptions { + /** + * The number of columns in the terminal. + */ + cols?: number; - export class Terminal { - cols: number; - rows: number; - ydisp: number; - element: HTMLElement; - textarea: HTMLTextAreaElement; + /** + * Whether the cursor blinks. + */ + cursorBlink?: boolean; - /** - * Creates a new `Terminal` object. - * - * @param {object} options An object containing a set of options. - */ - constructor(options?: any); + /** + * The style of the cursor. + */ + cursorStyle?: 'block' | 'underline' | 'bar'; - /** - * Registers an event listener. - * @param eventName The name of the event. - * @param callback The callback. - */ - on(eventName: string, callback: (data: any) => void): void; + /** + * Whether input should be disabled. + */ + disableStdin?: boolean; - /** - * Resizes the terminal. - * - * @param x The number of columns to resize to. - * @param y The number of rows to resize to. - */ - resize(columns: number, rows: number): void; + /** + * The number of rows in the terminal. + */ + rows?: number; - /** - * Emits an event. - * @param eventName The name of the event. - * @param data The data attached to the event. - */ - emit(eventName: string, data: any): void; + /** + * The amount of scrollback in the terminal. Scrollback is the amount of rows + * that are retained when lines are scrolled beyond the initial viewport. + */ + scrollback?: number; - /** - * Writes text to the terminal, followed by a break line character (\n). - * @param data The text to write to the terminal. - */ - writeln(data: string): void; - - /** - * Opens the terminal within an element. - * @param parent The element to create the terminal within. - * @param focus Focus the terminal, after it gets instantiated in the - * DOM. - */ - open(parent: HTMLElement, focus: boolean): void; - - /** - * Attaches a custom key event handler which is run before keys are - * processed, giving consumers of xterm.js ultimate control as to what - * keys should be processed by the terminal and what keys should not. - * @param customKeyEventHandler The custom KeyboardEvent handler to - * attach. This is a function that takes a KeyboardEvent, allowing - * consumers to stop propogation and/or prevent the default action. The - * function returns whether the event should be processed by xterm.js. - */ - attachCustomKeyEventHandler(customKeyEventHandler: (...any) => boolean); - - /** - * Retrieves an option's value from the terminal. - * @param key The option key. - */ - getOption(key: string): any; - - /** - * Registers a link matcher, allowing custom link patterns to be matched and - * handled. - * @param {RegExp} regex The regular expression to search for, specifically - * this searches the textContent of the rows. You will want to use \s to match - * a space ' ' character for example. - * @param {LinkMatcherHandler} handler The callback when the link is called. - * @param {LinkMatcherOptions} [options] Options for the link matcher. - * @return {number} The ID of the new matcher, this can be used to deregister. - */ - registerLinkMatcher(regex: RegExp, handler: LinkMatcherHandler , options?: any); - - /** - * Deregisters a link matcher if it has been registered. - * @param matcherId The link matcher's ID (returned after register) - */ - deregisterLinkMatcher(matcherId: number): void; - - /** - * Gets whether the terminal has an active selection. - */ - hasSelection(): boolean; - - /** - * Gets the terminal's current selection, this is useful for implementing copy - * behavior outside of xterm.js. - */ - getSelection(): string; - - /** - * Clears the current terminal selection. - */ - clearSelection(): void; - - /** - * Selects all text within the terminal. - */ - selectAll(): void; - - /** - * Focus the terminal. Delegates focus handling to the terminal's DOM element. - */ - focus(): void; - - /** - * Find the next instance of the term, then scroll to and select it. If it - * doesn't exist, do nothing. - * @param term Tne search term. - * @return Whether a result was found. - */ - findNext(term: string): boolean; - - /** - * Find the previous instance of the term, then scroll to and select it. If it - * doesn't exist, do nothing. - * @param term Tne search term. - * @return Whether a result was found. - */ - findPrevious(term: string): boolean; - - /** - * Destroys the terminal. - */ - destroy(): void; - - /** - * Scroll the display of the terminal - * @param disp The number of lines to scroll down (negatives scroll up). - */ - scrollDisp(disp: number): void; - - /** - * Scroll the display of the terminal by a number of pages. - * @param {number} pageCount The number of pages to scroll (negative scrolls up). - */ - scrollPages(pageCount: number): void; - - /** - * Scrolls the display of the terminal to the top. - */ - scrollToTop(): void; - - /** - * Scrolls the display of the terminal to the bottom. - */ - scrollToBottom(): void; - - /** - * Clears the entire buffer, making the prompt line the new first line. - */ - clear(): void; - - /** - * Writes text to the terminal. - * @param data The text to write to the terminal. - */ - write(data: string): void; - - /** - * Sets an option on the terminal. - * @param key The option key. - * @param value The option value. - */ - setOption(key: string, value: any): void; - - /** - * Tells the renderer to refresh terminal content between two rows (inclusive) at the next - * opportunity. - * @param start The row to start from (between 0 and this.rows - 1). - * @param end The row to end at (between start and this.rows - 1). - */ - refresh(start: number, end: number): void; - - /** - * Loads an addon, attaching it to the Terminal prototype. - * @param addon The addon to load. - */ - static loadAddon(addon: string): void; - } + /** + * The size of tab stops in the terminal. + */ + tabStopWidth?: number; +} + + +type Option = BooleanOption | StringOption | StringArrayOption | NumberOption | GeometryOption | HandlerOption; +type BooleanOption = + 'cancelEvents' | + 'convertEol' | + 'cursorBlink' | + 'debug' | + 'disableStdin' | + 'popOnBell' | + 'screenKeys' | + 'useFlowControl' | + 'visualBell'; +type StringOption = + 'cursorStyle' | + 'termName'; +type StringArrayOption = 'colors'; +type NumberOption = + 'cols' | + 'rows' | + 'tabStopWidth' | + 'scrollback'; +type GeometryOption = 'geometry'; +type HandlerOption = 'handler'; + +declare module 'xterm' { + /** + * The class that represents an xterm.js terminal. + */ + export class Terminal { + element: HTMLElement; + textarea: HTMLTextAreaElement; + + /** + * Creates a new `Terminal` object. + * + * @param options An object containing a set of options. + */ + constructor(options?: ITerminalOptions); + + /** + * Unfocus the terminal. + */ + blur(): void; + + /** + * Focus the terminal. + */ + focus(): void; + + /** + * Registers an event listener. + * @param type The type of the event. + * @param listener The listener. + */ + on(type: string, listener: (data: any) => void): void; + + /** + * Deregisters an event listener. + * @param type The type of the event. + * @param listener The listener. + */ + on(type: string, listener: (data: any) => void): void; + + /** + * Resizes the terminal. + * @param x The number of columns to resize to. + * @param y The number of rows to resize to. + */ + resize(columns: number, rows: number): void; + + /** + * Writes text to the terminal, followed by a break line character (\n). + * @param data The text to write to the terminal. + */ + writeln(data: string): void; + + /** + * Opens the terminal within an element. + * @param parent The element to create the terminal within. + */ + open(parent: HTMLElement): void; + + /** + * Attaches a custom key event handler which is run before keys are + * processed, giving consumers of xterm.js ultimate control as to what keys + * should be processed by the terminal and what keys should not. + * @param customKeyEventHandler The custom KeyboardEvent handler to attach. + * This is a function that takes a KeyboardEvent, allowing consumers to stop + * propogation and/or prevent the default action. The function returns + * whether the event should be processed by xterm.js. + */ + attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean); + + /** + * Retrieves an option's value from the terminal. + * @param key The option key. + */ + getOption(key: StringOption): string; + getOption(key: BooleanOption): boolean; + getOption(key: StringArrayOption): number[]; + getOption(key: NumberOption): number; + getOption(key: GeometryOption): [number, number]; + getOption(key: HandlerOption): (data: string) => void; + getOption(key: Option): any; + + // /** + // * Registers a link matcher, allowing custom link patterns to be matched and + // * handled. + // * @param {RegExp} regex The regular expression to search for, specifically + // * this searches the textContent of the rows. You will want to use \s to match + // * a space ' ' character for example. + // * @param {LinkMatcherHandler} handler The callback when the link is called. + // * @param {LinkMatcherOptions} [options] Options for the link matcher. + // * @return {number} The ID of the new matcher, this can be used to deregister. + // */ + // registerLinkMatcher(regex: RegExp, handler: LinkMatcherHandler , options?: any); + + // /** + // * Deregisters a link matcher if it has been registered. + // * @param matcherId The link matcher's ID (returned after register) + // */ + // deregisterLinkMatcher(matcherId: number): void; + + /** + * Gets whether the terminal has an active selection. + */ + hasSelection(): boolean; + + /** + * Gets the terminal's current selection, this is useful for implementing + * copy behavior outside of xterm.js. + */ + getSelection(): string; + + /** + * Clears the current terminal selection. + */ + clearSelection(): void; + + /** + * Selects all text within the terminal. + */ + selectAll(): void; + + // /** + // * Find the next instance of the term, then scroll to and select it. If it + // * doesn't exist, do nothing. + // * @param term Tne search term. + // * @return Whether a result was found. + // */ + // findNext(term: string): boolean; + + // /** + // * Find the previous instance of the term, then scroll to and select it. If it + // * doesn't exist, do nothing. + // * @param term Tne search term. + // * @return Whether a result was found. + // */ + // findPrevious(term: string): boolean; + + /** + * Destroys the terminal and detaches it from the DOM. + */ + destroy(): void; + + /** + * Scroll the display of the terminal + * @param amount The number of lines to scroll down (negative scroll up). + */ + scrollDisp(amount: number): void; + + /** + * Scroll the display of the terminal by a number of pages. + * @param pageCount The number of pages to scroll (negative scrolls up). + */ + scrollPages(pageCount: number): void; + + /** + * Scrolls the display of the terminal to the top. + */ + scrollToTop(): void; + + /** + * Scrolls the display of the terminal to the bottom. + */ + scrollToBottom(): void; + + /** + * Clear the entire buffer, making the prompt line the new first line. + */ + clear(): void; + + /** + * Writes text to the terminal. + * @param data The text to write to the terminal. + */ + write(data: string): void; + + /** + * Sets an option on the terminal. + * @param key The option key. + * @param value The option value. + */ + setOption(key: StringOption, value: string): void; + setOption(key: BooleanOption, value: boolean): void; + setOption(key: StringArrayOption, value: number[]): void; + setOption(key: NumberOption, value: number): void; + setOption(key: GeometryOption, value: [number, number]): void; + setOption(key: HandlerOption, value: (data: string) => void): void; + setOption(key: Option, value: any): void; + + /** + * Tells the renderer to refresh terminal content between two rows + * (inclusive) at the next opportunity. + * @param start The row to start from (between 0 and this.rows - 1). + * @param end The row to end at (between start and this.rows - 1). + */ + refresh(start: number, end: number): void; + + /** + * Perform a full reset (RIS, aka '\x1bc'). + */ + reset(): void + + /** + * Loads an addon, attaching it to the Terminal prototype and making it + * available to all newly created Terminals. + * @param addon The addon to load. + */ + static loadAddon(addon: string): void; + } } From 92ac427d00a87d563d03993482ebcad1ab6128af Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 18 Aug 2017 17:34:10 -0700 Subject: [PATCH 03/17] Type addon strings in loadAddon --- typings/xterm.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 5e942ad59..98312875a 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -277,6 +277,6 @@ declare module 'xterm' { * available to all newly created Terminals. * @param addon The addon to load. */ - static loadAddon(addon: string): void; + static loadAddon(addon: 'attach' | 'fit' | 'fullscreen' | 'search' | 'terminado'): void; } } From e4e2fbf88562f1ffd309002f59ef348fbf2792c2 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 18 Aug 2017 17:46:49 -0700 Subject: [PATCH 04/17] Add overloads for Terminal.on --- typings/xterm.d.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 98312875a..268d95d1c 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -109,6 +109,14 @@ declare module 'xterm' { * @param type The type of the event. * @param listener The listener. */ + on(type: 'blur' | 'focus' | 'lineFeed' | 'open', listener: () => void): void; + on(type: 'data', listener: (data: string) => void): void; + on(type: 'key', listener: (key: string, event: KeyboardEvent) => void): void; + on(type: 'keypress' | 'keydown', listener: (event: KeyboardEvent) => void): void; + on(type: 'refresh', listener: (data: {element: HTMLElement, start: number, end: number}) => void): void; + on(type: 'resize', listener: (data: {terminal: Terminal, cols: number, rows: number}) => void): void; + on(type: 'scroll', listener: (ydisp: number) => void): void; + on(type: 'title', listener: (title: string) => void): void; on(type: string, listener: (data: any) => void): void; /** From cd29c83a64c8111032d4b79b757d653745a1a0e3 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 19 Aug 2017 09:18:44 -0700 Subject: [PATCH 05/17] Improve overloaded function typings/comments --- typings/xterm.d.ts | 159 ++++++++++++++++++++++++++++++--------------- 1 file changed, 106 insertions(+), 53 deletions(-) diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 268d95d1c..89762d146 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -48,30 +48,6 @@ interface ITerminalOptions { tabStopWidth?: number; } - -type Option = BooleanOption | StringOption | StringArrayOption | NumberOption | GeometryOption | HandlerOption; -type BooleanOption = - 'cancelEvents' | - 'convertEol' | - 'cursorBlink' | - 'debug' | - 'disableStdin' | - 'popOnBell' | - 'screenKeys' | - 'useFlowControl' | - 'visualBell'; -type StringOption = - 'cursorStyle' | - 'termName'; -type StringArrayOption = 'colors'; -type NumberOption = - 'cols' | - 'rows' | - 'tabStopWidth' | - 'scrollback'; -type GeometryOption = 'geometry'; -type HandlerOption = 'handler'; - declare module 'xterm' { /** * The class that represents an xterm.js terminal. @@ -102,22 +78,56 @@ declare module 'xterm' { * @param type The type of the event. * @param listener The listener. */ - on(type: string, listener: (data: any) => void): void; + on(type: 'blur' | 'focus' | 'lineFeed' | 'open', listener: () => void): void; + /** + * Registers an event listener. + * @param type The type of the event. + * @param listener The listener. + */ + on(type: 'data', listener: (data?: string) => void): void; + /** + * Registers an event listener. + * @param type The type of the event. + * @param listener The listener. + */ + on(type: 'key', listener: (key?: string, event?: KeyboardEvent) => void): void; + /** + * Registers an event listener. + * @param type The type of the event. + * @param listener The listener. + */ + on(type: 'keypress' | 'keydown', listener: (event?: KeyboardEvent) => void): void; + /** + * Registers an event listener. + * @param type The type of the event. + * @param listener The listener. + */ + on(type: 'refresh', listener: (data?: {element: HTMLElement, start: number, end: number}) => void): void; + /** + * Registers an event listener. + * @param type The type of the event. + * @param listener The listener. + */ + on(type: 'resize', listener: (data?: {terminal: Terminal, cols: number, rows: number}) => void): void; + /** + * Registers an event listener. + * @param type The type of the event. + * @param listener The listener. + */ + on(type: 'scroll', listener: (ydisp?: number) => void): void; + /** + * Registers an event listener. + * @param type The type of the event. + * @param listener The listener. + */ + on(type: 'title', listener: (title?: string) => void): void; /** * Deregisters an event listener. * @param type The type of the event. * @param listener The listener. */ - on(type: 'blur' | 'focus' | 'lineFeed' | 'open', listener: () => void): void; - on(type: 'data', listener: (data: string) => void): void; - on(type: 'key', listener: (key: string, event: KeyboardEvent) => void): void; - on(type: 'keypress' | 'keydown', listener: (event: KeyboardEvent) => void): void; - on(type: 'refresh', listener: (data: {element: HTMLElement, start: number, end: number}) => void): void; - on(type: 'resize', listener: (data: {terminal: Terminal, cols: number, rows: number}) => void): void; - on(type: 'scroll', listener: (ydisp: number) => void): void; - on(type: 'title', listener: (title: string) => void): void; - on(type: string, listener: (data: any) => void): void; + off(type: 'blur' | 'focus' | 'lineFeed' | 'open' | 'data' | 'key' | 'keypress' | 'keydown' | 'refresh' | 'resize' | 'scroll' | 'title', listener: (...args: any[]) => void): void; /** * Resizes the terminal. @@ -149,18 +159,6 @@ declare module 'xterm' { */ attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean); - /** - * Retrieves an option's value from the terminal. - * @param key The option key. - */ - getOption(key: StringOption): string; - getOption(key: BooleanOption): boolean; - getOption(key: StringArrayOption): number[]; - getOption(key: NumberOption): number; - getOption(key: GeometryOption): [number, number]; - getOption(key: HandlerOption): (data: string) => void; - getOption(key: Option): any; - // /** // * Registers a link matcher, allowing custom link patterns to be matched and // * handled. @@ -254,18 +252,73 @@ declare module 'xterm' { */ write(data: string): void; + /** + * Retrieves an option's value from the terminal. + * @param key The option key. + */ + getOption(key: 'cursorStyle' | 'termName'): string; + /** + * Retrieves an option's value from the terminal. + * @param key The option key. + */ + getOption(key: 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell'): boolean; + /** + * Retrieves an option's value from the terminal. + * @param key The option key. + */ + getOption(key: 'colors'): number[]; + /** + * Retrieves an option's value from the terminal. + * @param key The option key. + */ + getOption(key: 'cols' | 'rows' | 'tabStopWidth' | 'scrollback'): number; + /** + * Retrieves an option's value from the terminal. + * @param key The option key. + */ + getOption(key: 'geometry'): [number, number]; + /** + * Retrieves an option's value from the terminal. + * @param key The option key. + */ + getOption(key: 'handler'): (data: string) => void; + /** * Sets an option on the terminal. * @param key The option key. * @param value The option value. */ - setOption(key: StringOption, value: string): void; - setOption(key: BooleanOption, value: boolean): void; - setOption(key: StringArrayOption, value: number[]): void; - setOption(key: NumberOption, value: number): void; - setOption(key: GeometryOption, value: [number, number]): void; - setOption(key: HandlerOption, value: (data: string) => void): void; - setOption(key: Option, value: any): void; + setOption(key: 'cursorStyle' | 'termName', value: string): void; + /** + * Sets an option on the terminal. + * @param key The option key. + * @param value The option value. + */ + setOption(key: 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell', value: boolean): void; + /** + * Sets an option on the terminal. + * @param key The option key. + * @param value The option value. + */ + setOption(key: 'colors', value: number[]): void; + /** + * Sets an option on the terminal. + * @param key The option key. + * @param value The option value. + */ + setOption(key: 'cols' | 'rows' | 'tabStopWidth' | 'scrollback', value: number): void; + /** + * Sets an option on the terminal. + * @param key The option key. + * @param value The option value. + */ + setOption(key: 'geometry', value: [number, number]): void; + /** + * Sets an option on the terminal. + * @param key The option key. + * @param value The option value. + */ + setOption(key: 'handler', value: (data: string) => void): void; /** * Tells the renderer to refresh terminal content between two rows From 4474f29ebf4084250f8a946067170dbe1d35ae86 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 19 Aug 2017 09:25:57 -0700 Subject: [PATCH 06/17] Add link matcher APIs --- src/Terminal.ts | 4 ++-- typings/xterm.d.ts | 56 +++++++++++++++++++++++++++++++++------------- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index 96aced253..10a1954b0 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -1397,10 +1397,10 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT * this searches the textContent of the rows. You will want to use \s to match * a space ' ' character for example. * @param handler The callback when the link is called. - * @param [options] Options for the link matcher. + * @param options Options for the link matcher. * @return The ID of the new matcher, this can be used to deregister. */ - public registerLinkMatcher(regex: RegExp, handler: LinkMatcherHandler, options: ILinkMatcherOptions): number { + public registerLinkMatcher(regex: RegExp, handler: LinkMatcherHandler, options?: ILinkMatcherOptions): number { if (this.linkifier) { const matcherId = this.linkifier.registerLinkMatcher(regex, handler, options); this.refresh(0, this.rows - 1); diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 89762d146..152c2cd9b 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -48,6 +48,30 @@ interface ITerminalOptions { tabStopWidth?: number; } +/** + * An object containing options for a link matcher. + */ +interface ILinkMatcherOptions { + /** + * The index of the link from the regex.match(text) call. This defaults to 0 + * (for regular expressions without capture groups). + */ + matchIndex?: number; + + /** + * A callback that validates an individual link, returning true if valid and + * false if invalid. + */ + validationCallback?: (uri: string, element: HTMLElement, callback: (isValid: boolean) => void) => void; + + /** + * The priority of the link matcher, this defines the order in which the link + * matcher is evaluated relative to others, from highest to lowest. The + * default value is 0. + */ + priority?: number; +} + declare module 'xterm' { /** * The class that represents an xterm.js terminal. @@ -159,23 +183,23 @@ declare module 'xterm' { */ attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean); - // /** - // * Registers a link matcher, allowing custom link patterns to be matched and - // * handled. - // * @param {RegExp} regex The regular expression to search for, specifically - // * this searches the textContent of the rows. You will want to use \s to match - // * a space ' ' character for example. - // * @param {LinkMatcherHandler} handler The callback when the link is called. - // * @param {LinkMatcherOptions} [options] Options for the link matcher. - // * @return {number} The ID of the new matcher, this can be used to deregister. - // */ - // registerLinkMatcher(regex: RegExp, handler: LinkMatcherHandler , options?: any); + /** + * (EXPERIMENTAL) Registers a link matcher, allowing custom link patterns to + * be matched and handled. + * @param regex The regular expression to search for, specifically this + * searches the textContent of the rows. You will want to use \s to match a + * space ' ' character for example. + * @param handler The callback when the link is called. + * @param options Options for the link matcher. + * @return The ID of the new matcher, this can be used to deregister. + */ + registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => boolean | void , options?: any); - // /** - // * Deregisters a link matcher if it has been registered. - // * @param matcherId The link matcher's ID (returned after register) - // */ - // deregisterLinkMatcher(matcherId: number): void; + /** + * (EXPERIMENTAL) Deregisters a link matcher if it has been registered. + * @param matcherId The link matcher's ID (returned after register) + */ + deregisterLinkMatcher(matcherId: number): void; /** * Gets whether the terminal has an active selection. From fd8b62610f98b59a53e277f875fcb63014497ee7 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 19 Aug 2017 09:49:37 -0700 Subject: [PATCH 07/17] Add typings test setup --- .gitignore | 1 + fixtures/typings-test/tsconfig.json | 9 +++++++++ fixtures/typings-test/typing-tests.ts | 23 +++++++++++++++++++++++ src/Terminal.integration.ts | 11 +++++++++++ typings/xterm.d.ts | 24 ++++++++++++------------ 5 files changed, 56 insertions(+), 12 deletions(-) create mode 100644 fixtures/typings-test/tsconfig.json create mode 100644 fixtures/typings-test/typing-tests.ts diff --git a/.gitignore b/.gitignore index f98114933..8e28c797f 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ npm-debug.log build/ .vscode/ .DS_Store +fixtures/typings-test/*.js # Directories needed for code coverage /coverage/ diff --git a/fixtures/typings-test/tsconfig.json b/fixtures/typings-test/tsconfig.json new file mode 100644 index 000000000..2f78a6d06 --- /dev/null +++ b/fixtures/typings-test/tsconfig.json @@ -0,0 +1,9 @@ +{ + "files": [ + "typing-tests.ts" + ], + "compilerOptions": { + "module": "commonjs", + "target": "es5" + } +} diff --git a/fixtures/typings-test/typing-tests.ts b/fixtures/typings-test/typing-tests.ts new file mode 100644 index 000000000..dd686d914 --- /dev/null +++ b/fixtures/typings-test/typing-tests.ts @@ -0,0 +1,23 @@ +/// + +import { Terminal } from 'xterm'; + +namespace constructor_tests { + { + new Terminal(); + new Terminal({}); + new Terminal({ + cols: 1, + rows: 1 + }); + new Terminal({ + 'cols': 1, + 'cursorBlink': true, + 'cursorStyle': 'block', + 'disableStdin': false, + 'rows': 1, + 'scrollback': 10, + 'tabStopWidth': 2, + }); + } +} diff --git a/src/Terminal.integration.ts b/src/Terminal.integration.ts index 2155d0e0b..d5c014d81 100644 --- a/src/Terminal.integration.ts +++ b/src/Terminal.integration.ts @@ -4,11 +4,13 @@ * This file contains integration tests for xterm.js. */ +import * as cp from 'child_process'; import * as glob from 'glob'; import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; import * as pty from 'node-pty'; +import { assert } from 'chai'; import { Terminal } from './Terminal'; import { CHAR_DATA_CHAR_INDEX } from './Buffer'; @@ -143,3 +145,12 @@ if (os.platform() !== 'win32') { } }); } + +describe('typings', () => { + it('should throw no compile errors', () => { + let result = cp.spawnSync(path.join(__dirname, '..', 'node_modules', '.bin', 'tsc'), { + cwd: path.join(__dirname, '..', 'fixtures', 'typings-test') + }); + assert.equal(result.status, 0, `build did not succeed:\nstdout: ${result.stdout.toString()}\nstderr: ${result.stderr.toString()}\n`); + }); +}); diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 152c2cd9b..b503ec2da 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -181,19 +181,19 @@ declare module 'xterm' { * propogation and/or prevent the default action. The function returns * whether the event should be processed by xterm.js. */ - attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean); + attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void; - /** - * (EXPERIMENTAL) Registers a link matcher, allowing custom link patterns to - * be matched and handled. - * @param regex The regular expression to search for, specifically this - * searches the textContent of the rows. You will want to use \s to match a - * space ' ' character for example. - * @param handler The callback when the link is called. - * @param options Options for the link matcher. - * @return The ID of the new matcher, this can be used to deregister. - */ - registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => boolean | void , options?: any); + /** + * (EXPERIMENTAL) Registers a link matcher, allowing custom link patterns to + * be matched and handled. + * @param regex The regular expression to search for, specifically this + * searches the textContent of the rows. You will want to use \s to match a + * space ' ' character for example. + * @param handler The callback when the link is called. + * @param options Options for the link matcher. + * @return The ID of the new matcher, this can be used to deregister. + */ + registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => boolean | void , options?: any): number; /** * (EXPERIMENTAL) Deregisters a link matcher if it has been registered. From 6e2ca0af1255ed158d8a9bb4fc8a10f820b5fc31 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 19 Aug 2017 10:17:47 -0700 Subject: [PATCH 08/17] Fill out typings tests --- fixtures/typings-test/typing-tests.ts | 187 +++++++++++++++++++++++++- src/Terminal.integration.ts | 3 +- src/Terminal.ts | 2 +- typings/xterm.d.ts | 6 +- 4 files changed, 192 insertions(+), 6 deletions(-) diff --git a/fixtures/typings-test/typing-tests.ts b/fixtures/typings-test/typing-tests.ts index dd686d914..43ca18bc5 100644 --- a/fixtures/typings-test/typing-tests.ts +++ b/fixtures/typings-test/typing-tests.ts @@ -2,7 +2,7 @@ import { Terminal } from 'xterm'; -namespace constructor_tests { +namespace constructor { { new Terminal(); new Terminal({}); @@ -21,3 +21,188 @@ namespace constructor_tests { }); } } + +namespace properties { + { + const t: Terminal = new Terminal(); + const element: HTMLElement = t.element; + const textarea: HTMLTextAreaElement = t.textarea; + } +} + +namespace static_methods { + { + Terminal.loadAddon('attach'); + Terminal.loadAddon('fit'); + Terminal.loadAddon('fullscreen'); + Terminal.loadAddon('search'); + Terminal.loadAddon('terminado'); + } +} + +namespace methods_core { + { + const t: Terminal = new Terminal(); + t.blur(); + t.focus(); + t.destroy(); + t.clear(); + t.refresh(0, 1); + t.reset(); + t.resize(1, 1); + t.write('foo'); + t.writeln('foo'); + } + { + const t: Terminal = new Terminal(); + // no arg + t.on('blur', () => {}); + t.on('focus', () => {}); + t.on('lineFeed', () => {}); + t.on('open', () => {}); + // args + t.on('data', () => {}); + t.on('data', (data: string) => console.log(data)); + t.on('key', () => {}); + t.on('key', (key: string) => console.log(key, event)); + t.on('key', (key: string, event: KeyboardEvent) => console.log(key, event)); + t.on('keydown', () => {}); + t.on('keydown', (event: KeyboardEvent) => console.log(event)); + t.on('keypress', () => {}); + t.on('keypress', (event: KeyboardEvent) => console.log(event)); + t.on('refresh', () => {}); + t.on('refresh', (data: {element: HTMLElement, start: number, end: number}) => console.log(data)); + t.on('resize', () => {}); + t.on('resize', (data: {terminal: Terminal, cols: number, rows: number}) => console.log(data)); + t.on('scroll', () => {}); + t.on('scroll', (ydisp: number) => console.log(ydisp)); + t.on('title', () => {}); + t.on('title', (title: string) => console.log(title)); + } + { + const t: Terminal = new Terminal(); + // no arg + t.off('blur', () => {}); + t.off('focus', () => {}); + t.off('lineFeed', () => {}); + t.off('open', () => {}); + // args + t.off('data', () => {}); + t.off('data', (data: string) => console.log(data)); + t.off('key', () => {}); + t.off('key', (key: string) => console.log(key, event)); + t.off('key', (key: string, event: KeyboardEvent) => console.log(key, event)); + t.off('keydown', () => {}); + t.off('keydown', (event: KeyboardEvent) => console.log(event)); + t.off('keypress', () => {}); + t.off('keypress', (event: KeyboardEvent) => console.log(event)); + t.off('refresh', () => {}); + t.off('refresh', (data: {element: HTMLElement, start: number, end: number}) => console.log(data)); + t.off('resize', () => {}); + t.off('resize', (data: {terminal: Terminal, cols: number, rows: number}) => console.log(data)); + t.off('scroll', () => {}); + t.off('scroll', (ydisp: number) => console.log(ydisp)); + t.off('title', () => {}); + t.off('title', (title: string) => console.log(title)); + } + { + const t: Terminal = new Terminal(); + const e: HTMLElement = null; + t.open(e); + } + { + const t: Terminal = new Terminal(); + t.attachCustomKeyEventHandler((e: KeyboardEvent) => true); + t.attachCustomKeyEventHandler((e: KeyboardEvent) => false); + } + namespace options { + { + const t: Terminal = new Terminal(); + const r01: string = t.getOption('cursorStyle'); + const r02: string = t.getOption('termName'); + const r03: boolean = t.getOption('cancelEvents'); + const r04: boolean = t.getOption('convertEol'); + const r05: boolean = t.getOption('cursorBlink'); + const r06: boolean = t.getOption('debug'); + const r07: boolean = t.getOption('disableStdin'); + const r08: boolean = t.getOption('popOnBell'); + const r09: boolean = t.getOption('screenKeys'); + const r10: boolean = t.getOption('useFlowControl'); + const r11: boolean = t.getOption('visualBell'); + const r12: string[] = t.getOption('colors'); + const r13: number = t.getOption('cols'); + const r14: number = t.getOption('rows'); + const r15: number = t.getOption('tabStopWidth'); + const r16: number = t.getOption('scrollback'); + const r17: [number, number] = t.getOption('geometry'); + const r18: (data: string) => void = t.getOption('handler'); + } + { + const t: Terminal = new Terminal(); + t.setOption('cursorStyle', 'foo'); + t.setOption('termName', 'foo'); + t.setOption('cancelEvents', true); + t.setOption('convertEol', true); + t.setOption('cursorBlink', true); + t.setOption('debug', true); + t.setOption('disableStdin', true); + t.setOption('popOnBell', true); + t.setOption('screenKeys', true); + t.setOption('useFlowControl', true); + t.setOption('visualBell', true); + t.setOption('colors', ['a', 'b']); + t.setOption('cols', 1); + t.setOption('rows', 1); + t.setOption('tabStopWidth', 1); + t.setOption('scrollback', 1); + t.setOption('geometry', [1, 1]); + t.setOption('handler', (data: string) => console.log(data)); + } + } + namespace scrolling { + { + const t: Terminal = new Terminal(); + t.scrollDisp(-1); + t.scrollDisp(1); + t.scrollDisp(-1); + t.scrollDisp(1); + t.scrollToTop(); + t.scrollToBottom(); + } + } + namespace selection { + { + const t: Terminal = new Terminal(); + const r1: boolean = t.hasSelection(); + const r2: string = t.getSelection(); + t.clearSelection(); + t.selectAll(); + } + } +} + +namespace methods_experimental { + { + const t: Terminal = new Terminal(); + t.registerLinkMatcher(/foo/, () => {}); + t.registerLinkMatcher(new RegExp('foo'), () => {}); + t.registerLinkMatcher(/foo/, () => {}, {}); + t.registerLinkMatcher(/foo/, (event: MouseEvent, uri: string) => { + console.log(event, uri); + return void 0; + }, {}); + t.registerLinkMatcher(/foo/, () => true, {}); + t.registerLinkMatcher(/foo/, () => false, {}); + t.registerLinkMatcher(/foo/, () => true, { + matchIndex: 1 + }); + t.registerLinkMatcher(/foo/, () => true, { + matchIndex: 1, + priority: 1, + validationCallback: (uri: string, element: HTMLElement, callback: (isValid: boolean) => void) => { + console.log(uri, element, callback); + } + }); + t.deregisterLinkMatcher(1); + } +} diff --git a/src/Terminal.integration.ts b/src/Terminal.integration.ts index d5c014d81..31d2ad5da 100644 --- a/src/Terminal.integration.ts +++ b/src/Terminal.integration.ts @@ -147,7 +147,8 @@ if (os.platform() !== 'win32') { } describe('typings', () => { - it('should throw no compile errors', () => { + it('should throw no compile errors', function () { + this.timeout(20000); let result = cp.spawnSync(path.join(__dirname, '..', 'node_modules', '.bin', 'tsc'), { cwd: path.join(__dirname, '..', 'fixtures', 'typings-test') }); diff --git a/src/Terminal.ts b/src/Terminal.ts index 10a1954b0..24808099f 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -414,7 +414,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT */ public getOption(key: StringOption): string; public getOption(key: BooleanOption): boolean; - public getOption(key: StringArrayOption): number[]; + public getOption(key: StringArrayOption): string[]; public getOption(key: NumberOption): number; public getOption(key: GeometryOption): [number, number]; public getOption(key: HandlerOption): (data: string) => void; diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index b503ec2da..6758b94fe 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -193,7 +193,7 @@ declare module 'xterm' { * @param options Options for the link matcher. * @return The ID of the new matcher, this can be used to deregister. */ - registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => boolean | void , options?: any): number; + registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => boolean | void , options?: ILinkMatcherOptions): number; /** * (EXPERIMENTAL) Deregisters a link matcher if it has been registered. @@ -290,7 +290,7 @@ declare module 'xterm' { * Retrieves an option's value from the terminal. * @param key The option key. */ - getOption(key: 'colors'): number[]; + getOption(key: 'colors'): string[]; /** * Retrieves an option's value from the terminal. * @param key The option key. @@ -324,7 +324,7 @@ declare module 'xterm' { * @param key The option key. * @param value The option value. */ - setOption(key: 'colors', value: number[]): void; + setOption(key: 'colors', value: string[]): void; /** * Sets an option on the terminal. * @param key The option key. From 380f950d4d48e9f8d747b7ef5c9d7e8400bfd97b Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 19 Aug 2017 10:22:46 -0700 Subject: [PATCH 09/17] Clean up --- fixtures/typings-test/tsconfig.json | 2 +- .../typings-test/{typing-tests.ts => typings-test.ts} | 0 src/Terminal.integration.ts | 10 ++++++---- 3 files changed, 7 insertions(+), 5 deletions(-) rename fixtures/typings-test/{typing-tests.ts => typings-test.ts} (100%) diff --git a/fixtures/typings-test/tsconfig.json b/fixtures/typings-test/tsconfig.json index 2f78a6d06..2dcff2ea1 100644 --- a/fixtures/typings-test/tsconfig.json +++ b/fixtures/typings-test/tsconfig.json @@ -1,6 +1,6 @@ { "files": [ - "typing-tests.ts" + "typings-test.ts" ], "compilerOptions": { "module": "commonjs", diff --git a/fixtures/typings-test/typing-tests.ts b/fixtures/typings-test/typings-test.ts similarity index 100% rename from fixtures/typings-test/typing-tests.ts rename to fixtures/typings-test/typings-test.ts diff --git a/src/Terminal.integration.ts b/src/Terminal.integration.ts index 31d2ad5da..7e4ed8704 100644 --- a/src/Terminal.integration.ts +++ b/src/Terminal.integration.ts @@ -147,11 +147,13 @@ if (os.platform() !== 'win32') { } describe('typings', () => { - it('should throw no compile errors', function () { + it('should throw no compile errors', function (): void { this.timeout(20000); - let result = cp.spawnSync(path.join(__dirname, '..', 'node_modules', '.bin', 'tsc'), { - cwd: path.join(__dirname, '..', 'fixtures', 'typings-test') - }); + const tsc = path.join(__dirname, '..', 'node_modules', '.bin', 'tsc'); + const fixtureDir = path.join(__dirname, '..', 'fixtures', 'typings-test'); + let result = cp.spawnSync(tsc, { cwd: fixtureDir }); assert.equal(result.status, 0, `build did not succeed:\nstdout: ${result.stdout.toString()}\nstderr: ${result.stderr.toString()}\n`); + // Clean up + fs.unlinkSync(path.join(fixtureDir, 'typings-test.js')); }); }); From 34f5b2cb8a9041b6cd6877367fe7a946b2224a1a Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 19 Aug 2017 10:29:05 -0700 Subject: [PATCH 10/17] Remove option overloads from src src/ handles more than that specified (and should incase you're not using TS), this also reduces duplication as the definitions are only in typings/ --- src/Terminal.ts | 18 +++--------------- src/Types.ts | 23 ----------------------- 2 files changed, 3 insertions(+), 38 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index 24808099f..32f9ea231 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -37,7 +37,7 @@ import * as Browser from './utils/Browser'; import * as Mouse from './utils/Mouse'; import { CHARSETS } from './Charsets'; import { getRawByteCoords } from './utils/Mouse'; -import { CustomKeyEventHandler, Charset, LinkMatcherHandler, LinkMatcherValidationCallback, CharData, LineData, Option, StringOption, BooleanOption, StringArrayOption, NumberOption, GeometryOption, HandlerOption } from './Types'; +import { CustomKeyEventHandler, Charset, LinkMatcherHandler, LinkMatcherValidationCallback, CharData, LineData } from './Types'; import { ITerminal, IBrowser, ITerminalOptions, IInputHandlingTerminal, ILinkMatcherOptions, IViewport, ICompositionHelper } from './Interfaces'; // Declare for RequireJS in loadAddon @@ -412,13 +412,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT * Retrieves an option's value from the terminal. * @param {string} key The option key. */ - public getOption(key: StringOption): string; - public getOption(key: BooleanOption): boolean; - public getOption(key: StringArrayOption): string[]; - public getOption(key: NumberOption): number; - public getOption(key: GeometryOption): [number, number]; - public getOption(key: HandlerOption): (data: string) => void; - public getOption(key: Option): any { + public getOption(key: string): any { if (!(key in DEFAULT_OPTIONS)) { throw new Error('No option with key "' + key + '"'); } @@ -435,13 +429,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT * @param {string} key The option key. * @param {any} value The option value. */ - public setOption(key: StringOption, value: string): void; - public setOption(key: BooleanOption, value: boolean): void; - public setOption(key: StringArrayOption, value: number[]): void; - public setOption(key: NumberOption, value: number): void; - public setOption(key: GeometryOption, value: [number, number]): void; - public setOption(key: HandlerOption, value: (data: string) => void): void; - public setOption(key: Option, value: any): void { + public setOption(key: string, value: any): void { if (!(key in DEFAULT_OPTIONS)) { throw new Error('No option with key "' + key + '"'); } diff --git a/src/Types.ts b/src/Types.ts index 0de78d526..0753d80e1 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -18,26 +18,3 @@ export type Charset = {[key: string]: string}; export type CharData = [number, string, number]; export type LineData = CharData[]; - -export type Option = BooleanOption | StringOption | StringArrayOption | NumberOption | GeometryOption | HandlerOption; -export type BooleanOption = - 'cancelEvents' | - 'convertEol' | - 'cursorBlink' | - 'debug' | - 'disableStdin' | - 'popOnBell' | - 'screenKeys' | - 'useFlowControl' | - 'visualBell'; -export type StringOption = - 'cursorStyle' | - 'termName'; -export type StringArrayOption = 'colors'; -export type NumberOption = - 'cols' | - 'rows' | - 'tabStopWidth' | - 'scrollback'; -export type GeometryOption = 'geometry'; -export type HandlerOption = 'handler'; From 34e1ee2bf60a540e3721fa7a64346ccabead7dae Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 19 Aug 2017 13:20:32 -0700 Subject: [PATCH 11/17] Fix typings test on Windows --- src/Terminal.integration.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Terminal.integration.ts b/src/Terminal.integration.ts index 7e4ed8704..124e89cb8 100644 --- a/src/Terminal.integration.ts +++ b/src/Terminal.integration.ts @@ -149,7 +149,10 @@ if (os.platform() !== 'win32') { describe('typings', () => { it('should throw no compile errors', function (): void { this.timeout(20000); - const tsc = path.join(__dirname, '..', 'node_modules', '.bin', 'tsc'); + let tsc = path.join(__dirname, '..', 'node_modules', '.bin', 'tsc'); + if (process.platform === 'win32') { + tsc += '.cmd'; + } const fixtureDir = path.join(__dirname, '..', 'fixtures', 'typings-test'); let result = cp.spawnSync(tsc, { cwd: fixtureDir }); assert.equal(result.status, 0, `build did not succeed:\nstdout: ${result.stdout.toString()}\nstderr: ${result.stderr.toString()}\n`); From fa015d91fed7aa427716391b4ec172cf764f8d67 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 19 Aug 2017 13:30:37 -0700 Subject: [PATCH 12/17] Improve types and add bellStyle/bellSound --- fixtures/typings-test/typings-test.ts | 7 +++++++ src/Terminal.ts | 2 +- typings/xterm.d.ts | 16 ++++++++++++++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/fixtures/typings-test/typings-test.ts b/fixtures/typings-test/typings-test.ts index 0e82f788f..e6fcd5a15 100644 --- a/fixtures/typings-test/typings-test.ts +++ b/fixtures/typings-test/typings-test.ts @@ -140,6 +140,8 @@ namespace methods_core { const r16: number = t.getOption('scrollback'); const r17: [number, number] = t.getOption('geometry'); const r18: (data: string) => void = t.getOption('handler'); + const r19: string = t.getOption('bellSound'); + const r20: string = t.getOption('bellStyle'); } { const t: Terminal = new Terminal(); @@ -161,6 +163,11 @@ namespace methods_core { t.setOption('scrollback', 1); t.setOption('geometry', [1, 1]); t.setOption('handler', (data: string) => console.log(data)); + t.setOption('bellSound', 'foo'); + t.setOption('bellStyle', 'none'); + t.setOption('bellStyle', 'visual'); + t.setOption('bellStyle', 'sound'); + t.setOption('bellStyle', 'both'); } } namespace scrolling { diff --git a/src/Terminal.ts b/src/Terminal.ts index ff42d1396..686cffd89 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -149,7 +149,7 @@ const DEFAULT_OPTIONS: ITerminalOptions = { cursorBlink: false, cursorStyle: 'block', bellSound: BellSound, - bellStyle: null, + bellStyle: 'none', scrollback: 1000, screenKeys: false, debug: false, diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index ee7d68d87..c8df78fc8 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -290,7 +290,7 @@ declare module 'xterm' { * Retrieves an option's value from the terminal. * @param key The option key. */ - getOption(key: 'cursorStyle' | 'termName'): string; + getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'termName'): string; /** * Retrieves an option's value from the terminal. * @param key The option key. @@ -322,7 +322,19 @@ declare module 'xterm' { * @param key The option key. * @param value The option value. */ - setOption(key: 'cursorStyle' | 'termName', value: string): void; + setOption(key: 'termName' | 'bellSound', value: string): void; + /** + * Sets an option on the terminal. + * @param key The option key. + * @param value The option value. + */ + setOption(key: 'bellStyle', value: 'none' | 'visual' | 'sound' | 'both'): void; + /** + * Sets an option on the terminal. + * @param key The option key. + * @param value The option value. + */ + setOption(key: 'cursorStyle', value: 'block' | 'underline' | 'bar'): void; /** * Sets an option on the terminal. * @param key The option key. From f520e27f40aaa344791df213028c0fca043582cd Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 19 Aug 2017 13:32:03 -0700 Subject: [PATCH 13/17] Fix tests --- fixtures/typings-test/typings-test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fixtures/typings-test/typings-test.ts b/fixtures/typings-test/typings-test.ts index e6fcd5a15..0770233a1 100644 --- a/fixtures/typings-test/typings-test.ts +++ b/fixtures/typings-test/typings-test.ts @@ -145,7 +145,9 @@ namespace methods_core { } { const t: Terminal = new Terminal(); - t.setOption('cursorStyle', 'foo'); + t.setOption('cursorStyle', 'bar'); + t.setOption('cursorStyle', 'block'); + t.setOption('cursorStyle', 'underline'); t.setOption('termName', 'foo'); t.setOption('cancelEvents', true); t.setOption('convertEol', true); From e848d6afbe24136073887abea218f296ddc871ce Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 19 Aug 2017 14:33:41 -0700 Subject: [PATCH 14/17] Remove open event Fixes #901 --- fixtures/typings-test/typings-test.ts | 2 -- src/Terminal.ts | 7 ------- typings/xterm.d.ts | 4 ++-- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/fixtures/typings-test/typings-test.ts b/fixtures/typings-test/typings-test.ts index 0770233a1..f99d6ea3f 100644 --- a/fixtures/typings-test/typings-test.ts +++ b/fixtures/typings-test/typings-test.ts @@ -63,7 +63,6 @@ namespace methods_core { t.on('blur', () => {}); t.on('focus', () => {}); t.on('lineFeed', () => {}); - t.on('open', () => {}); // args t.on('data', () => {}); t.on('data', (data: string) => console.log(data)); @@ -89,7 +88,6 @@ namespace methods_core { t.off('blur', () => {}); t.off('focus', () => {}); t.off('lineFeed', () => {}); - t.off('open', () => {}); // args t.off('data', () => {}); t.off('data', (data: string) => console.log(data)); diff --git a/src/Terminal.ts b/src/Terminal.ts index 686cffd89..42d3fc3fa 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -765,13 +765,6 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT // Listen for mouse events and translate // them into terminal mouse protocols. this.bindMouse(); - - /** - * This event is emitted when terminal has completed opening. - * - * @event open - */ - this.emit('open'); } /** diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index c8df78fc8..80cc14a81 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -112,7 +112,7 @@ declare module 'xterm' { * @param type The type of the event. * @param listener The listener. */ - on(type: 'blur' | 'focus' | 'lineFeed' | 'open', listener: () => void): void; + on(type: 'blur' | 'focus' | 'lineFeed', listener: () => void): void; /** * Registers an event listener. * @param type The type of the event. @@ -161,7 +161,7 @@ declare module 'xterm' { * @param type The type of the event. * @param listener The listener. */ - off(type: 'blur' | 'focus' | 'lineFeed' | 'open' | 'data' | 'key' | 'keypress' | 'keydown' | 'refresh' | 'resize' | 'scroll' | 'title', listener: (...args: any[]) => void): void; + off(type: 'blur' | 'focus' | 'lineFeed' | 'data' | 'key' | 'keypress' | 'keydown' | 'refresh' | 'resize' | 'scroll' | 'title', listener: (...args: any[]) => void): void; /** * Resizes the terminal. From 8fdedd4da1cd3ce3bcebcdf7ea44b38da778b976 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 19 Aug 2017 14:38:54 -0700 Subject: [PATCH 15/17] Slim down refresh and resize events Fixes #903 --- fixtures/typings-test/typings-test.ts | 4 ++-- src/Renderer.ts | 2 +- src/Terminal.ts | 2 +- typings/xterm.d.ts | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fixtures/typings-test/typings-test.ts b/fixtures/typings-test/typings-test.ts index f99d6ea3f..ffe6afd49 100644 --- a/fixtures/typings-test/typings-test.ts +++ b/fixtures/typings-test/typings-test.ts @@ -74,9 +74,9 @@ namespace methods_core { t.on('keypress', () => {}); t.on('keypress', (event: KeyboardEvent) => console.log(event)); t.on('refresh', () => {}); - t.on('refresh', (data: {element: HTMLElement, start: number, end: number}) => console.log(data)); + t.on('refresh', (data: {start: number, end: number}) => console.log(data)); t.on('resize', () => {}); - t.on('resize', (data: {terminal: Terminal, cols: number, rows: number}) => console.log(data)); + t.on('resize', (data: {cols: number, rows: number}) => console.log(data)); t.on('scroll', () => {}); t.on('scroll', (ydisp: number) => console.log(ydisp)); t.on('title', () => {}); diff --git a/src/Renderer.ts b/src/Renderer.ts index f2999afaf..b51a9ff93 100644 --- a/src/Renderer.ts +++ b/src/Renderer.ts @@ -320,7 +320,7 @@ export class Renderer { this._terminal.element.appendChild(this._terminal.rowContainer); } - this._terminal.emit('refresh', {element: this._terminal.element, start: start, end: end}); + this._terminal.emit('refresh', {start, end}); }; /** diff --git a/src/Terminal.ts b/src/Terminal.ts index 42d3fc3fa..90a7a6fab 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -1944,7 +1944,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.refresh(0, this.rows - 1); this.geometry = [this.cols, this.rows]; - this.emit('resize', {terminal: this, cols: x, rows: y}); + this.emit('resize', {cols: x, rows: y}); } /** diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 80cc14a81..3172f3b34 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -136,13 +136,13 @@ declare module 'xterm' { * @param type The type of the event. * @param listener The listener. */ - on(type: 'refresh', listener: (data?: {element: HTMLElement, start: number, end: number}) => void): void; + on(type: 'refresh', listener: (data?: {start: number, end: number}) => void): void; /** * Registers an event listener. * @param type The type of the event. * @param listener The listener. */ - on(type: 'resize', listener: (data?: {terminal: Terminal, cols: number, rows: number}) => void): void; + on(type: 'resize', listener: (data?: {cols: number, rows: number}) => void): void; /** * Registers an event listener. * @param type The type of the event. From c984013e1efc86b74035bafc0d668c585ce4fa22 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 19 Aug 2017 14:52:48 -0700 Subject: [PATCH 16/17] Remove terminal from other events --- src/Terminal.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index 90a7a6fab..4c6ba9163 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -511,7 +511,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.showCursor(); this.restartCursorBlinking.apply(this); // TODO: Why pass terminal here? - this.emit('focus', {terminal: this}); + this.emit('focus'); }); }; @@ -535,7 +535,7 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.element.classList.remove('focus'); this.clearCursorBlinkingInterval.apply(this); // TODO: Why pass terminal here? - this.emit('blur', {terminal: this}); + this.emit('blur'); }); } @@ -710,14 +710,8 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.textarea.setAttribute('autocapitalize', 'off'); this.textarea.setAttribute('spellcheck', 'false'); this.textarea.tabIndex = 0; - this.textarea.addEventListener('focus', () => { - // TODO: Do we need terminal passed here? - this.emit('focus', {terminal: this}); - }); - this.textarea.addEventListener('blur', () => { - // TODO: Do we need terminal passed here? - this.emit('blur', {terminal: this}); - }); + this.textarea.addEventListener('focus', () => this.emit('focus')); + this.textarea.addEventListener('blur', () => this.emit('blur')); this.helperContainer.appendChild(this.textarea); this.compositionView = document.createElement('div'); From eda9443b1a48e25af1f7dab011b7d363f12abec9 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 20 Aug 2017 10:29:48 -0700 Subject: [PATCH 17/17] Allow null with cursorStyle and bellStyle --- src/Terminal.ts | 10 ++++++++++ typings/xterm.d.ts | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index 879bfbab1..a17cf94a9 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -437,6 +437,16 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT throw new Error('No option with key "' + key + '"'); } switch (key) { + case 'bellStyle': + if (!value) { + value = 'none'; + } + break; + case 'cursorStyle': + if (!value) { + value = 'block'; + } + break; case 'tabStopWidth': if (value < 1) { console.warn(`tabStopWidth cannot be less than 1, value: ${value}`); diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 3172f3b34..7ccd19435 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -328,13 +328,13 @@ declare module 'xterm' { * @param key The option key. * @param value The option value. */ - setOption(key: 'bellStyle', value: 'none' | 'visual' | 'sound' | 'both'): void; + setOption(key: 'bellStyle', value: null | 'none' | 'visual' | 'sound' | 'both'): void; /** * Sets an option on the terminal. * @param key The option key. * @param value The option value. */ - setOption(key: 'cursorStyle', value: 'block' | 'underline' | 'bar'): void; + setOption(key: 'cursorStyle', value: null | 'block' | 'underline' | 'bar'): void; /** * Sets an option on the terminal. * @param key The option key.