terminal.js
Version:
terminal emulation library for javascript.
2,181 lines (1,919 loc) • 296 kB
JavaScript
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Terminal = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
module.exports = require("./lib/terminal.js");
module.exports.TermState = require("./lib/term_state.js");
module.exports.TermDiff = require("./lib/term_diff.js");
module.exports.output = {
PlainOutput: require("./lib/output/plain.js"),
AnsiOutput: require("./lib/output/ansi.js"),
TtyOutput: require("./lib/output/tty.js"),
HtmlOutput: require("./lib/output/html.js"),
DomOutput: require("./lib/output/dom.js")
};
module.exports.source = {
EmitterSource: require("./lib/source/emitter.js")
};
module.exports.input = {
DomInput: require('./lib/input/dom.js'),
TtyInput: require('./lib/input/tty.js'),
};
},{"./lib/input/dom.js":10,"./lib/input/tty.js":11,"./lib/output/ansi.js":12,"./lib/output/dom.js":14,"./lib/output/html.js":15,"./lib/output/plain.js":17,"./lib/output/tty.js":18,"./lib/source/emitter.js":20,"./lib/term_diff.js":21,"./lib/term_state.js":22,"./lib/terminal.js":23}],2:[function(require,module,exports){
"use strict";
// function(cmd, chunk);
/**
* handlers for command characters
* @enum {Function|string}
* @readonly
* @this refers to calling {@link Terminal}
*/
var chr = {
/**
* BELL
*/
"\x07": function(cmd, chunk) { // BELL
this.emit("bell");
},
/**
* BACKSPACE
*/
"\x08": function(cmd, chunk) { // BACKSPACE
this.state.mvCursor(-1, 0);
},
/**
* TAB
*/
"\x09": function(cmd, chunk) { // TAB
this.state.mvTab(1);
},
/**
* DELETE
*/
"\x7f": function(cmd, chunk) { // DELETE
this.state.removeChar(1);
},
/**
* TABSET
*/
"\x88": function(cmd, chunk) { // TABSET
this.state.setTab();
},
/**
* SO
*/
"\x0e": function() { // SO
this.state.mapCharset("G1");
},
/**
* SI
*/
"\x0f": function() { // SI
this.state.mapCharset("G0");
},
/**
* ESCAPE
*/
"\x1b": function(cmd, chunk) {
return chunk[1] !== undefined ?
this.callHandler("esc", chunk[1], chunk) :
0;
},
/**
* CARRIAGE RETURN
*/
"\r": function(cmd, chunk) {
this.state.setCursor(0, null);
}
};
module.exports = chr;
},{}],3:[function(require,module,exports){
"use strict";
// function(cmd, n, m, args, mod);
/**
* csi command handlers
* @enum {Function|string}
* @readonly
* @this refers to calling {@link Terminal}
*/
var csi = {
/**
* CSI Ps @ <br>
* Insert Ps (Blank) Character(s) (default = 1) (ICH)
*/
"@": function(cmd, n, m, args, mod) {
this.state.insertBlank(n || 1);
},
/**
* CSI Ps A <br>
* Cursor Up Ps Times (default = 1) (CUU)
*/
"A": function(cmd, n, m, args, mod) {
this.state.mvCursor(0, -(n || 1));
},
/**
* CSI Ps B <br>
* Cursor Down Ps Times (default = 1) (CUD)
*/
"B": function(cmd, n, m, args, mod) {
this.state.mvCursor(0, n || 1);
},
/**
* CSI Ps C <br>
* Cursor Forward Ps Times (default = 1) (CUF)
*/
"C": function(cmd, n, m, args, mod) {
this.state.mvCursor(n || 1, 0);
},
/**
* CSI Ps D <br>
* Cursor backward Ps Times (default = 1) (CUB)
*/
"D": function(cmd, n, m, args, mod) {
this.state.mvCursor(-(n || 1), 0);
},
/**
* CSI Ps E <br>
* Cursor down Ps Rows, to column 1 (default = 1) (CNL , NEL)
*/
"E": function(cmd, n, m, args, mod) {
this.state.mvCursor(0, n || 1).setCursor(0, null);
},
/**
* CSI Ps F <br>
* Cursor Preceding Line PS Times (default = 1) (CPL)
*/
"F": function(cmd, n, m, args, mod) {
// (vt52 compatibility mode - Use special graphics character set? )
this.state.mvCursor(0, -n || -1).setCursor(0, null);
},
/**
* CSI Ps G <br>
* Cursor Character Absolute [column] (default = [row,1]) (CHA)
*/
"G": function(cmd, n, m, args, mod) {
//vt52 compatibility mode - Use normal US/UK character set )
this.state.setCursor((n || 1) - 1);
},
/**
* CSI Ps ; Ps H <br>
* Cursor Position [row;column] (default = [1,1]) (CUP)
*/
"H": function(cmd, n, m, args, mod) {
this.state.setCursor((m || 1) - 1, (n || 1) - 1);
},
/**
* CSI Ps I <br>
* Cursor Forward Tabulation Ps tab stops (default = 1) (CHT)
*/
"I": function(cmd, n, m, args, mod) {
this.state.mvTab(n || 1);
},
/**
* CSI Ps J <br>
* Erase in Display (default = 0) (ED)
* <ul>
* <li>J - erase from cursor to end of display</li>
* <li>0J - erase from cursor to end of display</li>
* <li>1J - erase from start to cursor</li>
* <li>2J - erase whole display</li>
* </ul>
*/
"J": function(cmd, n, m, args, mod) {
this.state.eraseInDisplay(n || 0);
},
/**
* CSI Ps K <br>
* Erase in Line (default = 0) (EL)
* <ul>
* <li>K - erase from cursor to end of line</li>
* <li>0K - erase from cursor to end of line</li>
* <li>1K - erase from start of line to cursor</li>
* <li>2K - erase whole line</li>
* </ul>
*/
"K": function(cmd, n, m, args, mod) {
this.state.eraseInLine(n || 0);
},
/**
* CSI Ps L <br>
* Insert Ps Line(s) (default = 1) (IL)
*/
"L": function(cmd, n, m, args, mod) {
this.state.insertLine(n || 1);
this.state.setCursor(0, null);
},
/**
* CSI Ps M <br>
* Delete Ps Line(s) (default = 1) (DL)
*/
"M": function(cmd, n, m, args, mod) {
this.state.removeLine(n || 1);
},
/**
* CSI Ps P <br>
* Delete Ps Character(s) (default = 1) (DCH)
*/
"P": function(cmd, n, m, args, mod) {
this.state.removeChar(n || 1);
},
/**
* CSI Pl ; Pc R <br>
* Report cursor pAosition (CPR)<br>
* <ul>
* <li>Pl indicates what line the cursor is on</li>
* <li>Pr indicated what row the cursor is on</li>
* </ul>
* @todo implement
*/
"R": function(cmd, n, m, args, mod) {
// TODO
},
/**
* CSI Ps S <br>
* Scroll up Ps lines (default = 1) (SU)
*/
"S": function(cmd, n, m, args, mod) {
this.state.scroll(n || 1);
},
/**
* CSI Ps T <br>
* Scroll down Ps lines (default = 1) (SD) <br>
* CSI Ps ; Ps ; Ps ; Ps ; Ps T <br>
* Initiate highlight mouse tracking <br>
* CSI > Ps; Ps T <br>
* @todo handle ">" mode
*/
"T": function(cmd, n, m, args, mod) {
if(args.length <= 1)
this.state.scroll(-n || -1);
},
/**
* CSI Ps X <br>
* Erase Ps Character(s) (default = 1) (ECH)
*/
"X": function(cmd, n, m, args, mod) {
this.state.eraseCharacters(n || 1);
},
/**
* CSI Ps Z <br>
* Cursor Backward Tabulation Ps tab stops (default = 1) (CBT)
*/
"Z": function(cmd, n, m, args, mod) {
this.state.mvTab(-(n || 1));
},
/**
* CSI Ps a <br>
* Move cursor right the indicated # of columns (default = 1) (HPR)
*/
"a": function(cmd, n, m, args, mod) {
this.state.mvCursor(n || 1, 0);
},
/**
* CSI Ps b <br>
* Repeat the preceding graphic character Ps times (REP)
*/
"b": function(cmd, n, m, args, mod) {
// TODO
},
/**
* CSI P s c <br>
* Send Device Attributes (Primary DA) <br>
* CSI > P s c <br>
* Send Device Attributes (Secondary DA) <br>
*/
"c": function(cmd, n, m, args, mod) {
// TODO
this.emit("request", "\x1b>0;95;c");
},
/**
* CSI Pm d <br>
* Line Position Absolute [row] (default = [1,column]) (VPA)
*/
"d": function(cmd, n, m, args, mod) {
this.state.setCursor(null, (n || 1) - 1);
},
/**
* CSI Pm e <br>
* Vertical position relative.
* Move cursor down the indicated # of rows (default = 1) (VPR)
*/
"e": function(cmd, n, m, args, mod) {
this.state.mvCursor(0, n || 1);
},
/**
* CSI Ps ; Ps f <br>
* Horizontal and Vertical Position [row;column] (default = [1,1]) (HVP)
*/
"f": function(cmd, n, m, args, mod) {
this.state.setCursor((m || 1) - 1, (n || 1) - 1);
},
/**
* CSI Ps g <br>
* Tab Clear (default = 0) (TBC)
*/
"g": function(cmd, n, m, args, mod) {
// 0g = clear tab stop at the current position
// 3g = delete all tab stops
// TODO
this.state.tabClear(n || 0);
},
/**
* CSI Pm h <br>
* Set Mode (SM) <br>
* CSI ? Pm h - mouse escape codes, cursor escape codes <br>
*/
"h": function(cmd, n, m, args, mod) {
var i;
for(i = 0; i < args.length; i++)
this.callHandler("mode", mod+args[i], true);
},
/**
* CSI Pm i Media Copy (MC) <br>
* CSI ? Pm i <br>
*/
"i": function(cmd, n, m, args, mod) {
// TODO
},
/**
* CSI Pm l Reset Mode (RM) <br>
* CSI ? Pm l <br>
*/
"l": function(cmd, n, m, args, mod) {
var i;
for(i = 0; i < args.length; i++)
this.callHandler("mode", mod+args[i], false);
},
/**
* CSI Pm m <br>
* Character Attributes (SGR) <br>
* CSI > Ps; Ps m <br>
*/
"m": function(cmd, n, m, args, mod) {
// Set graphic rendition
var i;
if(args[1] === 5 && args[0] === 38)
this.state.setAttribute("fg", args[2]);
else if(args[1] === 5 && args[0] === 48)
this.state.setAttribute("bg", args[2]);
else {
for(i = 0; i < args.length; i++)
this.callHandler("sgr", args[i]);
if(i === 0)
this.callHandler("sgr", 0);
}
},
/**
* CSI Ps n Device Status Report (DSR) <br>
* CSI > Ps n <br>
* <ul>
* <li>5n - Device Status report</li>
* <li>0n - Response: terminal is OK</li>
* <li>3n - Response: terminal is not OK</li>
* <li>6n - Request cursor position (CPR)</li>
* </ul>
* @todo implement
*/
"n": function(cmd, n, m, args, mod) {
// TODO
},
/**
* CSI > Ps p Set pointer mode <br>
* CSI ! p Soft terminal reset (DECSTR) <br>
* CSI Ps$ p <br>
* Request ANSI mode (DECRQM) <br>
* CSI ? Ps$ p <br>
* Request DEC private mode (DECRQM) <br>
* CSI Ps ; Ps " p <br>
*/
"p": function(cmd, n, m, args, mod) {
// TODO
},
/**
* CSI Ps q <br>
* Load LEDs (DECLL) <br>
* CSI Ps SP q <br>
* CSI Ps " q <br>
* <ul>
* <li>0q - turn off all four leds</li>
* <li>1q - turn on Led #1</li>
* <li>2q - turn on Led #2</li>
* <li>3q - turn on Led #3</li>
* <li>4q - turn on Led #4</li>
* </ul>
*/
"q": function(cmd, n, m, args, mod) {
if(n === 0)
this.state.resetLeds();
else
this.state.ledOn(n-1);
},
/**
* CSI Ps ; Ps r <br>
* Set Scrolling Region [top;bottom] (default = full size of window)
* (DECSTBM) <br>
* CSI ? Pm r <br>
* CSI Pt; Pl; Pb; Pr; Ps$ r <br>
*/
"r": function(cmd, n, m, args, mod) {
// TODO handle ? prefix, $ ends
this.state.setScrollRegion((n || 1) -1 , (m || (this.state.rows) ) -1);
},
/**
* CSI ? Pm s <br>
* Save cursor (ANSI.SYS)
*/
"s": function(cmd, n, m, args, mod) {
this.state.saveCursor();
},
/**
* CSI t <br>
* unknown
* @todo implement
*/
"t": function(cmd, n, m, args, mod) {
// TODO
},
/**
* CSI Ps SP u <br>
* Restore cursor (ANSI.SYS)
*/
"u": function(cmd, n, m, args, mod) {
this.state.restoreCursor();
},
/**
* CSI Pt; Pl; Pb; Pr; Pp; Pt; Pl; Pp$ v <br>
* (DECCRA)
* @todo implement
*/
"v": function(cmd, n, m, args, mod) {
// TODO
},
/**
* CSI Pt ; Pl ; Pb ; Pr " w <br>
* (DECEFR)
* @todo implement
*/
"w": function(cmd, n, m, args, mod) {
// TODO
},
/**
* CSI Ps x Request Terminal Parameters (DECREQTPARM) <br>
* CSI Ps x Select Attribute Change Extent (DECSACE) <br>
* CSI Pc; Pt; Pl; Pb; Pr$ x <br>
* @todo implement
*/
"x": function(cmd, n, m, args, mod) {
// TODO
},
/**
* Request Checksum of Rectangular Area
* DECRQCRA
* @todo implement
*/
"y": function(cmd, n, m, args, mod) {
// TODO
},
/**
* CSI Ps ; Pu " z <br>
* CSI Pt; Pl; Pb; Pr$ z <br>
* (DECELR) / (DECERA)
* Erase rectangular area
*/
"z": function(cmd, n, m, args, mod) {
// TODO
},
/**
* CSI Pm ` Character Position Absolute <br>
* [column] (default = [row,1]) (HPA)
*/
"`": function(cmd, n, m, args, mod) {
this.state.setCursor((n || 1) - 1);
},
/**
* CSI Pm " { <br>
* CSI Pt; Pl; Pb; Pr$ { <br>
* Selectively erase retangular area (DECSLE) / (DECSERA)
* @todo implement
*/
"{": function(cmd, n, m, args, mod) {
// TODO
},
/**
* CSI Ps " | <br>
* Request locator position (DECRQLP)
* @todo implement
*/
"|": function(cmd, n, m, args, mod) {
// TODO
},
/**
* CSI P m SP } <br>
* Insert P s Column(s) (default = 1) (DECIC), VT420 and up
* @todo implement
*/
"}": function(cmd, n, m, args, mod) {
// TODO
},
/**
* CSI P m SP ~ <br>
* Delete P s Column(s) (default = 1) (DECDC), VT420 and up
* @todo implement
*/
"~": function(cmd, n, m, args, mod) {
// TODO
}
};
module.exports = csi;
},{}],4:[function(require,module,exports){
"use strict";
// function(cmd, n, m, args, mod);
/**
* dcs command handlers
* Currently we ignore all DCS codes
* @enum {Function|string}
* @readonly
* @this refers to calling {@link Terminal}
*/
module.exports = {
};
},{}],5:[function(require,module,exports){
"use strict";
/**
* esc command handlers
* Currently we ignore all DCS codes
* @enum {Function|string}
* @readonly
* @this refers to calling {@link Terminal}
*/
var esc = {
/**
* ESC c<br>
* Full Reset (RIS)
*/
"c": function(cmd, chunk) {
this.state.reset();
return 2;
},
/**
* ESC D<br>
* Index (IND is 0x84)
* Moves cursor down one line in same column.
* If cursor is at bottom margin, screen performs a scroll-up.
*/
"D": function(cmd, chunk) {
this.state.nextLine();
return 2;
},
/**
* ESC E<br>
* Next Line (NEL is 0x85)
* This sequence causes the active position to move to the first position on
* the next line downward
* If the active position is at the bottom margin, a scroll up is performed
*/
"E": function(cmd, chunk) {
this.state.nextLine().setCursor(0);
return 2;
},
/**
* ESC F<br>
* Start of Selected Area to be sent to auxiliary output device (SSA)
*/
/**
* ESC G<br>
* End of Selected Area to be sent to auxiliary output device (SSA)
*/
/**
* ESC H<br>
* Tab Set (HTS is 0x88)
*/
"H": function(cmd, chunk) {
this.state.setTab();
return 2;
},
/**
* ESC I<br>
* Horizontal Tab Justify, moves string to next tab position (HTJ)
*/
/**
* ESC J<br>
* Vertical Tabulation Set at current line (VTS)
*/
/**
* ESC K<br>
* Partial Line Down (subscript) (PLD)
*/
/**
* ESC L<br>
* Partial Line Up (superscript) (PLU)
*/
/**
* ESC M<br>
* Reverse Index (RI is 0x8d)
* Move the active position to the same horizontal position on the preceding line.
* If the active position is at the top margin, a scroll down is performed
*/
"M": function(cmd, chunk) {
this.state.prevLine();
return 2;
},
/**
* ESC N<br>
* Single Shift Select of G2 Character Set (SS2 is 0x8e). This affects next character only
*/
"N": function(cmd, chunk) {
this.state.mapCharset("G2", true);
return 2;
},
/**
* ESC O<br>
* Single Shift Select of G3 Character Set (SS3 is 0x8f). This affects next character only
*/
"O": function(cmd, chunk) {
this.state.mapCharset("G3", true);
return 2;
},
/**
* ESC P<br>
* Device Control String (DCS is 0x90)
* @todo function should return errors if it detects garbaged DCS sequences
*/
"P": function(cmd, chunk) {
var dcs = this.parseDcs(chunk);
if(dcs === null || dcs.cmd === "")
return 0;
else if(dcs.length !== chunk.length && dcs.cmd === "") {
// TODO Garbaged DCS. report error.
return 1;
}
var result = this.callHandler("dcs", dcs.cmd, +dcs.args[0],
+dcs.args[1], dcs.args, dcs.mod);
return dcs.length;
},
/**
* ESC Q<br>
* Private Use 1 (PU1)
*/
"Q": function(cmd, chunk) {
return 2;
},
/**
* ESC R<br>
* Private Use 2 (PU2)
*/
"R": function(cmd, chunk) {
return 2;
},
/**
* ESC S<br>
* Set Transmit State (STS)
*/
"S": function(cmd, chunk) {
return 2;
},
/**
* ESC T<br>
* Cancel Character, ignore previous character (CCH)
* @todo implement
*/
"T": function(cmd, chunk) {
//TODO
return 2;
},
/**
* ESC U<br>
* Message Waiting, turns on an indicator on the terminal (MW)
*/
"U": function(cmd, chunk) {
return 2;
},
/**
* ESC V<br>
* Start of Protected Area (SPA)
*/
"V": function(cmd, chunk) {
return 2;
},
/**
* ESC W<br>
* End of Protected Area (EPA)
*/
"W": function(cmd, chunk) {
return 2;
},
/**
* ESC X<br>
* Reserved
*/
"X": function(cmd, chunk) {
return 2;
},
/**
* ESC Y<br>
* Reserved
*/
"Y": function(cmd, chunk) {
return 2;
},
/**
* ESC Z<br>
* DECID Dec Private identification
* The kernel returns the string ESC [ ? 6 c , claiming it is a VT102
*/
"Z": function(cmd, chunk) {
return 2;
},
/**
* ESC n<br>
* Invoke the G2 Character Set as GL (LS2)
*/
"n": function(cmd, chunk) {
this.state.mapCharset("G2");
return 2;
},
/**
* ESC o<br>
* Invoke the G3 Character Set as GL (LS3)
*/
"o": function(cmd, chunk) {
this.state.mapCharset("G3");
return 2;
},
/**
* ESC 7<br>
* Save Cursor (DECSC)
*/
"7": function(cmd, chunk) {
this.state.saveCursor();
return 2;
},
/**
* ESC 8<br>
* Restore Cursor (DECRC)
*/
"8": function(cmd, chunk) {
this.state.restoreCursor();
return 2;
},
/**
* ESC |<br>
* Invoke the G3 Character Set as GR (LS3R)
*/
"|": function(cmd, chunk) {
// TODO
return 2;
},
/**
* ESC [<br>
* Control sequence introducer (CSI)
* @todo function should return errors if it detects garbaged CSI sequences
*/
"[": function(cmd, chunk) {
var csi = this.parseCsi(chunk);
if(csi === null || csi.cmd === "")
return 0;
else if(csi.length !== chunk.length && csi.cmd === "") {
// TODO Garbaged CSI. report error.
return 1;
}
var result = this.callHandler("csi", csi.cmd, +csi.args[0], +csi.args[1], csi.args, csi.mod);
//if(result === null)
// TODO Unknown CSI. report error.
return csi.length;
},
/**
* ESC \<br>
* 7-bit - File Separator (FS)
* 8-bit - String Terminator (VT125 exits graphics) (ST)
*/
"\\": function(cmd, chunk) {
return 2;
},
/**
* ESC ]<br>
* 7-bit - Group Separator (GS)
* 8-bit - Operating System Command (OSC is 0x9d)
* @todo function should return errors if it detects garbaged OSC sequences
*/
"]": function(cmd, chunk) {
var osc = this.parseOsc(chunk);
if(osc === null || osc.terminated === false)
return 0;
else if(osc.length !== chunk.length && osc.terminated === false) {
// TODO Garbaged OSC. report error.
return 1;
}
var result = this.callHandler("osc", osc.cmd, osc.args);
//if(result === null)
// TODO Unknown OSC. report error.
return osc.length;
},
/**
* ESC ^<br>
* Privacy Message (password verification), terminaed by ST
* (PM is 0x9e) (PM)
*/
"^": function(cmd, chunk) {
return 2;
},
/**
* ESC _<br>
* Application Program Command (to word processor), term by ST
* (APC is 0x9f) (APC)
*/
"_": function(cmd, chunk) {
return 2;
},
/**
* ESC %<br>
* Select default/utf-8 character set.
* @ = default, G = utf-8; 8 (Obsolete)
*/
"%": function(cmd, chunk) {
if(chunk[2] === undefined)
return 0;
this.state.selectCharset("unicode");
return 3;
},
/**
* ESC }<br>
* Invoke the G2 Character Set as GR (LS2R)
*/
"}": function(cmd, chunk) {
// TODO
return 2;
},
/**
* ESC ~<br>
* Invoke the G1 Character Set as GR (LS1R)
*/
"~": function(cmd, chunk) {
// TODO
return 2;
},
/**
* ESC ( ) * + - . /<br>
*/
"(": "/",
")": "/",
"*": "/",
"+": "/",
"-": "/",
".": "/",
"/": function(cmd, chunk) {
var targets = { "(": "G0",
")": "G1", "*": "G2", "+": "G3",
"-": "G1", ".": "G2", "/": "G3" };
if(chunk[2] === undefined)
return 0;
if(chunk[2] === "%" && chunk[3] === undefined)
return 0;
var charset = (chunk[2] === "0") ? "graphics" : "unicode";
this.state.selectCharset(charset, targets[chunk[1]]);
return (chunk[2] === "%") ? 4 : 3;
},
/**
* ESC #<br>
* 3 DEC line height/width
*/
"#": function(cmd, chunk) {
if(chunk[2] === undefined)
return 0;
var line = this.state.getLine();
switch(chunk[2]) {
case "3":
line.attr.doubleheight = "top";
break;
case "4":
line.attr.doubleheight = "bottom";
break;
case "5":
delete line.attr.doubleheight;
delete line.attr.doublewidth;
break;
case "6":
line.attr.doublewidth = true;
break;
}
this.state.setLine(line);
return 3;
},
/**
* ESC g<br>
* Visual Bell
*/
"g": function(cmd, chunk) {
this.emit("bell", true);
return 2;
},
/**
* ESC <<br>
* The terminal interprets all sequences according to ANSI standards X3.64-1979 and X3.41-1974.
* The VT52 escape sequences described in this chapter are not recognized.
* (DECANM)
*/
"<": function(cmd, chunk) {
return 2;
},
/**
* ESC ><br>
* (set numeric keypad mode?)
* Normal Keypad (DECPNM)
*/
">": function(cmd, chunk) {
this.state.setMode("appKeypad", false);
return 2;
},
/**
* ESC =<br>
* Application Keypad (DECPAM)
* Serial port requested application keyboard
*/
"=": function(cmd, chunk) {
this.state.setMode("appKeypad", true);
return 2;
}
};
module.exports = esc;
},{}],6:[function(require,module,exports){
"use strict";
/**
* handlers for Mode escape characters
* @enum {Function|string}
* @readonly
* @this refers to calling {@link Terminal}
*/
var mode = {
// "0": // Error this command is ignored
// Application Key Pad - Guarded Area Transmit Mode, send all (VT132) (GATM)
"1": function(cmd, value) {
this.state.setMode("appKeypad", value);
},
// "?1": // Cursor Keys Mode (DECCKM)
// "2": // Keyboard Action Mode , disable keyboard input (KAM)
// "?2": // ANSI Mode, use ESC < to switch VT52 to ANSI (DECANM)
// "3": , // Enable or disable control characters to be displayed
// "?3": genMode("132col"), // Column mode - 132 col (DECOLM)
// Insert/Replace Mode (IRM)
"4": function(cmd, value) {
this.state.setMode("insert", value);
},
// "?4": , // Scrolling Mode - Smooth (DECSCLM)
//"5": // Status Report Transfer Mode, report after DCS (STRM)
// Screen Mode - Reverse (DECSCNM)
"?5": function(cmd, value) {
this.state.setMode("reverse", value);
},
//"?6": genMode("relative"), // Origin Mode, line 1 is relative to scroll region (DECOM)
// Wraparound - On - Vertical Editing Mode (VEM)
"7": function(cmd, value) {
this.state.setMode("wrap", value);
},
//"?7": // AutoWrap Mode, start newline after column 80 (DECWAM)
//"8": // reserved
//"?8": // Auto Repeat Mode, key will autorepeat (DECARM)
//"9": // reserved
//"?9": genMode("interlace"), // INterLace Mode, interlaced for taking photos
//"10": // (HEM)
//"?10": // EDit Mode, VT132 is in EDIT mode (DECEDM)
//"11": // (PUM)
//"?11": // Line Transmit Mode, ignore TTM, send line (DECLTM)
//"12": // (SRM), // Local Echo: Send/Receive Mode
// Blink Cursor
"?12": function(cmd, value) {
this.state.setMode("cursorBlink", value);
},
//"13": // Format Effector Action Mode, FE"s are stored (FEAM)
//"?13": // Space Compression/Field Delimiting on (DECSCFDM)
//"14": // Format Effector Transfer Mode, send only if stored (FETM)
//"?14": // Transmit Execution Mode, transmit on ENTER (DECTEM)
//"15": // Multiple Area Transfer Mode, send all areas (MATM)
//"16": // Transmit Termination Mode, send scrolling region (TTM)
//"17": // Send Area Transmit Mode, send entire buffer (SATM)
//"18": // Tabulation Stop Mode, lines are independent (TSM)
//"?18": // Print FormFeed mode, send FF after printscreen (DECPFF) - Print Form Feed Mode
//"19": // Editing Boundry Mode, all of memory affected (EBM)
//"?19": // Printer Extent Mode (DECPEX) (DECPEXT)
// Automatic Linefeed Mode (LNM)
"20": function(cmd, value) {
this.state.setMode("crlf", value);
},
// "?20": // Overstrike, overlay characters on GIGI (OV1)
// "?21": // Local BASIC, GIGI to keyboard and screen (BA1)
// "?22": // Host BASIC, GIGI to host computer (BA2)
// "?23": // GIGI numeric keypad sends reprogrammable sequences (PK1)
// "?24": // Autohardcopy before erasing or rolling GIGI screen (AH1
// Visible Cursor (DECTCEM)
"?25": function(cmd, value) {
this.state.setMode("cursor", value);
},
// "34": // Normal Cursor visibility (DECRLM)
// "?35": // (DECHEBM) - Hebrew/N-A Keyboard Mapping
// "?36": // (DECHEM) - Hebrew Encoding Mode
// "?38": // (DECTEK)- TEKtronix mode graphics
// "?42": // (DECNRCM) - Enable operation in 7-bit or 8-bit character mode
"?47": function(cmd, value) {
this.state.switchBuffer(value);
},
// "?57": // (DECNAKB) - Greek/N-A Keyboard Mapping
// "?60": // (DECHCCM) - Page Cursor-Coupling Mode
// "?61": // (DECVCCM) - Vertical Cursor-Coupling Mode
// "?64": // (DECPCCM) - Page Cursor-Coupling Mode
// "?66": // (DECNKM) - Numeric Keypad Mode
// "?67": // (DECKBUM) - Typewriter or Data Processing Keys
// "?68": // (DECLRMM) (DECVSSM) - Left Right Margin Mode
// "?73": // (DECXRLMM)
// "?95": // (DECNCSM) - Set/Reset No Clearing Screen On Column Change
// "?96": // (DECRLCM) - Right-to-Left Copy
// "?97": // (DECCRTSM) - Set/Reset CRT Save Mode
// "?98": // (DECARSM) - Set/Reset Auto Resize Mode
// "?99": // (DECMCM) - Set/Reset Modem Control Mode
// "?100": // (DECAAM) - Set/Reset Auto Answerback Mode
// "?101": // (DECCANSM) - Conceal Answerback Message Mode
// "?102": // (DECNULM) - Set/Reset Ignoring Null Mode
// "?103": // (DECHDPXM) - Set/Reset Half-Duplex Mode
// "?104": // (DECESKM) - Enable Secondary Keyboard Language Mode
// "?106": // (DECOSNM)
// VT200 Mouse tracking
"?1000": function(cmd, value) {
this.state.setMode("mousebtn", value);
},
"?1002": function(cmd, value) {
this.state.setMode("mousemtn", value);
},
"?1006": function(cmd, value) {
this.state.setMode("mousesgr", value);
},
"?1047": function(cmd, value) {
this.state.switchBuffer(value);
},
"?1048": function(cmd, v) {
if(v)
this.state.saveCursor();
else
this.state.restoreCursor();
},
"?1049": function(cmd, v) {
this.callHandler("mode", "1048", v);
this.callHandler("mode", "1047", v);
if(v)
this.state.setCursor(0, 0);
}
};
module.exports = mode;
},{}],7:[function(require,module,exports){
"use strict";
function emitter(name) {
var args_ = arguments;
return function(cmd, arg) {
var args = Array.prototype.slice(args_, 1);
args.unshift(arg);
this.emit.apply(name, args);
};
}
function meta(name) {
return function(cmd, arg) {
this.state.setMeta(name, arg);
};
}
var specialColor = {
0: "bold",
1: "underline",
2: "blink",
3: "reverse"
};
/**
* handlers for OSC escape characters
* @enum {Function|string}
* @readonly
* @this refers to calling {@link Terminal}
*/
var osc = {
"": "0",
0: function(cmd, args) {
this.state.setMeta("title", args[0]);
this.state.setMeta("icon", args[0]);
},
1: meta("icon"),
2: meta("title"),
3: function() {},
4: function(cmd, arg) {
arg = arg.split(";");
this.emit("colorchange", arg[0], arg[1]);
},
5: function(cmd, arg) {
arg = arg.split(";");
this.emit("colorchange", specialColor[arg[0]], arg[1]);
},
10: emitter("colorchange", "fg"),
11: emitter("colorchange", "bg"),
12: emitter("colorchange", "cursor"),
13: emitter("colorchange", "mousefg"),
14: emitter("colorchange", "mousebg"),
15: emitter("colorchange", "tektronixfg"),
16: emitter("colorchange", "tektronixbg"),
17: emitter("colorchange", "highlightbg"),
18: emitter("colorchange", "tektronixhighlight"),
19: emitter("colorchange", "highlightfg"),
46: emitter("logfilechange"),
50: emitter("fontchange"),
51: emitter("emacs"),
// TODO: Manipulate Selection Data
52: function() {
},
104: function(cmd, arg) {
this.emit("colorreset", arg);
},
105: function(cmd, arg) {
this.emit("colorreset", specialColor[arg]);
},
110: emitter("colorreset", "fg"),
111: emitter("colorreset", "bg"),
112: emitter("colorreset", "cursor"),
113: emitter("colorreset", "mousefg"),
114: emitter("colorreset", "mousebg"),
115: emitter("colorreset", "tektronixfg"),
116: emitter("colorreset", "tektronixbg"),
117: emitter("colorreset", "highlightbg"),
118: emitter("colorreset", "tektronixhighlight"),
119: emitter("colorreset", "highlightfg"),
};
module.exports = osc;
},{}],8:[function(require,module,exports){
"use strict";
function attr(name, value) {
return function() {
this.state.setAttribute(name, value);
};
}
/**
* handlers for SGR escape characters
* @enum {Function|string}
* @readonly
* @this refers to calling {@link Terminal}
*/
var sgr = {
0: function(cmd) {
this.state.resetAttribute();
},
1: attr("bold", true), // Bold
2: function(cmd) {}, // Weight:feint
3: attr("italic", true), // Italic
4: attr("underline", true), // Underline
5: "6", // Slowly Blinking
6: attr("blink", true), //Rapidly Blinking
7: attr("inverse", true), // Inverse
8: function(cmd) {}, // Hidden
9: function(cmd) {}, // Strike Through
20: function(cmd) {}, // Style:fraktur
21: function(cmd) {}, // Double Underlined
22: attr("bold", false),
23: attr("italic", false),
24: attr("underline", false),
25: attr("blink", false),
27: attr("inverse", false),
30: "37", 31: "37", 32: "37", 33: "37", 34: "37", 35: "37", 36: "37",
37: function(cmd) {
this.state.setAttribute("fg", (+cmd) - 30);
},
38: function(cmd) {
// TODO 255 color support
},
39: function(cmd) {
this.state.resetAttribute("fg");
},
40: "47", 41: "47", 42: "47", 43: "47", 44: "47", 45: "47", 46: "47",
47: function(cmd) {
this.state.setAttribute("bg", (+cmd) - 40);
},
48: function(cmd) {
// TODO 255 color support
},
49: function(cmd) {
this.state.resetAttribute("bg");
},
51: function(cmd) { // Frame:box
},
52: function(cmd) { // Frame:circle
},
53: function(cmd) { // Overlined
},
90: "97", 91: "97", 92: "97", 93: "97", 94: "97", 95: "97", 96: "97",
97: function(cmd) {
this.state.setAttribute("fg", (+cmd) - 90 + 8);
},
100: "107", 101: "107", 102: "107", 103: "107", 104: "107", 105: "107", 106: "107",
107: function(cmd) {
this.state.setAttribute("bg", (+cmd) - 100 + 8);
}
};
module.exports = sgr;
},{}],9:[function(require,module,exports){
"use strict";
var stream = require("stream");
var util = require("util");
var myUtil = require("../util.js");
function BaseInput(target, buffer) {
BaseInput.super_.apply(this, arguments);
var opts = arguments[Math.max(1, arguments.length - 1)];
this.target = target;
this.buffer = buffer;
this._appKeypad = false;
var self = this;
this._opts = myUtil.extend({}, this._defOpts, opts);
}
util.inherits(BaseInput, stream.Readable);
BaseInput.prototype.getKey = function(key) {
var rv = this.buffer.getMode("appKeypad") ? "\x1bO" : "\x1b[";
switch(key) {
case "up":
rv += "A";
break;
case "down":
rv += "B";
break;
case "right":
rv += "C";
break;
case "left":
rv += "D";
break;
}
return rv;
};
BaseInput.prototype._read = function() {
};
module.exports = BaseInput;
},{"../util.js":24,"stream":54,"util":59}],10:[function(require,module,exports){
"use strict";
var myUtil = require("../util");
var inherits = require("util").inherits;
function DomInput(target, buffer, opts) {
DomInput.super_.apply(this, arguments);
target.tabIndex = 0;
this._addListener(this.target, "keypress", this._keypress);
this._addListener(this.target, "keydown", this._keydown);
this._addListener(this.target, "paste", this._paste);
this._addListener(this.target, "contextmenu", this._contextmenu);
this._addListener(this.target, "click", this._click);
this._addListener(this.target, "mousemove", this._mousemove);
}
inherits(DomInput, require("./base"));
module.exports = DomInput;
DomInput.prototype._addListener = function(elem, name, cb) {
var self = this;
var wrap = function(ev) {
ev = ev || window.event;
return cb.call(self, ev);
};
if(elem.addEventListener)
elem.addEventListener(name, wrap);
else
elem["on"+name] = wrap;
};
DomInput.prototype.getKeyCode = function(ev) {
if(!ev)
return;
else if(ev.charCode)
return ev.charCode;
else if(ev.which)
return ev.which;
else
return ev.keyCode;
};
DomInput.prototype._mousemove = function(ev) {
};
DomInput.prototype._click = function(ev) {
this.target.contentEditable=false;
};
DomInput.prototype._cancelEvent = function(ev) {
if(ev.stopPropagation) ev.stopPropagation();
if(ev.preventDefault) ev.preventDefault();
this.target.contentEditable=false;
return false;
};
DomInput.prototype._contextmenu = function(ev) {
var self = this;
this.target.contentEditable=true;
};
DomInput.prototype._paste = function(ev) {
this.push(ev.clipboardData.getData("text/plain"));
return this._cancelEvent(ev);
};
// Taken from tty.js: https://github.com/chjj/tty.js
DomInput.prototype._keypress = function(ev) {
var key = this.getKeyCode(ev);
if (!key || ev.ctrlKey || ev.altKey || ev.metaKey) return;
this.push(String.fromCharCode(key));
this.target.contentEditable=false;
return this._cancelEvent(ev);
};
// Taken from tty.js: https://github.com/chjj/tty.js
DomInput.prototype._keydown = function(ev) {
var key, keyCode = this.getKeyCode(ev);
if ((ev.ctrlKey && ev.shiftKey) || ev.metaKey) {
// do not catch ctrl+shift and meta key bindings.
return;
}
switch (keyCode) {
//backspace
case 8:
if (ev.shiftKey) {
key = "\x08"; //^H
break;
}
key = "\x7f"; //^?
break;
//tab
case 9:
if (ev.shiftKey) {
key = "\x1b[Z";
break;
}
key = "\t";
break;
//return /enter
case 13:
key = "\r";
break;
//escape
case 27:
key = "\x1b";
break;
//left - arrow
case 37:
key = this.getKey("left");
break;
//right - arrow
case 39:
key = this.getKey("right");
break;
//up - arrow
case 38:
key = this.getKey("up");
break;
//down - arrow
case 40:
key = this.getKey("down");
break;
//delete
case 46:
key = "\x1b[3~";
break;
//insert
case 45:
key = "\x1b[2~";
break;
//home
case 36:
key = "\x1bOH";
break;
//end
case 35:
key = "\x1bOF";
break;
//page up
case 33:
key = "\x1b[5~";
break;
//page down
case 34:
key = "\x1b[6~";
break;
//F1
case 112:
key = "\x1bOP";
break;
//F2
case 113:
key = "\x1bOQ";
break;
//F3
case 114:
key = "\x1bOR";
break;
//F4
case 115:
key = "\x1bOS";
break;
//F5
case 116:
key = "\x1b[15~";
break;
//F6
case 117:
key = "\x1b[17~";
break;
//F7
case 118:
key = "\x1b[18~";
break;
//F8
case 119:
key = "\x1b[19~";
break;
//F9
case 120:
key = "\x1b[20~";
break;
//F10
case 121:
key = "\x1b[21~";
break;
//F11
case 122:
key = "\x1b[23~";
break;
//F12
case 123:
key = "\x1b[24~";
break;
default:
//a - z and space
if (ev.ctrlKey) {
if (keyCode >= 65 && keyCode <= 90)
key = String.fromCharCode(keyCode - 64);
else if (keyCode === 32)
//NUL
key = String.fromCharCode(0);
else if (keyCode >= 51 && keyCode <= 55)
//escape, file sep, group sep, record sep, unit sep
key = String.fromCharCode(keyCode - 51 + 27);
else if (keyCode === 56)
//delete
key = String.fromCharCode(127);
else if (keyCode === 219)
//^[-escape
key = String.fromCharCode(27);
else if (keyCode === 221)
//^] - group sep
key = String.fromCharCode(29);
} else if (ev.altKey) {
if (keyCode >= 65 && keyCode <= 90)
key = "\x1b" + String.fromCharCode(keyCode + 32);
else if (keyCode === 192)
key = "\x1b`";
else if (keyCode >= 48 && keyCode <= 57)
key = "\x1b" + (keyCode - 48);
}
break;
}
if(key !== undefined) {
this.target.contentEditable=false;
this.push(key);
return this._cancelEvent(ev);
}
};
DomInput.canHandle = require("../output/dom.js").canHandle;
},{"../output/dom.js":14,"../util":24,"./base":9,"util":59}],11:[function(require,module,exports){
"use strict";
var myUtil = require("../util");
var inherits = require("util").inherits;
function TtyInput(target, buffer, opts) {
TtyInput.super_.apply(this, arguments);
var self = this;
if(this.target.stdout)
this.target = this.target.stdout;
this.target.on("readable", function() {
self.doread();
});
}
inherits(TtyInput, require("./base"));
module.exports = TtyInput;
var APP_KEYPAD_PATTERN = /\x1b\[([0-9;]*[ABCD])/g;
TtyInput.prototype.doread = function() {
var data = this.target.read().toString();
if(this.appKeypad)
data = data.replace(APP_KEYPAD_PATTERN, "\x1bO$1");
this.push(data);
};
TtyInput.canHandle = function(target) {
if(target.stdin)
target = target.stdin;
return typeof target === "object" && "read" in target && "on" in target && target.isTTY;
};
},{"../util":24,"./base":9,"util":59}],12:[function(require,module,exports){
"use strict";
var myUtil = require("../util");
var inherits = require("util").inherits;
function AnsiOutput(state, opts) {
AnsiOutput.super_.apply(this, arguments);
}
inherits(AnsiOutput, require("./base.js"));
module.exports = AnsiOutput;
AnsiOutput.prototype._mkSgr = function(attr, extra) {
var codes = "", cursor = extra && extra.$cursor;
codes += attr.bold === true ? ";1" : ";22";
codes += attr.italic === true ? ";3" : ";23";
codes += attr.underline === true ? ";4" : ";24";
codes += attr.blink === true ? ";5" : ";25";
codes += (attr.inverse === true || (cursor && attr.inverse !== true)) ?
";7" : ";27";
var fg = attr.fg;
var bg = attr.bg;
if (fg) {
if (fg < 8) codes += ";" + (+fg + 30);
else if (fg < 16) codes += ";" + (+fg + 90 - 8);
else codes += ";38;5;"+fg;
}
if (bg) {
if (bg < 7) codes += ";" + (+bg + 30);
else if (bg < 16) codes += ";" + (+bg + 100 - 8);
else codes += ";48;5;"+bg;
}
return "\x1b["+codes.substr(1)+"m";
};
AnsiOutput.prototype._renderLine = function(line, cursor) {
var i, start;
var output = "", attr;
var str = line.str;
if(line.attr[str.length].bg !== null)
str += myUtil.repeat(" ", this.state.colums - str.length);
else if(cursor !== undefined)
str += myUtil.repeat(" ", cursor + 1 - str.length);
for(i = 0; i < str.length;) {
start = i++;
if(start in line.attr)
attr = line.attr[start];
if(cursor !== start)
while(i < str.length && !(i in line.attr) && cursor !== i)
i++;
output += this._mkSgr(attr, { $cursor: cursor === start}) +
str.substring(start, i);
}
return output;
};
AnsiOutput.prototype.toString = function() {
var lines = "";
var c = this.state.cursor;
for(var i = 0; i < this.state.rows; i++) {
var line = this.state.getLine(i);
lines += "\n" + this._renderLine(line, c.y === i ? c.x : null);
}
return lines.substr(1) + "\x1b[0m";
};
AnsiOutput.canHandle = function(target) {
return target === "ansi";
};
},{"../util":24,"./base.js":13,"util":59}],13:[function(require,module,exports){
"use strict";
var myUtil = require("../util.js");
function BaseOutput(state) {
var opts = arguments[Math.max(1, arguments.length - 1)];
this.state = state;
this._opts = myUtil.extend({}, this._defOpts, opts);
}
module.exports = BaseOutput;
BaseOutput.prototype.toString = function() {
throw new Error("toString is not implemented!");
};
},{"../util.js":24}],14:[function(require,module,exports){
"use strict";
var myUtil = require("../util");
var inherits = require("util").inherits;
var HtmlOutput = require("./html.js");
function DomOutput(state, writer, target, opts) {
this.html = new HtmlOutput(state, opts);
target.innerHTML = "<div style='visibility:hidden;'></div>";
this.spacer = target.firstChild;
this.cursorView = null;
DomOutput.super_.apply(this, arguments);
this._opts.adhesiveCursor = true;
}
inherits(DomOutput, require("./live_base.js"));
module.exports = DomOutput;
DomOutput.prototype.createView = function() {
var e = this.target.ownerDocument.createElement("div");
e.style.overflow = "hidden";
return e;
};
DomOutput.prototype.removeLine = function(number, view) {
return this.target.removeChild(view);
};
DomOutput.prototype.changeLine = function(number, view, line, cursor) {
view.innerHTML = this.html._renderLine(line, cursor);
};
DomOutput.prototype.insertLine = function(number, view, line, cursor) {
view.innerHTML = this.html._renderLine(line, cursor);
this.target.insertBefore(view, this.target.childNodes[number]);
return view;
};
DomOutput.prototype.changeLed = function(l1, l2, l3, l4) {
};
DomOutput.prototype.setCursor = function(x, y) {
};
DomOutput.prototype.resize = function(size) {
this.target.lastChild.innerHTML = this.html._genColumnsString();
};
DomOutput.prototype.commit = function() {
var i;
var diff = this.state.rows - this.state.getBufferRowCount();
var html = myUtil.repeat("<br />", diff) +
"<div style='line-height:0'>" + myUtil.repeat(" ", this.state.columns) + "</div>";
this.spacer.innerHTML = html;
this.spacer.lineHeight = diff === 0 ? "0" : "inherit";
};
DomOutput.canHandle = function(target) {
// Test if target is some kind of DOM-Element
return target !== null && typeof target === "object" && "ownerDocument" in target;
};
},{"../util":24,"./html.js":15,"./live_base.js":16,"util":59}],15:[function(require,module,exports){
"use strict";
var myUtil = require("../util");
var inherits = require("util").inherits;
function HtmlOutput(state, opts) {
HtmlOutput.super_.apply(this, arguments);
}
inherits(HtmlOutput, require("./base"));
module.exports = HtmlOutput;
HtmlOutput.prototype._defOpts = {
cssClass: false,
cursorBg: "#00ff00",
cursorFg: "#ffffff",
};
// Taken from https://github.com/dtinth/headles-terminal/blob/master/vendor/term.js#L226
HtmlOutput.prototype.colors = [
// dark:
"#2e3436",
"#cc0000",
"#4e9a06",
"#c4a000",
"#3465a4",
"#75507b",
"#06989a",
"#d3d7cf",
// bright:
"#555753",
"#ef2929",
"#8ae234",
"#fce94f",
"#729fcf",
"#ad7fa8",
"#34e2e2",
"#eeeeec"
];
// Taken from https://github.com/chjj/tty.js/blob/master/static/term.js#L250
// Colors 16-255
// Thanks to TooTallNate for writing this.
HtmlOutput.prototype.colors = (function() {
var colors = HtmlOutput.prototype.colors,
r = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff], i;
function hex(c) {
c = c.toString(16);
return c.length < 2 ? "0" + c : c;
}
function out(r, g, b) {
colors.push("#" + hex(r) + hex(g) + hex(b));
}
// 16-231
i = 0;
for (; i < 216; i++) {
out(r[(i / 36) % 6 | 0], r[(i / 6) % 6 | 0], r[i % 6]);
}
// 232-255 (grey)
i = 0;
for (; i < 24; i++) {
r = 8 + i * 10;
out(r, r, r);
}
return colors;
})();
HtmlOutput.prototype._cssPrefix = function(css) {
return css + "-webkit-" + css + "-moz-" + css + "-ms-" + css;
};
HtmlOutput.prototype._mkCssProperties = function(attr) {
var css = "";
if(!attr)
return "";
if(attr.fg)
css += (attr.inverse ? "background" : "color") + ":" + this.colors[attr.fg] + ";";
if(attr.bg)
css += (attr.inverse ? "color" : "background") + ":" + this.colors[attr.bg] + ";";
if(attr.bold)
css += "font-weight:bold;";
if(attr.italic)
css += "font-style:italic;";
if(attr.underline || attr.blink)
css += "text-decoration:" + (attr.underline ? "underline " : "") + (attr.blink ? "blink;" : ";");
if(attr.doublewidth || attr.doubleheight) {
css += this._cssPrefix("transform:" + (attr.doublewidth ? "scaleX(2) " : "") +
(attr.doubleheight ? "scaleY(2);" : ";"));
css += this._cssPrefix("transform-origin:left " + (attr.doubleheight || "") + ";");
}
return css;
};
var PATTERN_LT = /</g;
var PATTERN_GT = />/g;
var PATTERN_SPACE = / /g;
HtmlOutput.prototype.escapeHtml = function(str) {
return str.replace(PATTERN_LT, "<").
replace(PATTERN_GT, ">").
replace(PATTERN_SPACE, " ");
};
HtmlOutput.prototype._mkAttr = function(attr, type, e) {
if(this._opts.cssClass) {
var classes = type || "";
var keys = Object.keys(attr);
for(var i = 0; i < keys.length; i++) {
if(attr[keys[i]] === true)
classes += " " + keys[i];
else if(attr[keys[i]] !== false && attr[keys[i]] !== null)
classes += " " + keys[i] + "_" + attr[keys[i]];
}
return "class='" + classes + "'";
}
var css = this._mkCssProperties(attr);
switch(type) {
case "cursor":
css += "background:" + this._opts.cursorBg + ";";
css += "color:" + this._opts.cursorFg + ";";
break;
case "line":
css += "overflow:hidden;white-space:nowrap;";
break;
}
if(css === "")
return "";
if(e)
e.setAttribute("style", css);
return "style='" + css + "'";
};
HtmlOutput.prototype._renderLine = function(line, cursor) {
var i, start;
var html = "", attr, css = "", htmlAttr, content;
var str = line.str;
if(line.attr[str.length].bg !== null)
str += myUtil.repeat(" ", this.state.columns - str.length);
else if(cursor !== undefined && cursor < this.state.columns)
str += myUtil.repeat(" ", cursor + 1 - str.length);
if(str.length === 0)
return "<br />";
for(i = 0; i < str.length;) {
css = "";
start = i++;
if(start in line.attr)
attr = line.attr[start];
if(cursor !== start)
while(i < str.length && !(i in line.attr) && cursor !== i)
i++;
htmlAttr = this._mkAttr(attr,
this.state.getMode("cursor") && cursor === start ? "cursor"
: undefined);
content = this.escapeHtml(str.substring(start, i));
if(htmlAttr !== "")
html += "<span " + htmlAttr + ">" + content + "</span>";
else
html += content;
}
return "<div "+ this._mkAttr(line.attr, "line") + ">" + html + "</div>";
};
HtmlOutput.prototype.toString = function() {
var i;
var lines = "";
for(i = 0; i < this.state.rows; i++) {
var line = this.state.getLine(i);
lines += "<div style='overflow:hidden'>" + this._renderLine(line) + "</div>";
}
return lines + "<div style='line-height:0;visibility:hidden;'>" +
this._genColumnsString() + "</div>";
};
HtmlOutput.prototype._genColumnsString = function() {
return myUtil.repeat(" ",this.state.columns);
};
HtmlOutput.canHandle = function(target) {
return target === "html";
};
},{"../util":24,"./base":13,"util":59}],16:[function(require,module,exports){
"use strict";
var inherits = require("util").inherits;
var dummy = function() {};
function LiveBaseOutput(state, writer, target, opts) {
LiveBaseOutput.super_.apply(this, arguments);
var i;
this.target = target;
this.writer = writer;
this._views = [];
this._oldViews = [];
this._cursorView = null;
this._cursorDrawnAt = null;
this._timeout = null;
this._queue = [];
var self = this;
state.on("lineremove",
function() { self._removeLine.apply(self, arguments); });
state.on("linechange",
function() { self._changeLine.apply(self, arguments); });
state.on("lineinsert",
function() { self._insertLine.apply(self, arguments); });
state.on("ledchange",
function() { self._changeLed.apply(self, arguments); });
state.on("cursormove",
function() { self._setCursor.apply(self, arguments); });
state.on("resize",
function() { self._resize.apply(self, arguments); });
state.on("bell",
function() { self._bell.apply(self, arguments); });
writer.on("ready",
function() { self._checkCommit(); });
}
inherits(LiveBaseOutput, require("./base"));
module.exports = LiveBaseOutput;
LiveBaseOutput.prototype._schedule = function(view, cb) {
var i;
for(i = 0; i < this._queue.length; i++) {
if(this._queue[i].view !== view)
continue;
this._queue[i].cb = cb;
return;
}
this._queue.unshift({ view: view, cb: cb });
};
LiveBaseOutput.prototype._flush = function(flush) {
var i;
for(i = 0; i < this._queue.length; i++) {
this._queue[i].cb.call(this, this._queue[i].view);
}
this._queue = [];
};
LiveBaseOutput.prototype._updateCursor = function(action, number) {
if(!this._opts.adhesiveCursor || this._cursorDrawnAt === null)
return;
switch(action) {
case "insert":
if(number <= this._cursorDrawnAt)
this._cursorDrawnAt = Math.min(this._cursorDrawnAt + 1, this.state.rows - 1);
break;
case "remove":
if(number < this._cursorDrawnAt)
this._cursorDrawnAt--;
else if(number === this._cursorDrawnAt)
this._cursorDrawnAt = null;
break;
}
};
LiveBaseOutput.prototype._removeLine = function(number) {
var viewContainer = this._views.splice(number, 1)[0];
var view = this.removeLine(number, viewContainer.view);
if(view) {
viewContainer.view = view;
this._oldViews.push(viewContainer);
}
this._updateCursor("remove", number);
};
LiveBaseOutput.prototype._changeLine = function(number, line, cursor) {
if(!this.state.getMode("cursor"))
cursor = undefined;
this._schedule(this._views[number], function(viewContainer) {
var view = this.changeLine(number, viewContainer.view, line, cursor);
if(view !== undefined)
viewContainer.view = view;
if(cursor !== undefined)
this._cursorDrawnAt = number;
});
};
LiveBaseOutput.prototype._insertLine = function(number, line, cursor) {
var viewContainer = this._oldViews.shift() || {view: this.createView() };
var view = this.insertLine(
number,
viewContainer.view,
line, cursor);
if(view !== undefined)
viewContainer.view = view;
this._views.splice(number, 0, viewContainer);
this._updateCursor("insert", number);
};
LiveBaseOutput.prototype._changeLed = function() {
this.changeLed.apply(this, arguments);
};
LiveBaseOutput.prototype._setCursor = function(x, y) {
this._cursorView = this.setCursor(x, y);
};
LiveBaseOutput.prototype._resize = function(size) {
this._flush();
this.resize(size);
};
LiveBaseOutput.prototype._checkCommit = function() {
var self = this, args = arguments;
if (!this._opts.renderInterval)
return this._commit.apply(this, args);
if (this._timeout !== null)
return;
this._timeout = setTimeout(function() {
self._commit.apply(self, args);
self._timeout = null;
}, this._opts._renderInterval);
};
LiveBaseOutput.prototype._commit = function() {
var c = this.state.cursor;
if(c.y !== this._cursorDrawnAt && this._cursorDrawnAt !== null) {
this._changeLine(this._cursorDrawnAt, this.state.getLine(this._cursorDrawnAt));
}
if(c.y < this._views.length) {
this._changeLine(c.y, this.state.getLine(c.y), c.x);
}
this._flush();
this.commit.apply(this, arguments);
};
LiveBaseOutput.prototype._bell = function() {
this.bell.apply(this, arguments);
};
LiveBaseOutput.prototype.createView =
LiveBaseOutput.proto