diff --git a/README.md b/README.md index 5470bf1..494d7af 100644 --- a/README.md +++ b/README.md @@ -277,7 +277,7 @@ The base element. - **bold, underline** - border attributes. - **style** - contains attributes (e.g. `fg/bg/underline`). see above. - **position** - raw width, height, and offsets. -- **content** - text content. +- **content** - raw text content. - **hidden** - whether the element is hidden or not. - **visible** - whether the element is visible or not. - **detached** - whether the element is attached to a screen in its ancestry @@ -313,7 +313,6 @@ The base element. - inherits all from Node. - **render()** - write content and children to the screen buffer. -- **setContent(text)** - set the content. - **hide()** - hide element. - **show()** - show element. - **toggle()** - toggle hidden/shown. @@ -325,6 +324,42 @@ The base element. - **onScreenEvent(type, listener)** - same as`el.on('screen', ...)` except this will automatically cleanup listeners after the element is detached. +###### Content Methods + +Methods for dealing with text content, line by line. Useful for writing a +text editor, irc client, etc. + +Note: all of these methods deal with pre-aligned, pre-wrapped text. If you use +deleteTop() on a box with a wrapped line at the top, it may remove 3-4 "real" +lines (rows) depending on how long the original line was. + +The `lines` parameter can be a string or an array of strings. The `line` +parameter must be a string. + +- **setContent(text)** - set the content. note: when text is input, it will be + stripped of all non-SGR escape codes, tabs will be replaced with 8 spaces, + and tags will be replaced with SGR codes (if enabled). +- **getContent(text)** - return content, slightly different from `el.content`. + assume the above formatting. +- **insertLine(i, lines)** - insert a line into the box's content. +- **deleteLine(i)** - delete a line from the box's content. +- **getLine(i)** - get a line from the box's content. +- **getBaseLine(i)** - get a line from the box's content from the visible top. +- **setLine(i, line)** - set a line in the box's content. +- **setBaseLine(i, line)** - set a line in the box's content from the visible + top. +- **clearLine(i)** - clear a line from the box's content. +- **clearBaseLine(i)** - clear a line from the box's content from the visible + top. +- **insertTop(lines)** - insert a line at the top of the box. +- **insertBottom(lines)** - insert a line at the bottom of the box. +- **deleteTop()** - delete a line at the top of the box. +- **deleteBottom()** - delete a line at the bottom of the box. +- **unshiftLine(lines)** - unshift a line onto the top of the content. +- **shiftLine(i)** - shift a line off the top of the content. +- **pushLine(lines)** - push a line onto the bottom of the content. +- **popLine(i)** - pop a line off the top of the content. + #### Box (from Element) @@ -345,15 +380,6 @@ A box element which draws a simple box containing `content` or other elements. ##### Methods: - inherits all from Element. -- **insertLine(i, line)** - insert a line into the box's content. -- **deleteLine(i)** - delete a line from the box's content. -- **getLine(i)** - get a line from the box's content. -- **setLine(i, line)** - set a line in the box's content. -- **clearLine(i)** - clear a line from the box's content. -- **insertTop(line)** - insert a line at the top of the box. -- **insertBottom(line)** - insert a line at the bottom of the box. -- **deleteTop()** - delete a line at the top of the box. -- **deleteBottom()** - delete a line at the bottom of the box. #### Text (from Element) diff --git a/lib/widget.js b/lib/widget.js index 3f151fc..8622443 100644 --- a/lib/widget.js +++ b/lib/widget.js @@ -1836,6 +1836,10 @@ Element.prototype.setContent = function(content, noClear) { this.parseContent(); }; +Element.prototype.getContent = function() { + return this._clines.fake.join('\n'); +}; + Element.prototype.parseContent = function() { if (this.detached) return false; @@ -2472,22 +2476,10 @@ Element.prototype.__defineGetter__('tpadding', function() { }); /** - * Box + * Rendering */ -function Box(options) { - if (!(this instanceof Box)) { - return new Box(options); - } - options = options || {}; - Element.call(this, options); -} - -Box.prototype.__proto__ = Element.prototype; - -Box.prototype.type = 'box'; - -Box.prototype._getShrinkSize = function() { +Element.prototype._getShrinkSize = function() { // TODO: Possibly move this to parseContent. return { height: this._clines.length, @@ -2500,7 +2492,7 @@ Box.prototype._getShrinkSize = function() { }; }; -Box.prototype._getShrinkBox = function(xi, xl, yi, yl) { +Element.prototype._getShrinkBox = function(xi, xl, yi, yl) { if (!this.children.length) { return { xi: xi, xl: xi, yi: yi, yl: yi }; } @@ -2547,7 +2539,7 @@ Box.prototype._getShrinkBox = function(xi, xl, yi, yl) { return { xi: xi, xl: xl, yi: yi, yl: yl }; }; -Box.prototype._getShrinkContent = function(xi, xl, yi, yl) { +Element.prototype._getShrinkContent = function(xi, xl, yi, yl) { var hw = this._getShrinkSize() , h = hw.height , w = hw.width; @@ -2576,7 +2568,7 @@ Box.prototype._getShrinkContent = function(xi, xl, yi, yl) { return { xi: xi, xl: xl, yi: yi, yl: yl }; }; -Box.prototype._getShrink = function(xi, xl, yi, yl) { +Element.prototype._getShrink = function(xi, xl, yi, yl) { var shrinkBox = this._getShrinkBox(xi, xl, yi, yl) , shrinkContent = this._getShrinkContent(xi, xl, yi, yl) , xll = xl @@ -2615,7 +2607,7 @@ Box.prototype._getShrink = function(xi, xl, yi, yl) { return { xi: xi, xl: xl, yi: yi, yl: yl }; }; -Box.prototype._getCoords = function(get) { +Element.prototype._getCoords = function(get) { if (this.hidden) return; var xi = this._getLeft(get) @@ -2697,7 +2689,7 @@ Box.prototype._getCoords = function(get) { }; // Here be dragons. -Box.prototype.render = function() { +Element.prototype.render = function() { this.parseContent(); var coords = this._getCoords(true); @@ -2924,8 +2916,8 @@ Box.prototype.render = function() { return coords; }; -Box.prototype.insertLine = function(i, line) { - if (typeof line === 'string') line = [line]; +Element.prototype.insertLine = function(i, line) { + if (typeof line === 'string') line = line.split('\n'); if (i !== i || i == null) { i = this._clines.ftor.length; @@ -2977,7 +2969,7 @@ Box.prototype.insertLine = function(i, line) { } }; -Box.prototype.deleteLine = function(i, n) { +Element.prototype.deleteLine = function(i, n) { n = n || 1; if (i !== i || i == null) { @@ -3022,12 +3014,12 @@ Box.prototype.deleteLine = function(i, n) { } }; -Box.prototype.insertTop = function(line) { +Element.prototype.insertTop = function(line) { var fake = this._clines.rtof[this.childBase || 0]; return this.insertLine(fake, line); }; -Box.prototype.insertBottom = function(line) { +Element.prototype.insertBottom = function(line) { var h = (this.childBase || 0) + this.height - this.iheight , i = Math.min(h, this._clines.length) , fake = this._clines.rtof[i - 1] + 1; @@ -3035,12 +3027,12 @@ Box.prototype.insertBottom = function(line) { return this.insertLine(fake, line); }; -Box.prototype.deleteTop = function(n) { +Element.prototype.deleteTop = function(n) { var fake = this._clines.rtof[this.childBase || 0]; return this.deleteLine(fake, n); }; -Box.prototype.deleteBottom = function(n) { +Element.prototype.deleteBottom = function(n) { var h = (this.childBase || 0) + this.height - 1 - this.iheight , i = Math.min(h, this._clines.length - 1) , n = n || 1 @@ -3049,7 +3041,7 @@ Box.prototype.deleteBottom = function(n) { return this.deleteLine(fake - (n - 1), n); }; -Box.prototype.setLine = function(i, line) { +Element.prototype.setLine = function(i, line) { i = Math.max(i, 0); while (this._clines.fake.length < i) { this._clines.fake.push(''); @@ -3058,43 +3050,64 @@ Box.prototype.setLine = function(i, line) { return this.setContent(this._clines.fake.join('\n'), true); }; -Box.prototype.setBaseLine = function(i, line) { +Element.prototype.setBaseLine = function(i, line) { var fake = this._clines.rtof[this.childBase || 0]; return this.setLine(fake + i, line); }; -Box.prototype.getLine = function(i) { +Element.prototype.getLine = function(i) { i = Math.max(i, 0); i = Math.min(i, this._clines.fake.length - 1); return this._clines.fake[i]; }; -Box.prototype.getBaseLine = function(i) { +Element.prototype.getBaseLine = function(i) { var fake = this._clines.rtof[this.childBase || 0]; return this.getLine(fake + i); }; -Box.prototype.clearLine = function(i) { +Element.prototype.clearLine = function(i) { i = Math.min(i, this._clines.fake.length - 1); return this.setLine(i, ''); }; -Box.prototype.unshiftLine = function(line) { +Element.prototype.clearBaseLine = function(i) { + var fake = this._clines.rtof[this.childBase || 0]; + return this.clearLine(fake + i); +}; + +Element.prototype.unshiftLine = function(line) { return this.insertLine(0, line); }; -Box.prototype.shiftLine = function(n) { +Element.prototype.shiftLine = function(n) { return this.deleteLine(0, n); }; -Box.prototype.pushLine = function(line) { +Element.prototype.pushLine = function(line) { return this.insertLine(this._clines.fake.length, line); }; -Box.prototype.popLine = function(n) { +Element.prototype.popLine = function(n) { return this.deleteLine(this._clines.fake.length - 1, n); }; +/** + * Box + */ + +function Box(options) { + if (!(this instanceof Box)) { + return new Box(options); + } + options = options || {}; + Element.call(this, options); +} + +Box.prototype.__proto__ = Element.prototype; + +Box.prototype.type = 'box'; + /** * Text */ @@ -3105,10 +3118,12 @@ function Text(options) { } options = options || {}; options.shrink = true; - Box.call(this, options); + Element.call(this, options); } -Text.prototype.__proto__ = Box.prototype; +Text.prototype.__proto__ = Element.prototype; + +Text.prototype.type = 'text'; /** * Line