docs, tests, examples, misc, editor.
This commit is contained in:
parent
05216eadbb
commit
6355b1259f
12
README.md
12
README.md
|
@ -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');
|
||||
|
|
238
lib/widget.js
238
lib/widget.js
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
});
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue