From 36ef6c32f371c42066f47a4ae37795e88ec49030 Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Sat, 16 Nov 2019 08:49:06 -0800 Subject: [PATCH] Add `iTerm.annotation()` method (#17) Co-authored-by: Sindre Sorhus --- example.js | 6 ++++++ index.d.ts | 46 +++++++++++++++++++++++++++++++++++++++++ index.js | 24 ++++++++++++++++++++- index.test-d.ts | 1 + readme.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 131 insertions(+), 1 deletion(-) diff --git a/example.js b/example.js index 604cd0e..9cb1ccf 100644 --- a/example.js +++ b/example.js @@ -3,3 +3,9 @@ const fs = require('fs'); const ansiEscapes = require('.'); console.log(ansiEscapes.image(fs.readFileSync('fixture.jpg'), {width: 15})); + +const text = 'this text will be annotated'; +console.log(text); +process.stdout.write(ansiEscapes.cursorPrevLine); +console.log(ansiEscapes.iTerm.annotation('this is an annotation', {length: text.length})); +console.log(); diff --git a/index.d.ts b/index.d.ts index 6c481f4..a11c51c 100644 --- a/index.d.ts +++ b/index.d.ts @@ -25,6 +25,40 @@ declare namespace ansiEscapes { readonly preserveAspectRatio?: boolean; } + + interface AnnotationOptions { + /** + Nonzero number of columns to annotate. + + Default: The remainder of the line. + */ + readonly length?: number; + + /** + Starting X coordinate. + + Must be used with `y` and `length`. + + Default: The cursor position + */ + readonly x?: number; + + /** + Starting Y coordinate. + + Must be used with `x` and `length`. + + Default: Cursor position. + */ + readonly y?: number; + + /** + Create a "hidden" annotation. + + Annotations created this way can be shown using the "Show Annotations" iTerm command. + */ + readonly isHidden?: boolean; + } } declare const ansiEscapes: { @@ -193,6 +227,18 @@ declare const ansiEscapes: { @param cwd - Current directory. Default: `process.cwd()`. */ setCwd(cwd: string): string; + + /** + An annotation looks like this when shown: + + ![screenshot of iTerm annotation](https://user-images.githubusercontent.com/924465/64382136-b60ac700-cfe9-11e9-8a35-9682e8dc4b72.png) + + See the [iTerm Proprietary Escape Codes documentation](https://iterm2.com/documentation-escape-codes.html) for more information. + + @param message - The message to display within the annotation. The `|` character is disallowed and will be stripped. + @returns An escape code which will create an annotation when printed in iTerm2. + */ + annotation(message: string, options?: ansiEscapes.AnnotationOptions): string; }; // TODO: remove this in the next major version diff --git a/index.js b/index.js index 4638bbc..fbe24ac 100644 --- a/index.js +++ b/index.js @@ -128,5 +128,27 @@ ansiEscapes.image = (buffer, options = {}) => { }; ansiEscapes.iTerm = { - setCwd: (cwd = process.cwd()) => `${OSC}50;CurrentDir=${cwd}${BEL}` + setCwd: (cwd = process.cwd()) => `${OSC}50;CurrentDir=${cwd}${BEL}`, + + annotation: (message, options = {}) => { + let ret = `${OSC}1337;`; + const hasX = typeof options.x !== 'undefined'; + const hasY = typeof options.y !== 'undefined'; + if ((hasX || hasY) && !(hasX && hasY && typeof options.length !== 'undefined')) { + throw new Error('`x`, `y` and `length` must be defined when `x` or `y` is defined'); + } + // eslint-disable-next-line padding-line-between-statements + message = message.replace(/\|/g, ''); + ret += options.isHidden ? 'AddHiddenAnnotation=' : 'AddAnnotation='; + if (options.length > 0) { + ret += + (hasX ? + [message, options.length, options.x, options.y] : + [options.length, message]).join('|'); + } else { + ret += message; + } + + return ret + BEL; + } }; diff --git a/index.test-d.ts b/index.test-d.ts index 53b49bf..a35f064 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -45,3 +45,4 @@ expectType( ansiEscapes.image(new Buffer(1), {preserveAspectRatio: false}) ); expectType(ansiEscapes.iTerm.setCwd('/foo/bar')); +expectType(ansiEscapes.iTerm.annotation('foo bar')); diff --git a/readme.md b/readme.md index b290753..3b98dad 100644 --- a/readme.md +++ b/readme.md @@ -175,6 +175,61 @@ Default: `process.cwd()` [Inform iTerm2](https://www.iterm2.com/documentation-escape-codes.html) of the current directory to help semantic history and enable [Cmd-clicking relative paths](https://coderwall.com/p/b7e82q/quickly-open-files-in-iterm-with-cmd-click). +### iTerm.annotation(message, options?) + +Creates an escape code to display an "annotation" in iTerm2. + +An annotation looks like this when shown: + + + +See the [iTerm Proprietary Escape Codes documentation](https://iterm2.com/documentation-escape-codes.html) for more information. + +#### message + +Type: `string` + +The message to display within the annotation. + +The `|` character is disallowed and will be stripped. + +#### options + +Type: `object` + +##### length + +Type: `number`\ +Default: The remainder of the line + +Nonzero number of columns to annotate. + +##### x + +Type: `number`\ +Default: Cursor position + +Starting X coordinate. + +Must be used with `y` and `length`. + +##### y + +Type: `number`\ +Default: Cursor position + +Starting Y coordinate. + +Must be used with `x` and `length`. + +##### isHidden + +Type: `boolean`\ +Default: `false` + +Create a "hidden" annotation. + +Annotations created this way can be shown using the "Show Annotations" iTerm command. ## Related