add Image element using w3mimgdisplay.
This commit is contained in:
parent
690cf9d3f4
commit
6ee469fdcb
29
README.md
29
README.md
|
@ -876,6 +876,35 @@ term.js to be installed).
|
||||||
- inherits all from Box.
|
- inherits all from Box.
|
||||||
|
|
||||||
|
|
||||||
|
#### Image (from Box)
|
||||||
|
|
||||||
|
Display an image in the terminal (jpeg, png, gif) using w3mimgdisplay. Requires
|
||||||
|
w3m to be installed. X11 required: works in xterm, urxvt, and possibly other
|
||||||
|
terminals.
|
||||||
|
|
||||||
|
##### Options:
|
||||||
|
|
||||||
|
- inherits all from Box.
|
||||||
|
- **file** - path to image
|
||||||
|
- **w3m** - path to w3mimgdisplay
|
||||||
|
|
||||||
|
##### Properties:
|
||||||
|
|
||||||
|
- inherits all from Box.
|
||||||
|
|
||||||
|
##### Events:
|
||||||
|
|
||||||
|
- inherits all from Box.
|
||||||
|
|
||||||
|
##### Methods:
|
||||||
|
|
||||||
|
- inherits all from Box.
|
||||||
|
- **setImage(img, callback)** - set the image in the box to a new path.
|
||||||
|
- **clearImage(callback)** - clear the current image.
|
||||||
|
- **imageSize(img, callback)** - get the size of an image file in pixels.
|
||||||
|
- **termSize(callback)** - get the size of the terminal in pixels.
|
||||||
|
|
||||||
|
|
||||||
### Positioning
|
### Positioning
|
||||||
|
|
||||||
Offsets may be a number, a percentage (e.g. `50%`), or a keyword (e.g.
|
Offsets may be a number, a percentage (e.g. `50%`), or a keyword (e.g.
|
||||||
|
|
238
lib/widget.js
238
lib/widget.js
|
@ -1558,10 +1558,12 @@ Screen.prototype.exec = function(file, args, options, callback) {
|
||||||
, ps = this.spawn(file, args, options);
|
, ps = this.spawn(file, args, options);
|
||||||
|
|
||||||
ps.on('error', function(err) {
|
ps.on('error', function(err) {
|
||||||
|
if (!callback) return;
|
||||||
return callback(err, false);
|
return callback(err, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
ps.on('exit', function(code) {
|
ps.on('exit', function(code) {
|
||||||
|
if (!callback) return;
|
||||||
return callback(null, code === 0);
|
return callback(null, code === 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -6538,6 +6540,241 @@ Terminal.prototype.render = function() {
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Image
|
||||||
|
* Good example of w3mimgdisplay commands:
|
||||||
|
* https://github.com/hut/ranger/blob/master/ranger/ext/img_display.py
|
||||||
|
*/
|
||||||
|
|
||||||
|
function Image(options) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if (!(this instanceof Node)) {
|
||||||
|
return new Image(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
|
Box.call(this, options);
|
||||||
|
|
||||||
|
if (this.options.file) {
|
||||||
|
self.setImage(self.options.file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Image.prototype.__proto__ = Box.prototype;
|
||||||
|
|
||||||
|
Image.prototype.type = 'image';
|
||||||
|
|
||||||
|
Image.w3m = '/usr/lib/w3m/w3mimgdisplay';
|
||||||
|
|
||||||
|
Image.prototype.render = function() {
|
||||||
|
var ret = this._render();
|
||||||
|
if (!ret) return;
|
||||||
|
this.setImage(this.options.file);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
Image.prototype.spawn = function(file, args, opt, callback) {
|
||||||
|
var screen = this.screen
|
||||||
|
, opt = opt || {}
|
||||||
|
, spawn = require('child_process').spawn
|
||||||
|
, ps;
|
||||||
|
|
||||||
|
ps = spawn(file, args, opt);
|
||||||
|
|
||||||
|
if (callback) {
|
||||||
|
ps.on('error', callback);
|
||||||
|
|
||||||
|
ps.on('exit', function(code) {
|
||||||
|
if (code !== 0) return callback(new Error('Exit Code: ' + code));
|
||||||
|
return callback(null, code === 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return ps;
|
||||||
|
};
|
||||||
|
|
||||||
|
Image.prototype.setImage = function(img, callback) {
|
||||||
|
var self = this;
|
||||||
|
this.termSize(function(err, dimensions) {
|
||||||
|
if (err) {
|
||||||
|
if (!callback) return;
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
var tw = dimensions.width / self.screen.width;
|
||||||
|
var th = dimensions.height / self.screen.height;
|
||||||
|
|
||||||
|
var file = self.options.w3m || Image.w3m;
|
||||||
|
|
||||||
|
var opt = {
|
||||||
|
stdio: 'pipe',
|
||||||
|
env: process.env,
|
||||||
|
cwd: process.env.HOME
|
||||||
|
};
|
||||||
|
|
||||||
|
self.clearImage(function() {
|
||||||
|
var ps = self.spawn(file, [], opt, function(err, success) {
|
||||||
|
if (!callback) return;
|
||||||
|
return err
|
||||||
|
? callback(err)
|
||||||
|
: callback(null, success);
|
||||||
|
});
|
||||||
|
|
||||||
|
// XXX Move below code to callback.
|
||||||
|
if (self.shrink) {
|
||||||
|
self.imageSize(img, function(err, size) {
|
||||||
|
if (err) return;
|
||||||
|
if (self.position.width == null) {
|
||||||
|
self.position.width = size.width / tw | 0;
|
||||||
|
}
|
||||||
|
if (self.position.height == null) {
|
||||||
|
self.position.height = size.height / th | 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var width = self.width * tw | 0
|
||||||
|
, height = self.height * th | 0
|
||||||
|
, left = self.left * tw | 0
|
||||||
|
, top = self.top * th | 0;
|
||||||
|
|
||||||
|
var input = '0;1;'
|
||||||
|
+ left + ';'
|
||||||
|
+ top + ';'
|
||||||
|
+ width + ';'
|
||||||
|
+ height + ';;;;;'
|
||||||
|
+ img
|
||||||
|
+ '\n4;\n3;\n';
|
||||||
|
|
||||||
|
self._props = {
|
||||||
|
left: left,
|
||||||
|
top: top,
|
||||||
|
width: width,
|
||||||
|
height: height
|
||||||
|
};
|
||||||
|
|
||||||
|
ps.stdin.write(input);
|
||||||
|
ps.stdin.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Image.prototype.clearImage = function(callback) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if (!this._props) {
|
||||||
|
if (!callback) return;
|
||||||
|
return callback(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
var file = this.options.w3m || Image.w3m;
|
||||||
|
|
||||||
|
var opt = {
|
||||||
|
stdio: 'pipe',
|
||||||
|
env: process.env,
|
||||||
|
cwd: process.env.HOME
|
||||||
|
};
|
||||||
|
|
||||||
|
var ps = this.spawn(file, [], opt, function(err, success) {
|
||||||
|
if (!callback) return;
|
||||||
|
return err
|
||||||
|
? callback(err)
|
||||||
|
: callback(null, success);
|
||||||
|
});
|
||||||
|
|
||||||
|
var width = this._props.width
|
||||||
|
, height = this._props.height
|
||||||
|
, left = this._props.left
|
||||||
|
, top = this._props.top;
|
||||||
|
|
||||||
|
var input = '6;'
|
||||||
|
+ left + ';'
|
||||||
|
+ top + ';'
|
||||||
|
+ width + ';'
|
||||||
|
+ height
|
||||||
|
+ '\n4;\n3;\n';
|
||||||
|
|
||||||
|
delete this._props;
|
||||||
|
|
||||||
|
ps.stdin.write(input);
|
||||||
|
ps.stdin.end();
|
||||||
|
};
|
||||||
|
|
||||||
|
Image.prototype.imageSize = function(img, callback) {
|
||||||
|
var self = this;
|
||||||
|
var file = this.options.w3m || Image.w3m;
|
||||||
|
|
||||||
|
var opt = {
|
||||||
|
stdio: 'pipe',
|
||||||
|
env: process.env,
|
||||||
|
cwd: process.env.HOME
|
||||||
|
};
|
||||||
|
|
||||||
|
var ps = this.spawn(file, [], opt);
|
||||||
|
|
||||||
|
var buf = '';
|
||||||
|
|
||||||
|
ps.stdout.setEncoding('utf8');
|
||||||
|
|
||||||
|
ps.stdout.on('data', function(data) {
|
||||||
|
buf += data;
|
||||||
|
});
|
||||||
|
|
||||||
|
ps.on('error', callback);
|
||||||
|
|
||||||
|
ps.on('exit', function() {
|
||||||
|
if (!callback) return;
|
||||||
|
var size = buf.trim().split(/\s+/);
|
||||||
|
return callback(null, {
|
||||||
|
raw: buf.trim(),
|
||||||
|
width: +size[0],
|
||||||
|
height: +size[1]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
var input = '5;' + img + '\n';
|
||||||
|
|
||||||
|
ps.stdin.write(input);
|
||||||
|
ps.stdin.end();
|
||||||
|
};
|
||||||
|
|
||||||
|
Image.prototype.termSize = function(callback) {
|
||||||
|
var self = this;
|
||||||
|
var file = this.options.w3m || Image.w3m;
|
||||||
|
|
||||||
|
var opt = {
|
||||||
|
stdio: 'pipe',
|
||||||
|
env: process.env,
|
||||||
|
cwd: process.env.HOME
|
||||||
|
};
|
||||||
|
|
||||||
|
var ps = this.spawn(file, ['-test'], opt);
|
||||||
|
|
||||||
|
var buf = '';
|
||||||
|
|
||||||
|
ps.stdout.setEncoding('utf8');
|
||||||
|
|
||||||
|
ps.stdout.on('data', function(data) {
|
||||||
|
buf += data;
|
||||||
|
});
|
||||||
|
|
||||||
|
ps.on('error', callback);
|
||||||
|
|
||||||
|
ps.on('exit', function() {
|
||||||
|
if (!callback) return;
|
||||||
|
var size = buf.trim().split(/\s+/);
|
||||||
|
return callback(null, {
|
||||||
|
raw: buf.trim(),
|
||||||
|
width: +size[0],
|
||||||
|
height: +size[1]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
ps.stdin.end();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helpers
|
* Helpers
|
||||||
*/
|
*/
|
||||||
|
@ -6655,5 +6892,6 @@ exports.Loading = exports.loading = Loading;
|
||||||
exports.Listbar = exports.listbar = Listbar;
|
exports.Listbar = exports.listbar = Listbar;
|
||||||
|
|
||||||
exports.Terminal = exports.terminal = Terminal;
|
exports.Terminal = exports.terminal = Terminal;
|
||||||
|
exports.Image = exports.image = Image;
|
||||||
|
|
||||||
exports.helpers = helpers;
|
exports.helpers = helpers;
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
var blessed = require('../')
|
||||||
|
, screen;
|
||||||
|
|
||||||
|
screen = blessed.screen({
|
||||||
|
dump: __dirname + '/logs/image.log',
|
||||||
|
smartCSR: true
|
||||||
|
});
|
||||||
|
|
||||||
|
var img = blessed.image({
|
||||||
|
parent: screen,
|
||||||
|
left: 'center',
|
||||||
|
top: 'center',
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
bg: 'green',
|
||||||
|
file: process.argv[2] || __dirname + '/test-image.png'
|
||||||
|
});
|
||||||
|
|
||||||
|
img.focus();
|
||||||
|
|
||||||
|
screen.key('q', function() {
|
||||||
|
return process.exit(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
screen.render();
|
Loading…
Reference in New Issue