docs. key() fix. wrapContent() fix. box.{insert,delete}Line fix.

This commit is contained in:
Christopher Jeffrey 2013-07-15 17:45:08 -05:00
parent bc99d7fc37
commit 12e7eab68d
2 changed files with 146 additions and 103 deletions

168
README.md
View File

@ -2,113 +2,68 @@
A curses-like library for node.js. A curses-like library for node.js.
Blessed was originally written to only support the xterm terminfo, but can ## Example
now parse and compile any terminfo to be completely portable accross all
terminals. See the `tput` example below.
Blessed also includes an extremely high-level widget library. This will render a box with ascii borders containing the text `'Hello world!'`,
## Example Usage
This will actually parse the xterm terminfo and compile every
string capability to a javascript function:
``` js
var Tput = require('blessed').Tput
, tput = Tput('xterm');
console.log(tput.setaf(4) + 'hello' + tput.sgr0());
```
To play around with it on the command line, it works just like tput:
``` bash
$ tput.js setaf 2
$ tput.js sgr0
$ echo "$(tput.js setaf 2)hello world$(tput.js sgr0)"
```
The main functionality is exposed in the main `blessed` module:
``` js
var blessed = require('blessed')
, program = blessed();
program.key('q', function(ch, key) {
program.clear();
program.disableMouse();
program.showCursor();
program.normalBuffer();
process.exit(0);
});
program.on('mouse', function(data) {
if (data.action === 'mousemove') {
program.move(data.x, data.y);
program.bg('red');
program.write('x');
program.bg('!red');
}
});
program.alternateBuffer();
program.enableMouse();
program.hideCursor();
program.clear();
program.move(1, 1);
program.bg('black');
program.write('Hello world', 'blue fg');
program.setx((program.cols / 2 | 0) - 4);
program.down(5);
program.write('Hi again!');
program.bg('!black');
program.feed();
```
## High-level Documentation
### Example
This will render a box with ascii borders containing the text 'Hello world!',
perfectly centered horizontally and vertically. perfectly centered horizontally and vertically.
``` js ``` js
var blessed = require('blessed') var blessed = require('blessed');
, screen = new blessed.Screen;
var box = new blessed.Box({ // Create a screen object.
var screen = blessed.screen();
// Create a box perfectly centered horizontally and vertically.
var box = blessed.box({
top: 'center', top: 'center',
left: 'center', left: 'center',
width: '50%', width: '50%',
height: '50%', height: '50%',
border: { border: {
type: 'ascii', type: 'ascii',
fg: 'white' fg: '#ffffff'
}, },
fg: 'white', fg: 'white',
bg: 'magenta', bg: 'magenta',
content: 'Hello world!', content: 'Hello {bold}world{/bold}!',
tags: true tags: true,
hoverEffects: {
bg: 'green'
}
}); });
// Append our box to the screen.
screen.append(box); screen.append(box);
// If our box is clicked, change the content.
box.on('click', function(data) { box.on('click', function(data) {
box.setContent('{center}Some different {red-fg}content{/red-fg}.{/center}'); box.setContent('{center}Some different {red-fg}content{/red-fg}.{/center}');
screen.render(); screen.render();
}); });
screen.key('escape', function(ch, key) { // If box is focused, handle `enter` and give us some more content.
box.key('enter', function() {
box.setContent('{right}Even different {black-fg}content{/black-fg}.{/right}\n');
box.setLine(1, 'bar');
box.insertLine(1, 'foo');
screen.render();
});
// Quit on Escape, q, or Control-C.
screen.key(['escape', 'q', 'C-c'], function(ch, key) {
return process.exit(0); return process.exit(0);
}); });
// Focus our element.
box.focus();
// Render the screen.
screen.render(); screen.render();
``` ```
## High-level Documentation
### Widgets ### Widgets
Blessed comes with a number of high-level widgets so you can avoid all the Blessed comes with a number of high-level widgets so you can avoid all the
@ -770,6 +725,65 @@ Outputting:
- For a less interactive position testing, see `test/widget-pos.js`. - For a less interactive position testing, see `test/widget-pos.js`.
## Lower-Level Usage
This will actually parse the xterm terminfo and compile every
string capability to a javascript function:
``` js
var Tput = require('blessed').Tput
, tput = Tput('xterm');
console.log(tput.setaf(4) + 'hello' + tput.sgr0());
```
To play around with it on the command line, it works just like tput:
``` bash
$ tput.js setaf 2
$ tput.js sgr0
$ echo "$(tput.js setaf 2)hello world$(tput.js sgr0)"
```
The main functionality is exposed in the main `blessed` module:
``` js
var blessed = require('blessed')
, program = blessed();
program.key('q', function(ch, key) {
program.clear();
program.disableMouse();
program.showCursor();
program.normalBuffer();
process.exit(0);
});
program.on('mouse', function(data) {
if (data.action === 'mousemove') {
program.move(data.x, data.y);
program.bg('red');
program.write('x');
program.bg('!red');
}
});
program.alternateBuffer();
program.enableMouse();
program.hideCursor();
program.clear();
program.move(1, 1);
program.bg('black');
program.write('Hello world', 'blue fg');
program.setx((program.cols / 2 | 0) - 4);
program.down(5);
program.write('Hi again!');
program.bg('!black');
program.feed();
```
## License ## License
Copyright (c) 2013, Christopher Jeffrey. (MIT License) Copyright (c) 2013, Christopher Jeffrey. (MIT License)

View File

@ -1535,16 +1535,16 @@ Element.prototype.__defineGetter__('detached', function() {
}); });
Element.prototype.key = function() { Element.prototype.key = function() {
return Screen.prototype.key.apply(this, arguments); return this.screen.program.key.apply(this, arguments);
}; };
Element.prototype.onceKey = function() { Element.prototype.onceKey = function() {
return Screen.prototype.onceKey.apply(this, arguments); return this.screen.program.onceKey.apply(this, arguments);
}; };
Element.prototype.unkey = Element.prototype.unkey =
Element.prototype.removeKey = function() { Element.prototype.removeKey = function() {
return Screen.prototype.unkey.apply(this, arguments); return this.screen.program.unkey.apply(this, arguments);
}; };
Element.prototype.clearPos = function() { Element.prototype.clearPos = function() {
@ -2168,75 +2168,99 @@ outer:
// Maybe _lastPos could be updated on .left, .right, etc setters? // Maybe _lastPos could be updated on .left, .right, etc setters?
Box.prototype.insertLine = function(i, line) { Box.prototype.insertLine = function(i, line) {
var pos = this._lastPos || 0;
if (typeof line === 'string') line = [line]; if (typeof line === 'string') line = [line];
if (this.screen.cleanSides(this)) { if (i > this._clines.length) {
for (var j = this._clines.length; j < i; j++) this._clines.push('');
}
i = Math.max(i, 0); i = Math.max(i, 0);
i = Math.min(i, this._lastPos.yl - this._lastPos.yi - (this.border ? 2 : 0) - this.padding * 2); //i = Math.min(i, this._clines.length);
var height = pos.yl - pos.yi - (this.border ? 2 : 0) - this.padding * 2
, base = this.childBase || 0
, visible = i >= base && i - base < height;
if (pos && visible && this.screen.cleanSides(this)) {
this.screen.insertLine(line.length, this.screen.insertLine(line.length,
this._lastPos.yi + (this.border ? 1 : 0) + this.padding + i, pos.yi + (this.border ? 1 : 0) + this.padding + i - base,
this._lastPos.yi, pos.yi,
this._lastPos.yl - (this.border ? 1 : 0) - this.padding - 1); pos.yl - (this.border ? 1 : 0) - this.padding - 1);
} }
line.forEach(function(line, j) { line.forEach(function(line, j) {
this._clines.splice((this.childBase || 0) + (this.border ? 1 : 0) + this.padding + i + j, 0, line); this._clines.splice(i + j, 0, line);
}, this); }, this);
this.setContent(this._clines.join('\n'), true); this.setContent(this._clines.join('\n'), true);
}; };
Box.prototype.deleteLine = function(i, n) { Box.prototype.deleteLine = function(i, n) {
var pos = this._lastPos || 0;
var reset = true var reset = true
, n = n || 1; , n = n || 1;
if (this.screen.cleanSides(this)) {
i = Math.max(i, 0); i = Math.max(i, 0);
i = Math.min(i, this._lastPos.yl - this._lastPos.yi - (this.border ? 2 : 0) - this.padding * 2); i = Math.min(i, this._clines.length - 1);
var height = pos.yl - pos.yi - (this.border ? 2 : 0) - this.padding * 2
, base = this.childBase || 0
, visible = i >= base && i - base < height;
if (pos && visible && this.screen.cleanSides(this)) {
this.screen.deleteLine(n, this.screen.deleteLine(n,
this._lastPos.yi + (this.border ? 1 : 0) + this.padding + i, pos.yi + (this.border ? 1 : 0) + this.padding + i - base,
this._lastPos.yi, pos.yi,
this._lastPos.yl - (this.border ? 1 : 0) - this.padding - 1); pos.yl - (this.border ? 1 : 0) - this.padding - 1);
reset = false; reset = false;
} }
while (n--) { while (n--) {
this._clines.splice((this.childBase || 0) + (this.border ? 1 : 0) + this.padding + i, 1); this._clines.splice(i, 1);
} }
this.setContent(this._clines.join('\n'), reset); this.setContent(this._clines.join('\n'), reset);
}; };
Box.prototype.insertTop = function(line) { Box.prototype.insertTop = function(line) {
return this.insertLine(0, line); return this.insertLine((this.childBase || 0) + 0, line);
}; };
Box.prototype.insertBottom = function(line) { Box.prototype.insertBottom = function(line) {
return this.insertLine(this.height - (this.border ? 2 : 0) - this.padding * 2, line); return this.insertLine((this.childBase || 0)
+ this.height - (this.border ? 2 : 0) - this.padding * 2, line);
}; };
Box.prototype.deleteTop = function() { Box.prototype.deleteTop = function() {
return this.deleteLine(0); return this.deleteLine((this.childBase || 0) + 0);
}; };
Box.prototype.deleteBottom = function() { Box.prototype.deleteBottom = function() {
return this.deleteLine(this.height - (this.border ? 2 : 0) - this.padding * 2); return this.deleteLine((this.childBase || 0)
+ this.height - (this.border ? 2 : 0) - this.padding * 2);
}; };
Box.prototype.setLine = function(i, line) { Box.prototype.setLine = function(i, line) {
if (i > this._clines.length) {
for (var j = this._clines.length; j < i; j++) this._clines.push('');
}
i = Math.max(i, 0); i = Math.max(i, 0);
i = Math.min(i, this._lastPos.yl - this._lastPos.yi - (this.border ? 2 : 0) - this.padding * 2); //i = Math.min(i, this._clines.length);
this._clines[(this.childBase || 0) + (this.border ? 1 : 0) + this.padding + i] = line; this._clines[(this.childBase || 0) + i] = line;
return this.setContent(this._clines.join('\n'), true); return this.setContent(this._clines.join('\n'), true);
}; };
Box.prototype.getLine = function(i) { Box.prototype.getLine = function(i) {
i = Math.max(i, 0); i = Math.max(i, 0);
i = Math.min(i, this._lastPos.yl - this._lastPos.yi - (this.border ? 2 : 0) - this.padding * 2); i = Math.min(i, this._clines.length);
return this._clines[(this.childBase || 0) + (this.border ? 1 : 0) + this.padding + i]; return this._clines[(this.childBase || 0) + i];
}; };
Box.prototype.clearLine = function(i) { Box.prototype.clearLine = function(i) {
i = Math.min(i, this._clines.length - 1);
return this.setLine(i, ''); return this.setLine(i, '');
}; };
@ -4095,7 +4119,8 @@ function wrapContent(content, width, tags, state) {
while (line[i] && line[i++] !== 'm'); while (line[i] && line[i++] !== 'm');
} }
if (!line[i]) break; if (!line[i]) break;
if (++total === width) { //if (++total === width) {
if (++total > width) {
// Try to find a space to break on: // Try to find a space to break on:
if (line[i] !== ' ') { if (line[i] !== ' ') {
var j = i; var j = i;
@ -4122,6 +4147,10 @@ function wrapContent(content, width, tags, state) {
line = line.substring(i - 1); line = line.substring(i - 1);
out.push(sp(part, width, align)); out.push(sp(part, width, align));
} }
// Make sure we didn't wrap the line to the very end, otherwise
// we get a pointless empty line after a newline.
if (line === '') return;
} }
// If only an escape code got cut off, at it to `part`. // If only an escape code got cut off, at it to `part`.