docs, tests, examples, misc, editor.

This commit is contained in:
Christopher Jeffrey 2013-07-03 23:15:09 -05:00
parent 05216eadbb
commit 6355b1259f
4 changed files with 261 additions and 27 deletions

View File

@ -194,6 +194,7 @@ The screen on which every other node renders.
- **mouse** - received on mouse events.
- **keypress** - received on key events.
- **element [name]** - global events received for all elements.
- **key [name]** - received on key event for [name].
##### Methods:
@ -215,6 +216,11 @@ The screen on which every other node renders.
- **focusPop()/focusLast()** - pop element off the focus stack.
- **saveFocus()** - save the focused element.
- **restoreFocus()** - restore the saved focused element.
- **key(name, listener)** - bind a keypress listener for a specific key.
- **spawn(file, args, options)** - spawn a process in the foreground, return to
blessed app after exit.
- **exec(file, args, options, callback)** - spawn a process in the foreground,
return to blessed app after exit. executes callback on error or exit.
#### Element (from Node)
@ -271,6 +277,7 @@ The base element.
- **keypress** - received on key events for this element.
- **move** - received when the element is moved.
- **resize** - received when the element is resized.
- **key [name]** - received on key event for [name].
##### Methods:
@ -281,6 +288,7 @@ The base element.
- **show()** - show element.
- **toggle()** - toggle hidden/shown.
- **focus()** - focus element.
- **key(name, listener)** - bind a keypress listener for a specific key.
#### Box (from Element)
@ -507,7 +515,7 @@ an element has the `position: absolute` CSS property.
When an element is created, it can be given coordinates in its constructor:
``` js
var box = new blessed.Box({
var box = blessed.box({
left: 'center',
top: 'center',
bg: 'yellow',
@ -604,7 +612,7 @@ it is hard to do this optimization automatically (blessed assumes you may
create any element of any width in any position). So, there is a solution:
``` js
var box = new blessed.Box(...);
var box = blessed.box(...);
box.setContent('line 1\nline 2');
box.insertBottom('line 3');
box.insertBottom('line 4');

View File

@ -41,14 +41,9 @@ function Node(options) {
(options.children || []).forEach(this.append.bind(this));
if (this.type === 'screen' && !this.focused) {
this.focused = this.children[0];
}
var self = this;
this.on('keypress', function(ch, key) {
self.emit('key ' + key.name, key);
});
// if (this.type === 'screen' && !this.focused) {
// this.focused = this.children[0];
// }
}
Node.uid = 0;
@ -57,10 +52,6 @@ Node.prototype.__proto__ = EventEmitter.prototype;
Node.prototype.type = 'node';
Node.prototype.key = function(name, listener) {
return this.on('key ' + name, listener);
};
Node.prototype.prepend = function(element) {
var old = element.parent;
@ -300,12 +291,9 @@ function Screen(options) {
});
this.on('newListener', function fn(type) {
if (type === 'keypress' || type === 'mouse') {
if (type === 'keypress') self._listenKeys();
if (type === 'keypress' || type.indexOf('key ') === 0 || type === 'mouse') {
if (type === 'keypress' || type.indexOf('key ') === 0) self._listenKeys();
if (type === 'mouse') self._listenMouse();
// if (self._listenedKeys && self._listenedMouse) {
// self.removeListener('newListener', fn);
// }
}
});
}
@ -316,7 +304,7 @@ Screen.prototype.__proto__ = Node.prototype;
Screen.prototype.type = 'screen';
// TODO: Bubble events.
// TODO: Bubble and capture events throughout the tree.
Screen.prototype._listenMouse = function(el) {
var self = this;
@ -431,6 +419,7 @@ Screen.prototype._listenKeys = function(el) {
if (!grabKeys) {
self.emit('keypress', ch, key);
self.emit('key ' + key.name, ch, key);
}
// If something changed from the screen key handler, stop.
@ -440,6 +429,8 @@ Screen.prototype._listenKeys = function(el) {
if (~self.input.indexOf(focused)) {
focused.emit('keypress', ch, key);
focused.emit('key ' + key.name, ch, key);
// self.emit('element keypress', focused, ch, key);
}
});
};
@ -554,6 +545,15 @@ Screen.prototype.insertTop = function(top, bottom) {
return this.insertLine(1, top, top, bottom);
};
Screen.prototype.deleteBottom = function(top, bottom) {
return this.clearRegion(0, this.width, bottom, bottom);
};
Screen.prototype.deleteTop = function(top, bottom) {
// return this.insertBottom(top, bottom);
return this.deleteLine(1, top, top, bottom);
};
Screen.prototype.draw = function(start, end) {
var x
, y
@ -802,6 +802,108 @@ Screen.prototype.fillRegion = function(attr, ch, xi, xl, yi, yl) {
}
};
Screen.prototype.key = function(key, listener) {
return this.on('key ' + key, listener);
};
Screen.prototype.spawn = function(file, args, options) {
if (!Array.isArray(args)) {
options = args;
args = [];
}
var options = options || {}
, spawn = require('child_process').spawn
, screen = this;
options.stdio = 'inherit';
screen.program.normalBuffer();
screen.program.showCursor();
var _listenedMouse = screen._listenedMouse;
if (_listenedMouse) {
screen.program.disableMouse();
}
var write = process.stdout.write;
process.stdout.write = function() {};
try {
process.stdin.pause();
} catch (e) {
;
}
var resume = function() {
if (resume.done) return;
resume.done = true;
try {
process.stdin.resume();
} catch (e) {
;
}
process.stdout.write = write;
screen.program.alternateBuffer();
screen.program.hideCursor();
if (_listenedMouse) {
screen.program.enableMouse();
}
screen.alloc();
screen.render();
};
var ps = spawn(file, args, options);
ps.on('error', resume);
ps.on('exit', resume);
return ps;
};
Screen.prototype.exec = function(file, args, options, callback) {
var callback = arguments[arguments.length-1]
, ps = this.spawn(file, args, options);
ps.on('error', function(err) {
return callback(err, false);
});
ps.on('exit', function(code) {
return callback(null, code === 0);
});
return ps;
};
Screen.prototype.readEditor = function(callback) {
var fs = require('fs')
, editor = process.env.EDITOR || 'vi'
, file = '/tmp/blessed.' + Math.random().toString(36)
, args = [file]
, opt;
opt = {
stdio: 'inherit',
env: process.env,
cwd: process.env.HOME
};
return this.exec(editor, args, opt, function(err, success) {
if (err) return callback(err);
return fs.readFile(file, 'utf8', function(err, data) {
return fs.unlink(file, function() {
if (err) return callback(err);
return callback(null, data);
});
});
});
};
/**
* Element
*/
@ -885,7 +987,7 @@ function Element(options) {
|| type === 'wheelup'
|| type === 'mousemove') {
self.screen._listenMouse(self);
} else if (type === 'keypress') {
} else if (type === 'keypress' || type.indexOf('key ') === 0) {
self.screen._listenKeys(self);
}
});
@ -1365,6 +1467,11 @@ Element.prototype.__defineSetter__('rright', function(val) {
Element.prototype.__defineSetter__('rtop', function(val) {
if (this.position.top === val) return;
this.emit('move');
// if (this._lastPos) {
// this.screen.clearRegion(
// this._lastPos.xi, this._lastPos.xl,
// this._lastPos.yi, this._lastPos.yl);
// }
this.screen.clearRegion(
this.left, this.left + this.width,
this.top, this.top + this.height);
@ -1383,6 +1490,10 @@ Element.prototype.__defineSetter__('rbottom', function(val) {
return this.options.bottom = this.position.bottom = val;
});
Element.prototype.key = function(key, listener) {
return this.on('key ' + key, listener);
};
/**
* Box
*/
@ -1755,16 +1866,32 @@ Box.prototype.insertTop = function(line) {
if (this._lastPos && 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, true);
// this.screen.render();
this._clines.splice((this.childBase || 0) + (this.border ? 1 : 0), 0, line);
this.setContent(this._clines.join('\n'), true);
};
Box.prototype.insertBottom = function(line) {
if (this._lastPos && 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, true);
// this.screen.render();
this._clines.splice((this.childBase || 0) + this.height - (this.border ? 2 : 0), 0, line);
this.setContent(this._clines.join('\n'), true);
};
Box.prototype.deleteTop = function() {
if (this._lastPos && this._lastPos.xi === 0 && this._lastPos.xl === this.screen.width) {
this.screen.deleteTop(this._lastPos.yi, this._lastPos.yl - 1);
}
this._clines.splice((this.childBase || 0) + (this.border ? 1 : 0), 1);
this.setContent(this._clines.join('\n'), true);
};
Box.prototype.deleteBottom = function() {
if (this._lastPos && this._lastPos.xi === 0 && this._lastPos.xl === this.screen.width) {
this.screen.deleteBottom(this._lastPos.yi, this._lastPos.yl - 1);
}
this._clines.splice((this.childBase || 0) + this.height - (this.border ? 2 : 0), 1);
this.setContent(this._clines.join('\n'), true);
};
/**
@ -2438,6 +2565,71 @@ Textbox.prototype.setEditor = function(callback) {
});
};
Textbox.prototype.editor =
Textbox.prototype.readEditor =
Textbox.prototype.setEditor = function(callback) {
var self = this;
this.focus();
var fs = require('fs')
, editor = process.env.EDITOR || 'vi'
, file = '/tmp/blessed.' + Math.random().toString(36)
, args = [file]
, opt;
opt = {
stdio: 'inherit',
env: process.env,
cwd: process.env.HOME
};
return this.screen.exec(editor, args, opt, function(err, success) {
if (err) return callback(err);
return fs.readFile(file, 'utf8', function(err, data) {
fs.unlink(file);
if (err) return callback(err);
value = value.replace(/[\r\n]/g, '');
self.value = value;
////if (self.censor) {
//// self.setContent(Array(self.value.length + 1).join('*'));
////} else
//if (!self.secret) {
// self.setContent(value);
//}
//return callback(null, value);
return self.setInput(callback);
});
});
};
Textbox.prototype.editor =
Textbox.prototype.readEditor =
Textbox.prototype.setEditor = function(callback) {
var self = this;
this.focus();
return this.screen.readEditor(function(err, value) {
if (err) return callback(err);
value = value.replace(/[\r\n]/g, '');
self.value = value;
////if (self.censor) {
//// self.setContent(Array(self.value.length + 1).join('*'));
////} else
//if (!self.secret) {
// self.setContent(value);
//}
//return callback(null, value);
return self.setInput(callback);
});
};
/**
* Textarea
*/

31
test/widget-insert.js Normal file
View File

@ -0,0 +1,31 @@
var blessed = require('blessed');
var screen = blessed.screen({
tput: true
});
var box = blessed.box({
parent: screen,
align: 'center',
bg: 'blue',
height: 5,
top: 'center',
left: 0,
content: 'line 1'
});
screen.render();
box.insertBottom('line 2');
box.insertTop('line 0');
screen.render();
setTimeout(function() {
box.deleteTop();
screen.render();
}, 2000);
screen.key('q', function() {
process.exit(0);
});

View File

@ -1,5 +1,8 @@
var blessed = require('blessed')
, screen = blessed.Screen({ tput: true });
var blessed = require('blessed');
var screen = new blessed.Screen({
tput: true
});
screen.append(new blessed.Text({
top: 0,