204 lines
3.6 KiB
JavaScript
Raw Normal View History

2015-04-18 20:27:53 -07:00
/**
2015-04-18 23:58:41 -07:00
* ansi-viewer
2015-04-18 20:27:53 -07:00
* ANSI art viewer for node.
* Copyright (c) 2015, Christopher Jeffrey and contributors (MIT License).
* https://github.com/chjj/blessed
*/
2015-04-19 12:09:05 -07:00
var blessed = require('blessed')
2015-04-18 20:27:53 -07:00
, request = require('request')
, fs = require('fs')
2015-04-20 14:09:01 -07:00
, cp = require('child_process')
, singlebyte = require('./singlebyte');
2015-04-18 20:27:53 -07:00
// $ wget -r -o log --tries=10 'http://artscene.textfiles.com/ansi/'
// $ grep 'http.*\.ans$' log | awk '{ print $3 }' > ansi-art.list
2015-04-18 20:27:53 -07:00
var urls = fs.readFileSync(__dirname + '/ansi-art.list', 'utf8').trim().split('\n');
var map = urls.reduce(function(map, url) {
map[/([^.\/]+\/[^.\/]+)\.ans$/.exec(url)[1]] = url;
return map;
}, {});
2015-04-18 23:58:41 -07:00
var max = Object.keys(map).reduce(function(out, text) {
return Math.max(out, text.length);
}, 0) + 6;
2015-04-20 14:09:01 -07:00
var screen = blessed.screen({
2015-04-18 20:27:53 -07:00
smartCSR: true,
dockBorders: true
});
var art = blessed.terminal({
parent: screen,
left: 0,
top: 0,
right: 0,
bottom: 0,
handler: function() {}
});
var list = blessed.list({
parent: screen,
label: ' {bold}{cyan-fg}ANSI Art{/cyan-fg}{/bold} (Drag Me) ',
tags: true,
draggable: true,
top: 0,
right: 0,
2015-04-18 23:58:41 -07:00
width: max,
height: '50%',
2015-04-18 20:27:53 -07:00
keys: true,
vi: true,
mouse: true,
border: 'line',
scrollbar: {
ch: ' ',
track: {
bg: 'cyan'
},
style: {
inverse: true
}
},
style: {
item: {
hover: {
bg: 'blue'
}
},
selected: {
bg: 'blue',
bold: true
}
},
search: function(callback) {
prompt.input('Search:', '', function(err, value) {
if (err) return;
2015-04-18 22:25:13 -07:00
return callback(null, value);
});
2015-04-18 20:27:53 -07:00
}
});
var status = blessed.box({
parent: screen,
bottom: 0,
right: 0,
height: 1,
width: 'shrink',
style: {
bg: 'blue'
},
content: 'Select your piece of ANSI art (`/` to search).'
});
var loader = blessed.loading({
parent: screen,
top: 'center',
left: 'center',
height: 5,
align: 'center',
width: '50%',
tags: true,
hidden: true,
border: 'line'
});
var msg = blessed.message({
parent: screen,
top: 'center',
left: 'center',
height: 'shrink',
width: '50%',
align: 'center',
tags: true,
hidden: true,
border: 'line'
});
var prompt = blessed.prompt({
parent: screen,
top: 'center',
left: 'center',
height: 'shrink',
width: 'shrink',
keys: true,
vi: true,
mouse: true,
tags: true,
border: 'line',
hidden: true
2015-04-18 20:27:53 -07:00
});
list.setItems(Object.keys(map));
list.on('select', function(url, selected) {
if (list._.rendering) return;
2015-04-18 20:27:53 -07:00
url = map[url.getText()];
status.setContent(url);
list._.rendering = true;
loader.load('Loading...');
2015-04-20 14:09:01 -07:00
request({
uri: url,
encoding: null
}, function(err, res, body) {
list._.rendering = false;
loader.stop();
if (err) {
return msg.error(err.message);
}
if (!body) {
return msg.error('No body.');
}
2015-04-20 14:09:01 -07:00
return cp437ToUtf8(body, function(err, body) {
if (err) {
return msg.error(err.message);
}
// Remove MCI codes:
//body = body.replace(/%[A-Z0-9]{2}/g, '');
2015-04-20 14:09:01 -07:00
// Reset and write the art:
art.term.reset();
art.term.write(body);
art.term.cursorHidden = true;
2015-04-20 14:09:01 -07:00
screen.render();
});
2015-04-18 20:27:53 -07:00
});
});
list.focus();
screen.key('q', function() {
return process.exit(0);
});
screen.key('h', function() {
list.toggle();
if (list.visible) list.focus();
});
screen.render();
2015-04-20 14:09:01 -07:00
/**
* Helpers
*/
// https://github.com/chjj/blessed/issues/127
// https://github.com/Mithgol/node-singlebyte
function cp437ToUtf8(buf, callback) {
try {
return callback(null, singlebyte.bufToStr(buf, 'cp437'));
} catch (e) {
return callback(e);
}
}