From 77695f994ac5c3fb9ebed6ad7e91a5cfd45be8f2 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Sat, 21 Feb 2015 02:49:15 -0800 Subject: [PATCH] add noAlt option. fix list shrinking. --- README.md | 4 +++ lib/program.js | 26 ++++++++++++++++-- lib/widget.js | 65 ++++++++++++++++++++++++++++++++++++++++++-- test/widget-noalt.js | 48 ++++++++++++++++++++++++++++++++ 4 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 test/widget-noalt.js diff --git a/README.md b/README.md index c72e5ea..c3b5204 100644 --- a/README.md +++ b/README.md @@ -180,6 +180,10 @@ The screen on which every other node renders. - **tabSize** - the width of tabs within an element's content. - **autoPadding** - automatically position child elements with border and padding in mind. +- **noAlt** - do not clear the screen, only scroll down enough to make room for + the elements on the screen. do not use the alternate screenbuffer. useful for + writing a CLI tool or some kind of prompt (experimental - see + test/widget-noalt.js). - **log** - create a log file. see `log` method. - **dump** - dump all output and input to desired file. can be used together with `log` option if set as a boolean. diff --git a/lib/program.js b/lib/program.js index 7cc1c18..300151b 100644 --- a/lib/program.js +++ b/lib/program.js @@ -2453,7 +2453,29 @@ Program.prototype.deviceStatus = function(param, callback, dec) { }; Program.prototype.getCursor = function(callback) { - return this.deviceStatus('6', callback); + return this.deviceStatus(6, callback); +}; + +Program.prototype.saveReportedCursor = function(callback) { + var self = this; + if (this.tput.strings.user7 === '\x1b[6n' || this.term('screen')) { + return this.getCursor(function(err, data) { + if (data) { + self._rx = data.status.x; + self._ry = data.status.y; + } + if (!callback) return; + return callback(err); + }); + } + if (!callback) return; + return callback(); +}; + +Program.prototype.restoreReportedCursor = function() { + if (this._rx == null) return; + return this.cup(this._ry, this._rx); + // return this.nel(); }; /** @@ -3531,7 +3553,7 @@ Program.prototype.manipulateWindow = function() { }; Program.prototype.getWindowSize = function(callback) { - return this.manipulateWindow('18', callback); + return this.manipulateWindow(18, callback); }; // CSI Pt; Pl; Pb; Pr; Ps$ t diff --git a/lib/widget.js b/lib/widget.js index 70899e8..42e96fa 100644 --- a/lib/widget.js +++ b/lib/widget.js @@ -423,6 +423,22 @@ Screen.prototype.__defineSetter__('title', function(title) { }); Screen.prototype.enter = function() { + if (this.options.noAlt) { + if (this._entered) return; + this._entered = true; + var self = this; + this.program.saveReportedCursor(); + this.program.hideCursor(); + this.program.cup(0, 0); + this.program.csr(0, this.height - 1); + this.alloc(); + var log = console.log; + console.log = function() { + self.leave(); + return log.apply(console, arguments); + }; + return; + } if (this.program.isAlt) return; this.program.alternateBuffer(); this.program.hideCursor(); @@ -432,6 +448,22 @@ Screen.prototype.enter = function() { }; Screen.prototype.leave = function() { + if (this.options.noAlt) { + if (this._left) return; + this._left = true; + if (this.program.scrollTop !== 0 + || this.program.scrollBottom !== this.rows - 1) { + this.program.csr(0, this.height - 1); + } + this.program.restoreReportedCursor(); + this.program.nel(); + this.program.showCursor(); + if (this._listenedMouse) { + this.program.disableMouse(); + } + this.program.flush(); + return; + } if (!this.program.isAlt) return; if (this.program.scrollTop !== 0 || this.program.scrollBottom !== this.rows - 1) { @@ -636,6 +668,27 @@ Screen.prototype.alloc = function() { } } + if (this.options.noAlt) { + var self = this; + var draw = self.draw; + this.draw = function() {}; + return this.once('render', function() { + var top = -1; + self.forDescendants(function(el) { + if (!el.lpos) return; + if (top === -1 || el.lpos.yi < top) { + top = el.lpos.yi; + } + }); + self.draw = draw; + if (top !== -1) { + top = self.program.rows - top; + self.program.output.write(Array(top + 1).join('\n')); + } + self.render(); + }); + } + this.program.clear(); }; @@ -3057,7 +3110,14 @@ Element.prototype._getShrinkBox = function(xi, xl, yi, yl, get) { if (this.position.height == null && (this.position.top == null || this.position.bottom == null) - && !this.scrollable) { + && (!this.scrollable || this._isList)) { + // NOTE: Lists get special treatment if they are shrunken - assume they + // want all list items showing. This is one case we can calculate the + // height based on items/boxes. + if (this._isList) { + myi = 0 - this.itop; + myl = this.items.length + this.ibottom; + } if (this.position.top == null && this.position.bottom != null) { yi = yl - (myl - myi); if (!this.screen.autoPadding) { @@ -3097,7 +3157,8 @@ Element.prototype._getShrinkContent = function(xi, xl, yi, yl, get) { if (this.position.height == null && (this.position.top == null || this.position.bottom == null) - && !this.scrollable) { + // && !this.scrollable) { + && (!this.scrollable || this._isList)) { if (this.position.top == null && this.position.bottom != null) { yi = yl - h - this.iheight; } else { diff --git a/test/widget-noalt.js b/test/widget-noalt.js new file mode 100644 index 0000000..14bb264 --- /dev/null +++ b/test/widget-noalt.js @@ -0,0 +1,48 @@ +var blessed = require('../') + , screen; + +screen = blessed.screen({ + dump: __dirname + '/logs/noalt.log', + title: 'widget-noalt test', + noAlt: true +}); + +var list = blessed.list({ + parent: screen, + align: 'center', + mouse: true, + keys: true, + vi: true, + width: '50%', + height: 'shrink', + //border: 'line', + bottom: 2, + left: 0, + style: { + fg: 'blue', + bg: 'default', + selected: { + bg: 'green' + } + }, + items: [ + 'one', + 'two', + 'three' + ] +}); + +list.select(0); + +list.on('select', function(item) { + console.log(item.getText()); + process.exit(0); +}); + +screen.key('C-c', function() { + process.exit(0); +}); + +list.focus(); + +screen.render();