1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | var blessed = require('blessed')
|
9 | , request = require('request')
|
10 | , singlebyte = require('./singlebyte')
|
11 | , fs = require('fs');
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | var urls = fs.readFileSync(__dirname + '/ansi-art.list', 'utf8').trim().split('\n');
|
17 |
|
18 | var map = urls.reduce(function(map, url) {
|
19 | map[/([^.\/]+\/[^.\/]+)\.ans$/.exec(url)[1]] = url;
|
20 | return map;
|
21 | }, {});
|
22 |
|
23 | var max = Object.keys(map).reduce(function(out, text) {
|
24 | return Math.max(out, text.length);
|
25 | }, 0) + 6;
|
26 |
|
27 | var screen = blessed.screen({
|
28 | smartCSR: true,
|
29 | dockBorders: true
|
30 | });
|
31 |
|
32 | var art = blessed.terminal({
|
33 | parent: screen,
|
34 | left: 0,
|
35 | top: 0,
|
36 | height: 60,
|
37 |
|
38 | width: 82,
|
39 | border: 'line',
|
40 | tags: true,
|
41 | label: ' {bold}{cyan-fg}ANSI Art{/cyan-fg}{/bold} (Drag Me) ',
|
42 | handler: function() {},
|
43 | draggable: true
|
44 | });
|
45 |
|
46 | var list = blessed.list({
|
47 | parent: screen,
|
48 | label: ' {bold}{cyan-fg}Art List{/cyan-fg}{/bold} (Drag Me) ',
|
49 | tags: true,
|
50 | draggable: true,
|
51 | top: 0,
|
52 | right: 0,
|
53 | width: max,
|
54 | height: '50%',
|
55 | keys: true,
|
56 | vi: true,
|
57 | mouse: true,
|
58 | border: 'line',
|
59 | scrollbar: {
|
60 | ch: ' ',
|
61 | track: {
|
62 | bg: 'cyan'
|
63 | },
|
64 | style: {
|
65 | inverse: true
|
66 | }
|
67 | },
|
68 | style: {
|
69 | item: {
|
70 | hover: {
|
71 | bg: 'blue'
|
72 | }
|
73 | },
|
74 | selected: {
|
75 | bg: 'blue',
|
76 | bold: true
|
77 | }
|
78 | },
|
79 | search: function(callback) {
|
80 | prompt.input('Search:', '', function(err, value) {
|
81 | if (err) return;
|
82 | return callback(null, value);
|
83 | });
|
84 | }
|
85 | });
|
86 |
|
87 | var status = blessed.box({
|
88 | parent: screen,
|
89 | bottom: 0,
|
90 | right: 0,
|
91 | height: 1,
|
92 | width: 'shrink',
|
93 | style: {
|
94 | bg: 'blue'
|
95 | },
|
96 | content: 'Select your piece of ANSI art (`/` to search).'
|
97 | });
|
98 |
|
99 | var loader = blessed.loading({
|
100 | parent: screen,
|
101 | top: 'center',
|
102 | left: 'center',
|
103 | height: 5,
|
104 | align: 'center',
|
105 | width: '50%',
|
106 | tags: true,
|
107 | hidden: true,
|
108 | border: 'line'
|
109 | });
|
110 |
|
111 | var msg = blessed.message({
|
112 | parent: screen,
|
113 | top: 'center',
|
114 | left: 'center',
|
115 | height: 'shrink',
|
116 | width: '50%',
|
117 | align: 'center',
|
118 | tags: true,
|
119 | hidden: true,
|
120 | border: 'line'
|
121 | });
|
122 |
|
123 | var prompt = blessed.prompt({
|
124 | parent: screen,
|
125 | top: 'center',
|
126 | left: 'center',
|
127 | height: 'shrink',
|
128 | width: 'shrink',
|
129 | keys: true,
|
130 | vi: true,
|
131 | mouse: true,
|
132 | tags: true,
|
133 | border: 'line',
|
134 | hidden: true
|
135 | });
|
136 |
|
137 | list.setItems(Object.keys(map));
|
138 |
|
139 | list.on('select', function(el, selected) {
|
140 | if (list._.rendering) return;
|
141 |
|
142 | var name = el.getText();
|
143 | var url = map[name];
|
144 |
|
145 | status.setContent(url);
|
146 |
|
147 | list._.rendering = true;
|
148 | loader.load('Loading...');
|
149 |
|
150 | request({
|
151 | uri: url,
|
152 | encoding: null
|
153 | }, function(err, res, body) {
|
154 | list._.rendering = false;
|
155 | loader.stop();
|
156 |
|
157 | if (err) {
|
158 | return msg.error(err.message);
|
159 | }
|
160 |
|
161 | if (!body) {
|
162 | return msg.error('No body.');
|
163 | }
|
164 |
|
165 | return cp437ToUtf8(body, function(err, body) {
|
166 | if (err) {
|
167 | return msg.error(err.message);
|
168 | }
|
169 |
|
170 | if (process.argv[2] === '--debug') {
|
171 | var filename = name.replace(/\//g, '.') + '.ans';
|
172 | fs.writeFileSync(__dirname + '/' + filename, body);
|
173 | }
|
174 |
|
175 |
|
176 | body = body.replace('Downloaded From P-80 International Information Systems 304-744-2253', '');
|
177 |
|
178 |
|
179 | body = body.replace(/%[A-Z0-9]{2}/g, '');
|
180 |
|
181 |
|
182 |
|
183 |
|
184 |
|
185 | art.term.reset();
|
186 | art.term.write(body);
|
187 | art.term.cursorHidden = true;
|
188 |
|
189 | screen.render();
|
190 |
|
191 | if (process.argv[2] === '--debug' || process.argv[2] === '--save') {
|
192 | takeScreenshot(name);
|
193 | }
|
194 | });
|
195 | });
|
196 | });
|
197 |
|
198 | list.items.forEach(function(item, i) {
|
199 | var text = item.getText();
|
200 | item.setHover(map[text]);
|
201 | });
|
202 |
|
203 | list.focus();
|
204 | list.enterSelected(0);
|
205 |
|
206 | screen.key('h', function() {
|
207 | list.toggle();
|
208 | if (list.visible) list.focus();
|
209 | });
|
210 |
|
211 | screen.key('r', function() {
|
212 | shuffle();
|
213 | });
|
214 |
|
215 | screen.key('S-s', function() {
|
216 | takeScreenshot(list.ritems[list.selected]);
|
217 | });
|
218 |
|
219 | screen.key('s', function() {
|
220 | slideshow();
|
221 | });
|
222 |
|
223 | screen.key('q', function() {
|
224 | return process.exit(0);
|
225 | });
|
226 |
|
227 | screen.render();
|
228 |
|
229 |
|
230 |
|
231 |
|
232 |
|
233 |
|
234 |
|
235 |
|
236 | function cp437ToUtf8(buf, callback) {
|
237 | try {
|
238 | return callback(null, singlebyte.bufToStr(buf, 'cp437'));
|
239 | } catch (e) {
|
240 | return callback(e);
|
241 | }
|
242 | }
|
243 |
|
244 |
|
245 | var ANIMATING = [
|
246 | 'bbs/void3',
|
247 | 'holiday/xmasfwks',
|
248 | 'unsorted/diver',
|
249 | 'unsorted/mash-chp',
|
250 | 'unsorted/ryans47',
|
251 | 'unsorted/xmasfwks'
|
252 | ];
|
253 |
|
254 | function takeScreenshot(name) {
|
255 | var filename = name.replace(/\//g, '.') + '.ans.sgr';
|
256 | var image;
|
257 |
|
258 | if (~ANIMATING.indexOf(name)) {
|
259 | image = blessed.element.prototype.screenshot.call(art,
|
260 | 0 - art.ileft, art.width - art.iright,
|
261 | 0 - art.itop, art.height - art.ibottom);
|
262 | } else {
|
263 | image = art.screenshot();
|
264 | }
|
265 | fs.writeFileSync(__dirname + '/' + filename, image);
|
266 | msg.display('Screenshot taken.');
|
267 | }
|
268 |
|
269 | function slideshow() {
|
270 | if (!screen._.slideshow) {
|
271 | screen._.slideshow = setInterval(function slide() {
|
272 | if (screen.lockKeys) return;
|
273 | var i = (list.items.length - 1) * Math.random() | 0;
|
274 | list.enterSelected(i);
|
275 | return slide;
|
276 | }(), 3000);
|
277 | msg.display('Slideshow started.');
|
278 | } else {
|
279 | clearInterval(screen._.slideshow);
|
280 | delete screen._.slideshow;
|
281 | msg.display('Slideshow stopped.');
|
282 | }
|
283 | }
|
284 |
|
285 | function shuffle() {
|
286 | var items = Object.keys(map).sort(function(key) {
|
287 | return Math.random() > 0.5 ? 1 : -1;
|
288 | });
|
289 | list.setItems(items);
|
290 | screen.render();
|
291 | msg.display('Shuffled items.');
|
292 | }
|