diff --git a/README.md b/README.md index 4318987..7f86659 100644 --- a/README.md +++ b/README.md @@ -77,10 +77,9 @@ perfectly centered horizontally and vertically. ``` js var blessed = require('blessed') - , program = blessed() - , screen = new blessed.Screen({ program: program }); + , screen = new blessed.Screen; -screen.append(new blessed.Box({ +var box = new blessed.Box({ top: 'center', left: 'center', width: '50%', @@ -92,7 +91,14 @@ screen.append(new blessed.Box({ fg: 'white', bg: 'magenta', content: 'Hello world!', -})); + tags: true +}); + +screen.append(box); + +box.on('click', function(data) { + box.setContent('{center}Some different {red-fg}content{/red-fg}.{/center}'); +}); screen.on('keypress', function(ch, key) { if (key.name === 'escape') { @@ -515,6 +521,44 @@ console.log(box.top); This still needs to be tested a bit, but it should work. +### Content + +Every element can have text content via `setContent`. If `tags: true` was +passed to the element's constructor, the content can contain tags. For example: + +``` +box.setContent('hello {red-fg}{green-bg}{bold}world{/bold}{/green-bg}{/red-fg}'); +``` + +To make this more concise `{/}` cancels all character attributes. + +``` +box.setContent('hello {red-fg}{green-bg}{bold}world{/}'); +``` + +Newlines and alignment are also possible in content. + +``` +box.setContent('hello\n' + + '{right}world{/right}\n' + + '{center}foo{/center}'); +``` + +This will produce a box that looks like: + +``` +| hello | +| world | +| foo | +``` + +Content can also handle SGR escape codes. This means if you got output from a +program, say `git log` for example, you can feed it directly to an element's +content and the colors will be parsed appropriately. + +This means that while `{red-fg}foo{/red-fg}` produces `^[[31mfoo^[[39m`, you +could just feed `^[[31mfoo^[[39m` directly to the content. + ### Rendering To actually render the screen buffer, you must call `render`. diff --git a/lib/colors.js b/lib/colors.js index 7b59e9a..355e13b 100644 --- a/lib/colors.js +++ b/lib/colors.js @@ -6,10 +6,6 @@ exports.matchColor = function(col) { if (col[0] !== '#') return col; - if (!exports._cache) { - exports._cache = {}; - } - if (exports._cache[col] != null) { return exports._cache[col]; } @@ -51,6 +47,8 @@ exports.matchColor = function(col) { return exports._cache[col] = li; }; +exports._cache = {}; + exports.def = [ '#000000', '#ee0000', @@ -343,8 +341,9 @@ Object.keys(exports.ccolors).forEach(function(name) { exports.ccolors[offset] = exports.colorNames[name]; return; } - var i = offset[0], l = offset[2]; - for (; i <= l; i++) exports.ccolors[i] = exports.colorNames[name]; + for (var i = offset[0], l = offset[1]; i <= l; i++) { + exports.ccolors[i] = exports.colorNames[name]; + } }); delete exports.ccolors[name]; }); diff --git a/lib/program.js b/lib/program.js index 5fd9eac..adfe221 100644 --- a/lib/program.js +++ b/lib/program.js @@ -49,7 +49,12 @@ function Program(options) { this.listen(); - Program.global = this; + //if (!Program.global) { + // Program._write = process.stdout.write; + // process.stdout.write = function() {}; + // process.stderr.write = function() {}; + // Program.global = this; + //} } Program.prototype.__proto__ = EventEmitter.prototype; @@ -688,6 +693,11 @@ Program.prototype.receive_ = function(text, callback) { Program.prototype.write = Program.prototype.echo = function(text, attr) { + //if (this.output === process.stdout) { + // return attr + // ? Program._write.call(this.output, this.text(text, attr)) + // : Program._write.call(this.output, text); + //} return attr ? this.output.write(this.text(text, attr)) : this.output.write(text); diff --git a/lib/widget.js b/lib/widget.js index 6719c55..1359ed6 100644 --- a/lib/widget.js +++ b/lib/widget.js @@ -133,10 +133,15 @@ Node.prototype.remove = function(element) { //element.emitDescendants('detach', function(el) { // el._detached = true; //}); + + //var ret = this._lastPos; + //if (ret) this.screen.clearRegion(ret.xi, ret.xl, ret.yi, ret.yl); }; Node.prototype.detach = function() { - this.parent.remove(this); + if (this.parent) this.parent.remove(this); + //var ret = this._lastPos; + //if (ret) this.screen.clearRegion(ret.xi, ret.xl, ret.yi, ret.yl); }; Node.prototype.emitDescendants = function() { @@ -206,7 +211,14 @@ function Screen(options) { this.program.on('resize', function() { self.alloc(); self.render(); - self.emit('resize'); + //self.emit('resize'); + (function emit(el) { + el.emit('resize'); + if (el.children) { + el.children.forEach(emit); + } + })(self); + //self.emitDescendants('resize'); }); this.program.alternateBuffer(); @@ -223,6 +235,8 @@ function Screen(options) { } } + this._maxListeners = Infinity; + process.on('uncaughtException', function(err) { reset(); if (err) console.error(err.stack + ''); @@ -805,9 +819,9 @@ function Element(options) { } }); - this.screen.on('resize', function() { - self.parseContent(); - }); + //this.onScreenEvent('resize', function() { + // self.parseContent(); + //}); this.on('resize', function() { self.parseContent(); @@ -837,6 +851,19 @@ Element.prototype.emit = function(type) { }; */ +Element.prototype.onScreenEvent = function(type, listener) { + var self = this; + if (this.parent) { + this.screen.on(type, listener); + } + this.on('attach', function() { + self.screen.on(type, listener); + }); + this.on('detach', function() { + self.screen.removeListener(type, listener); + }); +}; + Element.prototype.hide = function() { if (this.hidden) return; this.hidden = true; @@ -1228,10 +1255,6 @@ Element.prototype.__defineSetter__('rbottom', function(val) { return this.options.bottom = this.position.bottom = val; }); -Element.prototype.calcShrink = function(xi_, xl, yi_, yl) { - return [xi_, xl, yi_, yl]; -}; - /** * Box */ @@ -1525,7 +1548,7 @@ Box.prototype.insertTop = function(line) { if (this._lastPos.xi === 0 && this._lastPos.xl === this.screen.width) { this.screen.insertTop(this._lastPos.yi, this._lastPos.yl - 1); } - this.setContent(line + '\n' + this.content); + this.setContent(line + '\n' + this.content, true); }; Box.prototype.insertBottom = function(line) { @@ -1533,7 +1556,7 @@ Box.prototype.insertBottom = function(line) { if (this._lastPos.xi === 0 && this._lastPos.xl === this.screen.width) { this.screen.insertBottom(this._lastPos.yi, this._lastPos.yl - 1); } - this.setContent(this.content + '\n' + line); + this.setContent(this.content + '\n' + line, true); }; /** @@ -1753,7 +1776,8 @@ function List(options) { } } - this.screen.on('resize', resize); + //this.onScreenEvent('resize', resize); + this.on('resize', resize); }