UNPKG

terminal.js

Version:

terminal emulation library for javascript.

2,181 lines (1,919 loc) 296 kB
(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 &lt;<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 &gt;<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("&nbsp;", 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, "&lt;"). replace(PATTERN_GT, "&gt;"). replace(PATTERN_SPACE, "&nbsp;"); }; 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("&nbsp;",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