diff --git a/README.md b/README.md index 8162e94..74506d4 100644 --- a/README.md +++ b/README.md @@ -377,6 +377,9 @@ The screen on which every other node renders. - __cursorColor(color)__ - attempt to change cursor color. returns true if successful. - __cursorReset()__ - attempt to reset cursor. returns true if successful. +- __screenshot([xi, xl, yi, yl])__ - take an SGR screenshot of the screen + within the region. returns a string containing only characters and SGR codes. + can be displayed by simply echoing it in a terminal. #### Element (from Node) @@ -512,6 +515,9 @@ The base element. - __enableInput()__ - enable key and mouse events. calls bot enableMouse and enableKeys. - __enableDrag()__ - enable dragging of the element. - __disableDrag()__ - disable dragging of the element. +- __screenshot([xi, xl, yi, yl])__ - take an SGR screenshot of the element + within the region. returns a string containing only characters and SGR codes. + can be displayed by simply echoing it in a terminal. ###### Content Methods @@ -1252,6 +1258,9 @@ manager. Requires term.js and pty.js to be installed. See - inherits all from Box. - __write(data)__ - write data to the terminal. +- __screenshot([xi, xl, yi, xl])__ - nearly identical to `element.screenshot`, + however, the specified region includes the terminal's _entire_ scrollback, + rather than just what is visible on the screen. - Other methods similar to ScrollableBox. diff --git a/example/ansi-viewer/index.js b/example/ansi-viewer/index.js index ee3da0d..dd1ebd4 100644 --- a/example/ansi-viewer/index.js +++ b/example/ansi-viewer/index.js @@ -227,173 +227,3 @@ function cp437ToUtf8(buf, callback) { return callback(e); } } - -blessed.Element.prototype.screenshot = function(xi, xl, yi, yl) { - xi = this.lpos.xi + this.ileft + (xi || 0); - if (xl != null) { - xl = this.lpos.xi + this.ileft + (xl || 0); - } else { - xl = this.lpos.xl - this.iright; - } - yi = this.lpos.yi + this.itop + (yi || 0); - if (yl != null) { - yl = this.lpos.yi + this.itop + (yl || 0); - } else { - yl = this.lpos.yl - this.ibottom; - } - return this.screen.screenshot(xi, xl, yi, yl); -}; - -blessed.Terminal.prototype.screenshot = function(xi, xl, yi, yl) { - xi = 0 + (xi || 0); - if (xl != null) { - xl = 0 + (xl || 0); - } else { - xl = this.term.lines[0].length; - } - yi = 0 + (yi || 0); - if (yl != null) { - yl = 0 + (yl || 0); - } else { - yl = this.term.lines.length; - } - return this.screen.screenshot(xi, xl, yi, yl, this.term); -}; - -blessed.Screen.prototype.screenshot = function(xi, xl, yi, yl, term) { - if (xi == null) xi = 0; - if (xl == null) xl = this.lpos.xl; - if (yi == null) yi = 0; - if (yl == null) yl = this.lpos.yl; - - var x - , y - , line - , out - , ch - , data - , attr - , cwid - , point; - - var sdattr = this.dattr; - if (term) { - this.dattr = term.defAttr; - // default foreground = 257 - if (((this.dattr >> 9) & 0x1ff) === 257) { - this.dattr &= ~(0x1ff << 9); - this.dattr |= ((sdattr >> 9) & 0x1ff) << 9; - } - // default background = 256 - if ((this.dattr & 0x1ff) === 256) { - this.dattr &= ~0x1ff; - this.dattr |= sdattr & 0x1ff; - } - } - - var main = ''; - - var acs; - - for (y = yi; y < yl; y++) { - line = term - ? term.lines[y] - : this.lines[y]; - - if (!line) break; - - out = ''; - attr = this.dattr; - - for (x = xi; x < xl; x++) { - if (!line[x]) break; - - data = line[x][0]; - ch = line[x][1]; - - if (term) { - // default foreground = 257 - if (((data >> 9) & 0x1ff) === 257) { - data &= ~(0x1ff << 9); - data |= ((sdattr >> 9) & 0x1ff) << 9; - } - // default background = 256 - if ((data & 0x1ff) === 256) { - data &= ~0x1ff; - data |= sdattr & 0x1ff; - } - } - - if (data !== attr) { - if (attr !== this.dattr) { - out += '\x1b[m'; - } - if (data !== this.dattr) { - out += screen.codeAttr(data); - } - } - - if (this.fullUnicode) { - point = blessed.unicode.codePointAt(line[x][1], 0); - if (point <= 0x00ffff) { - cwid = blessed.unicode.charWidth(point); - if (cwid === 2) { - if (x === xl - 1) { - ch = ' '; - } else { - x++; - } - } - } - } - - /* - if (this.tput.strings.enter_alt_charset_mode - && !this.tput.brokenACS && (this.tput.acscr[ch] || acs)) { - if (this.tput.acscr[ch]) { - if (acs) { - ch = this.tput.acscr[ch]; - } else { - ch = this.tput.smacs() - + this.tput.acscr[ch]; - acs = true; - } - } else if (acs) { - ch = this.tput.rmacs() + ch; - acs = false; - } - } else { - if (!this.tput.unicode && this.tput.numbers.U8 !== 1 && ch > '~') { - ch = this.tput.utoa[ch] || '?'; - } - } - */ - - out += ch; - attr = data; - } - - if (attr !== this.dattr) { - out += '\x1b[m'; - } - - if (out) { - main += (y > 0 ? '\n' : '') + out; - } - } - - /* - if (acs) { - main += this.tput.rmacs(); - acs = false; - } - */ - - main = main.replace(/(?:\s*\x1b\[40m\s*\x1b\[m\s*)*$/, '') + '\n'; - - if (term) { - this.dattr = sdattr; - } - - return main; -}; diff --git a/lib/widget.js b/lib/widget.js index a5360a0..32e2e1f 100644 --- a/lib/widget.js +++ b/lib/widget.js @@ -2020,6 +2020,140 @@ Screen.prototype._cursorAttr = function(cursor, dattr) { }; }; +Screen.prototype.screenshot = function(xi, xl, yi, yl, term) { + if (xi == null) xi = 0; + if (xl == null) xl = this.lpos.xl; + if (yi == null) yi = 0; + if (yl == null) yl = this.lpos.yl; + + var x + , y + , line + , out + , ch + , data + , attr + , cwid + , point; + + var sdattr = this.dattr; + if (term) { + this.dattr = term.defAttr; + // default foreground = 257 + if (((this.dattr >> 9) & 0x1ff) === 257) { + this.dattr &= ~(0x1ff << 9); + this.dattr |= ((sdattr >> 9) & 0x1ff) << 9; + } + // default background = 256 + if ((this.dattr & 0x1ff) === 256) { + this.dattr &= ~0x1ff; + this.dattr |= sdattr & 0x1ff; + } + } + + var main = ''; + + // var acs; + + for (y = yi; y < yl; y++) { + line = term + ? term.lines[y] + : this.lines[y]; + + if (!line) break; + + out = ''; + attr = this.dattr; + + for (x = xi; x < xl; x++) { + if (!line[x]) break; + + data = line[x][0]; + ch = line[x][1]; + + if (term) { + // default foreground = 257 + if (((data >> 9) & 0x1ff) === 257) { + data &= ~(0x1ff << 9); + data |= ((sdattr >> 9) & 0x1ff) << 9; + } + // default background = 256 + if ((data & 0x1ff) === 256) { + data &= ~0x1ff; + data |= sdattr & 0x1ff; + } + } + + if (data !== attr) { + if (attr !== this.dattr) { + out += '\x1b[m'; + } + if (data !== this.dattr) { + out += this.codeAttr(data); + } + } + + if (this.fullUnicode) { + point = unicode.codePointAt(line[x][1], 0); + if (point <= 0x00ffff) { + cwid = unicode.charWidth(point); + if (cwid === 2) { + if (x === xl - 1) { + ch = ' '; + } else { + x++; + } + } + } + } + + // if (this.tput.strings.enter_alt_charset_mode + // && !this.tput.brokenACS && (this.tput.acscr[ch] || acs)) { + // if (this.tput.acscr[ch]) { + // if (acs) { + // ch = this.tput.acscr[ch]; + // } else { + // ch = this.tput.smacs() + // + this.tput.acscr[ch]; + // acs = true; + // } + // } else if (acs) { + // ch = this.tput.rmacs() + ch; + // acs = false; + // } + // } else { + // if (!this.tput.unicode && this.tput.numbers.U8 !== 1 && ch > '~') { + // ch = this.tput.utoa[ch] || '?'; + // } + // } + + out += ch; + attr = data; + } + + if (attr !== this.dattr) { + out += '\x1b[m'; + } + + if (out) { + main += (y > 0 ? '\n' : '') + out; + } + } + + // if (acs) { + // main += this.tput.rmacs(); + // acs = false; + // } + + main = main.replace(/(?:\s*\x1b\[40m\s*\x1b\[m\s*)*$/, '') + '\n'; + + if (term) { + this.dattr = sdattr; + } + + return main; +}; + /** * Element */ @@ -4552,6 +4686,22 @@ Element.prototype.getScreenLines = function() { return this._clines.slice(); }; +Element.prototype.screenshot = function(xi, xl, yi, yl) { + xi = this.lpos.xi + this.ileft + (xi || 0); + if (xl != null) { + xl = this.lpos.xi + this.ileft + (xl || 0); + } else { + xl = this.lpos.xl - this.iright; + } + yi = this.lpos.yi + this.itop + (yi || 0); + if (yl != null) { + yl = this.lpos.yi + this.itop + (yl || 0); + } else { + yl = this.lpos.yl - this.ibottom; + } + return this.screen.screenshot(xi, xl, yi, yl); +}; + /** * Box */ @@ -8278,6 +8428,22 @@ Terminal.prototype.setScrollPerc = function(i) { return this.setScroll((i / 100) * this.term.ybase | 0); }; +Terminal.prototype.screenshot = function(xi, xl, yi, yl) { + xi = 0 + (xi || 0); + if (xl != null) { + xl = 0 + (xl || 0); + } else { + xl = this.term.lines[0].length; + } + yi = 0 + (yi || 0); + if (yl != null) { + yl = 0 + (yl || 0); + } else { + yl = this.term.lines.length; + } + return this.screen.screenshot(xi, xl, yi, yl, this.term); +}; + /** * Image * Good example of w3mimgdisplay commands: