Comparing version 2.1.0 to 2.2.0
export { Canvas, Region } from "./antsy/canvas"; | ||
export { GridLayout } from "./antsy/grid_layout"; | ||
export { Key, KeyParser, KeyType, Modifier } from "./antsy/keys"; | ||
export { Terminal } from "./antsy/terminal"; | ||
export { TextBuffer } from "./antsy/text_buffer"; | ||
export { get_color, name_to_rgb, xterm_to_rgb } from "./antsy/xterm256"; |
@@ -6,2 +6,9 @@ "use strict"; | ||
Object.defineProperty(exports, "Region", { enumerable: true, get: function () { return canvas_1.Region; } }); | ||
var grid_layout_1 = require("./antsy/grid_layout"); | ||
Object.defineProperty(exports, "GridLayout", { enumerable: true, get: function () { return grid_layout_1.GridLayout; } }); | ||
var keys_1 = require("./antsy/keys"); | ||
Object.defineProperty(exports, "Key", { enumerable: true, get: function () { return keys_1.Key; } }); | ||
Object.defineProperty(exports, "KeyParser", { enumerable: true, get: function () { return keys_1.KeyParser; } }); | ||
Object.defineProperty(exports, "KeyType", { enumerable: true, get: function () { return keys_1.KeyType; } }); | ||
Object.defineProperty(exports, "Modifier", { enumerable: true, get: function () { return keys_1.Modifier; } }); | ||
var terminal_1 = require("./antsy/terminal"); | ||
@@ -8,0 +15,0 @@ Object.defineProperty(exports, "Terminal", { enumerable: true, get: function () { return terminal_1.Terminal; } }); |
@@ -0,1 +1,2 @@ | ||
/// <reference types="node" /> | ||
import { TextBuffer } from "./text_buffer"; | ||
@@ -7,5 +8,13 @@ export declare class Canvas { | ||
currentBuffer?: TextBuffer; | ||
_all?: Region; | ||
dirty: boolean; | ||
dirtyListener?: () => void; | ||
dirtyTimer?: NodeJS.Timeout; | ||
dirtyDebounceDelay: number; | ||
constructor(cols: number, rows: number); | ||
onDirty(debounceDelay: number, f: () => void): void; | ||
resize(cols: number, rows: number): void; | ||
all(): Region; | ||
clip(x1: number, y1: number, x2: number, y2: number): Region; | ||
setDirty(): void; | ||
write(x: number, y: number, attr: number, s: string): void; | ||
@@ -25,7 +34,10 @@ writeChars(x: number, y: number, attr: number, chars: string[]): void; | ||
attr: number; | ||
resizeListeners: Set<() => void>; | ||
constructor(canvas: Canvas, x1: number, y1: number, x2: number, y2: number); | ||
get cols(): number; | ||
get rows(): number; | ||
onResize(f: () => void): void; | ||
all(): Region; | ||
clip(x1: number, y1: number, x2: number, y2: number): Region; | ||
resize(x1: number, y1: number, x2: number, y2: number): void; | ||
color(fg?: string | number, bg?: string | number): this; | ||
@@ -32,0 +44,0 @@ backgroundColor(bg: string | number): this; |
@@ -10,2 +10,3 @@ "use strict"; | ||
const BLACK = 0; // xterm256.get_color("black"); | ||
const DEFAULT_ATTR = (BLACK << 8) | WHITE; | ||
const SPACE = 0x20; | ||
@@ -16,16 +17,45 @@ class Canvas { | ||
this.rows = rows; | ||
// do we want to be redrawn? | ||
this.dirty = true; | ||
this.dirtyDebounceDelay = 0; | ||
this.nextBuffer = new text_buffer_1.TextBuffer(cols, rows); | ||
this.currentBuffer = new text_buffer_1.TextBuffer(cols, rows); | ||
this.nextBuffer.clearBox(0, 0, cols, rows, (BLACK << 8) | WHITE); | ||
this.nextBuffer.clearBox(0, 0, cols, rows, DEFAULT_ATTR); | ||
} | ||
onDirty(debounceDelay, f) { | ||
this.dirtyListener = f; | ||
this.dirtyDebounceDelay = debounceDelay; | ||
} | ||
resize(cols, rows) { | ||
this.nextBuffer.resize(cols, rows, DEFAULT_ATTR); | ||
delete this.currentBuffer; | ||
this.cols = cols; | ||
this.rows = rows; | ||
if (this._all) | ||
this._all.resize(0, 0, this.cols, this.rows); | ||
} | ||
all() { | ||
return new Region(this, 0, 0, this.cols, this.rows); | ||
if (!this._all) | ||
this._all = new Region(this, 0, 0, this.cols, this.rows); | ||
return this._all; | ||
} | ||
clip(x1, y1, x2, y2) { | ||
x1 = Math.max(0, Math.min(x1, this.cols)); | ||
x2 = Math.max(0, Math.min(x2, this.cols)); | ||
y1 = Math.max(0, Math.min(y1, this.rows)); | ||
y2 = Math.max(0, Math.min(y2, this.rows)); | ||
return new Region(this, Math.max(x1, 0), y1, x2, y2); | ||
return this.all().clip(x1, y1, x2, y2); | ||
} | ||
setDirty() { | ||
this.dirty = true; | ||
if (!this.dirtyListener) | ||
return; | ||
if (!this.dirtyTimer) | ||
this.dirtyTimer = setTimeout(() => { | ||
this.dirtyTimer = undefined; | ||
if (this.dirty && this.dirtyListener) { | ||
try { | ||
this.dirtyListener(); | ||
} | ||
catch (error) { | ||
// pass | ||
} | ||
} | ||
}, this.dirtyDebounceDelay); | ||
} | ||
write(x, y, attr, s) { | ||
@@ -36,2 +66,3 @@ this.writeChars(x, y, attr, [...s]); | ||
var _a; | ||
this.setDirty(); | ||
for (let i = 0; i < chars.length; i++) { | ||
@@ -48,2 +79,3 @@ const ch = (_a = chars[i].codePointAt(0)) !== null && _a !== void 0 ? _a : SPACE; | ||
this.currentBuffer = new text_buffer_1.TextBuffer(this.cols, this.rows); | ||
this.dirty = false; | ||
return canvas_diff_1.computeDiff(this.currentBuffer, this.nextBuffer); | ||
@@ -81,2 +113,3 @@ } | ||
this.y2 = y2; | ||
this.resizeListeners = new Set(); | ||
this.cursorX = 0; | ||
@@ -92,2 +125,5 @@ this.cursorY = 0; | ||
} | ||
onResize(f) { | ||
this.resizeListeners.add(f); | ||
} | ||
all() { | ||
@@ -111,2 +147,13 @@ const r = new Region(this.canvas, 0, 0, this.canvas.cols, this.canvas.rows); | ||
} | ||
// usually called by a layout engine | ||
resize(x1, y1, x2, y2) { | ||
this.x1 = x1; | ||
this.y1 = y1; | ||
this.x2 = x2; | ||
this.y2 = y2; | ||
// clip cursor: | ||
this.at(this.cursorX, this.cursorY); | ||
for (const f of [...this.resizeListeners]) | ||
f(); | ||
} | ||
color(fg, bg) { | ||
@@ -133,2 +180,3 @@ if (fg !== undefined) { | ||
this.canvas.nextBuffer.clearBox(this.x1, this.y1, this.x2, this.y2, this.attr); | ||
this.canvas.setDirty(); | ||
return this; | ||
@@ -161,2 +209,3 @@ } | ||
this.canvas.nextBuffer.putBox(this.x1, this.y1, other.canvas.nextBuffer, other.x1, other.y1, other.x2, other.y2); | ||
this.canvas.setDirty(); | ||
return this; | ||
@@ -166,2 +215,3 @@ } | ||
this.canvas.nextBuffer.scrollUp(this.x1, this.y1, this.x2, this.y2, rows, this.attr); | ||
this.canvas.setDirty(); | ||
return this; | ||
@@ -171,2 +221,3 @@ } | ||
this.canvas.nextBuffer.scrollDown(this.x1, this.y1, this.x2, this.y2, rows, this.attr); | ||
this.canvas.setDirty(); | ||
return this; | ||
@@ -176,2 +227,3 @@ } | ||
this.canvas.nextBuffer.scrollLeft(this.x1, this.y1, this.x2, this.y2, cols, this.attr); | ||
this.canvas.setDirty(); | ||
return this; | ||
@@ -181,7 +233,9 @@ } | ||
this.canvas.nextBuffer.scrollRight(this.x1, this.y1, this.x2, this.y2, cols, this.attr); | ||
this.canvas.setDirty(); | ||
return this; | ||
} | ||
moveCursor(x = this.cursorX, y = this.cursorY) { | ||
this.canvas.nextBuffer.cursorX = x; | ||
this.canvas.nextBuffer.cursorY = y; | ||
this.canvas.nextBuffer.cursorX = this.x1 + x; | ||
this.canvas.nextBuffer.cursorY = this.y1 + y; | ||
this.canvas.setDirty(); | ||
return this; | ||
@@ -188,0 +242,0 @@ } |
export declare enum Modifier { | ||
Meta = 0, | ||
Shift = 1, | ||
Control = 2 | ||
Alt = 2, | ||
Control = 4, | ||
Meta = 8 | ||
} | ||
@@ -27,6 +28,6 @@ export declare enum KeyType { | ||
export declare class Key { | ||
modifiers: Modifier[]; | ||
modifiers: Modifier; | ||
type: KeyType; | ||
key: string; | ||
constructor(modifiers: Modifier[], type: KeyType, key?: string); | ||
constructor(modifiers: Modifier, type: KeyType, key?: string); | ||
toString(): string; | ||
@@ -43,3 +44,3 @@ } | ||
state: State; | ||
modifiers: Modifier[]; | ||
modifiers: Modifier; | ||
buffer: string; | ||
@@ -46,0 +47,0 @@ lastKey: number; |
@@ -6,5 +6,6 @@ "use strict"; | ||
(function (Modifier) { | ||
Modifier[Modifier["Meta"] = 0] = "Meta"; | ||
Modifier[Modifier["Shift"] = 1] = "Shift"; | ||
Modifier[Modifier["Control"] = 2] = "Control"; | ||
Modifier[Modifier["Alt"] = 2] = "Alt"; | ||
Modifier[Modifier["Control"] = 4] = "Control"; | ||
Modifier[Modifier["Meta"] = 8] = "Meta"; | ||
})(Modifier = exports.Modifier || (exports.Modifier = {})); | ||
@@ -16,2 +17,4 @@ function modifiersFromFlags(n) { | ||
rv.push(Modifier.Meta); | ||
if (n & 2) | ||
rv.push(Modifier.Alt); | ||
if (n & 1) | ||
@@ -21,3 +24,2 @@ rv.push(Modifier.Shift); | ||
rv.push(Modifier.Control); | ||
// alt (old name for meta) was 2 | ||
return rv; | ||
@@ -54,12 +56,9 @@ } | ||
toString() { | ||
const segments = this.modifiers.map(m => { | ||
switch (m) { | ||
case Modifier.Meta: | ||
return "M"; | ||
case Modifier.Shift: | ||
return "S"; | ||
case Modifier.Control: | ||
return "C"; | ||
} | ||
}); | ||
const segments = []; | ||
if ((this.modifiers & (Modifier.Meta | Modifier.Alt)) != 0) | ||
segments.push("M"); | ||
if (this.modifiers & Modifier.Shift) | ||
segments.push("S"); | ||
if (this.modifiers & Modifier.Control) | ||
segments.push("C"); | ||
switch (this.type) { | ||
@@ -114,3 +113,3 @@ case KeyType.Normal: | ||
this.state = State.Normal; | ||
this.modifiers = []; | ||
this.modifiers = 0; | ||
this.buffer = ""; | ||
@@ -145,7 +144,7 @@ this.lastKey = Date.now(); | ||
rv.push(new Key(this.modifiers, KeyType.Tab)); | ||
this.modifiers = []; | ||
this.modifiers = 0; | ||
return false; | ||
case Ascii.CR: | ||
rv.push(new Key(this.modifiers, KeyType.Return)); | ||
this.modifiers = []; | ||
this.modifiers = 0; | ||
return false; | ||
@@ -158,3 +157,3 @@ case Ascii.ESC: | ||
rv.push(new Key(this.modifiers, KeyType.Backspace)); | ||
this.modifiers = []; | ||
this.modifiers = 0; | ||
return false; | ||
@@ -164,7 +163,7 @@ default: | ||
// control codes! | ||
this.modifiers.push(Modifier.Control); | ||
this.modifiers |= Modifier.Control; | ||
c += 64; | ||
} | ||
rv.push(new Key(this.modifiers, KeyType.Normal, String.fromCodePoint(c))); | ||
this.modifiers = []; | ||
this.modifiers = 0; | ||
return false; | ||
@@ -183,4 +182,3 @@ } | ||
// well crap. assume they meant meta. | ||
if (this.modifiers.indexOf(Modifier.Meta) < 0) | ||
this.modifiers.push(Modifier.Meta); | ||
this.modifiers |= Modifier.Meta; | ||
this.state = State.Normal; | ||
@@ -196,3 +194,3 @@ return this.feedCodepoint(c, rv); | ||
this.state = State.Normal; | ||
this.modifiers = []; | ||
this.modifiers = 0; | ||
return false; | ||
@@ -203,3 +201,3 @@ case State.SS3: | ||
this.state = State.Normal; | ||
this.modifiers = []; | ||
this.modifiers = 0; | ||
return false; | ||
@@ -209,3 +207,3 @@ } | ||
// what is ESC O (something)? we don't support it. | ||
rv.push(new Key([Modifier.Meta], KeyType.Normal, "O")); | ||
rv.push(new Key(Modifier.Meta, KeyType.Normal, "O")); | ||
this.state = State.Normal; | ||
@@ -218,3 +216,3 @@ return this.feedCodepoint(c, rv); | ||
if (args[0] == 1 && args.length >= 2) | ||
this.modifiers = this.modifiers.concat(modifiersFromFlags(args[1])); | ||
this.modifiers |= (args[1] - 1); | ||
switch (command) { | ||
@@ -253,3 +251,3 @@ case "A": | ||
if (args.length > 1) | ||
this.modifiers = this.modifiers.concat(modifiersFromFlags(args[1])); | ||
this.modifiers = this.modifiers |= (args[1] - 1); | ||
switch (args[0] || 0) { | ||
@@ -323,4 +321,4 @@ case 1: | ||
// well crap. CSI + garbage? | ||
rv.push(new Key([Modifier.Meta], KeyType.Normal, "[")); | ||
rv.push(new Key([], KeyType.Normal, command)); | ||
rv.push(new Key(Modifier.Meta, KeyType.Normal, "[")); | ||
rv.push(new Key(0, KeyType.Normal, command)); | ||
break; | ||
@@ -327,0 +325,0 @@ } |
@@ -20,2 +20,4 @@ export declare class ScrollRegion { | ||
constructor(cols: number, rows: number); | ||
resize(cols: number, rows: number, defaultAttr: number): void; | ||
private alloc; | ||
put(x: number, y: number, attr: number, char: number): void; | ||
@@ -22,0 +24,0 @@ getAttr(x: number, y: number): number; |
@@ -24,2 +24,29 @@ "use strict"; | ||
this.pendingScrolls = []; | ||
this.alloc(cols, rows); | ||
this.cursorX = 0; | ||
this.cursorY = 0; | ||
this.attr = -1; | ||
} | ||
resize(cols, rows, defaultAttr) { | ||
const oldChars = this.chars; | ||
const oldAttrs = this.attrs; | ||
const oldCols = this.cols; | ||
const oldRows = this.rows; | ||
this.alloc(cols, rows); | ||
// invalidate everything, then copy over what will fit. | ||
this.clearBox(0, 0, cols, rows, defaultAttr); | ||
for (let y = 0; y < Math.min(oldRows, this.rows); y++) { | ||
this.setDirty(y); | ||
const left = this.cols * y; | ||
const oldLeft = oldCols * y; | ||
for (let x = 0; x < Math.min(oldCols, this.cols); x++) { | ||
this.chars[left + x] = oldChars[oldLeft + x]; | ||
this.attrs[left + x] = oldAttrs[oldLeft + x]; | ||
} | ||
} | ||
this.pendingScrolls = []; | ||
this.cursorX = Math.min(this.cursorX, cols - 1); | ||
this.cursorY = Math.min(this.cursorY, rows - 1); | ||
} | ||
alloc(cols, rows) { | ||
if (cols < 0 || rows < 0 || rows > MAX_HEIGHT) | ||
@@ -30,5 +57,4 @@ throw new Error(`Invalid terminal size ${cols} x ${rows}`); | ||
this.dirty = new Uint8Array(Math.ceil(rows / 8)); | ||
this.cursorX = 0; | ||
this.cursorY = 0; | ||
this.attr = -1; | ||
this.cols = cols; | ||
this.rows = rows; | ||
} | ||
@@ -35,0 +61,0 @@ put(x, y, attr, char) { |
@@ -126,2 +126,10 @@ "use strict"; | ||
}); | ||
it("resizes", () => { | ||
const c = new canvas_1.Canvas(10, 10); | ||
c.all().color("00f").at(5, 3).write("hello"); | ||
c.all().color("f00").at(0, 9).write("ok"); | ||
escpaint(c).should.eql(`${RESET}[[4;6H[[38;5;12mhello[[10H[[38;5;9mok[[H`); | ||
c.resize(8, 11); | ||
escpaint(c).should.eql(`${RESET}[[4;6H[[38;5;12mhel[[10H[[38;5;9mok[[H`); | ||
}); | ||
describe("scrolls", () => { | ||
@@ -128,0 +136,0 @@ function stars() { |
{ | ||
"name": "antsy", | ||
"version": "2.1.0", | ||
"version": "2.2.0", | ||
"description": "draw full-color (xterm-256) ansi graphics into a buffer", | ||
@@ -27,2 +27,3 @@ "keywords": [ | ||
"@types/node": "^10.17.28", | ||
"@types/source-map-support": "^0.5.3", | ||
"mocha": "^8.1.1", | ||
@@ -29,0 +30,0 @@ "should": "^13.2.3", |
@@ -60,3 +60,7 @@ # Antsy | ||
- `paintInline(): string` | ||
Return the ANSI codes that will paint the current canvas contents as if the screen was in an unknown (dirty) state. Every glyph and color will be rendered, separated by linefeeds, without cursor manipulation. This may be useful for rendering small canvases that are meant to be embedded in other displays or output that doesn't know about the canvas. | ||
## Region | ||
@@ -63,0 +67,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
172579
42
2031
131
7