Skip to content

Commit 2201c0c

Browse files
committed
feat: added status bar
1 parent ee8ccd8 commit 2201c0c

File tree

3 files changed

+89
-12
lines changed

3 files changed

+89
-12
lines changed

src/index.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const _ = require('lodash');
55
require('./polyfills');
66

77
const MainPanel = require('./widgets/MainPanel');
8+
const StatusLine = require('./widgets/StatusLine');
89

910
const opts = minimist(process.argv.slice(2));
1011
const logFile = opts._[0];
@@ -26,6 +27,11 @@ screen.key(['C-c'], function(_ch, _key) {
2627
const level = opts.l || opts.level;
2728
const sort = opts.s || opts.sort;
2829
const args = { screen, level, sort };
29-
const main = new MainPanel(args);
30-
main.loadFile(logFile);
31-
main.setCurrent();
30+
const mainPanel = new MainPanel(args);
31+
mainPanel.loadFile(logFile);
32+
33+
const statusLine = new StatusLine({ screen, mainPanel });
34+
screen.append(statusLine);
35+
mainPanel.setCurrent();
36+
37+
screen.render();

src/widgets/MainPanel.js

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const FIELDS = ['timestamp', 'level', 'message'];
1212

1313
class MainPanel extends BaseWidget {
1414
constructor(opts={}) {
15-
super(Object.assign({}, { handleKeys: true }, opts));
15+
super(Object.assign({}, { top: '0', height: '99%', handleKeys: true }, opts));
1616

1717
this.currentPage = opts.currentPage || 1;
1818
this.initialRow = opts.initialRow || 0;
@@ -25,7 +25,8 @@ class MainPanel extends BaseWidget {
2525
this.lastSearchTerm = null;
2626
this.levelFilter = opts.level;
2727
this.filters = [];
28-
this.sort = opts.sort || '-timestap';
28+
this.sort = opts.sort || '-timestamp';
29+
this.mode = 'normal';
2930

3031
this.log('pageWidth', this.pageWidth);
3132
this.update();
@@ -86,6 +87,7 @@ class MainPanel extends BaseWidget {
8687
}
8788

8889
renderLines() {
90+
this.resetMode();
8991
this.rows = this.lines.slice(this.initialRow, this.initialRow + this.height - 2);
9092
this.update();
9193
}
@@ -151,7 +153,7 @@ class MainPanel extends BaseWidget {
151153
return;
152154
}
153155
if (ch === 'f') {
154-
if (this.filters.length) {
156+
if (this.filters.length || this.levelFilter) {
155157
return this.clearFilters();
156158
}
157159
this.openFilter();
@@ -186,8 +188,9 @@ class MainPanel extends BaseWidget {
186188
}
187189

188190
openSort() {
191+
this.setMode('sort');
189192
this.openPicker('Sort by', FIELDS, (err, sort) => {
190-
if (!sort) { return; }
193+
if (!sort) { return this.resetMode(); }
191194
if (err) { return; }
192195
if (this.sortKey === sort && this.sortAsc) {
193196
return this.setSort(`-${sort}`);
@@ -196,11 +199,21 @@ class MainPanel extends BaseWidget {
196199
});
197200
}
198201

202+
setMode(mode) {
203+
this.log('setmode', mode);
204+
this.mode = mode;
205+
this.emit('update');
206+
}
207+
208+
resetMode() {
209+
this.setMode('normal');
210+
}
211+
199212
openFilter() {
213+
this.setMode('filter');
200214
const fields = ['timestamp', 'level', 'message', 'other'];
201215
this.openPicker('Filter by', fields, (err, field) => {
202-
if (!field) { return; }
203-
if (err) { return; }
216+
if (err || !field) { return this.resetMode(); }
204217
if (field === 'level') {
205218
return this.openLevelFilter();
206219
}
@@ -213,7 +226,7 @@ class MainPanel extends BaseWidget {
213226

214227
openCustomFilter() {
215228
this.prompt(`Field to filter:`, '', (field) => {
216-
if (!field) { return; }
229+
if (!field) { return this.resetMode(); }
217230
if (field.indexOf(':') > -1) {
218231
return this.setFilter(field.split(':')[0], field.split(':')[1], 'contains');
219232
}
@@ -223,7 +236,7 @@ class MainPanel extends BaseWidget {
223236

224237
openFilterTerm(field) {
225238
this.prompt(`Filter ${field} by:`, '', (value) => {
226-
if (!value) { return; }
239+
if (!value) { return this.resetMode(); }
227240
this.setFilter(field, value, 'contains');
228241
});
229242
}
@@ -287,13 +300,15 @@ class MainPanel extends BaseWidget {
287300
}
288301

289302
openSearch(clear=false) {
303+
this.setMode('search');
290304
if (clear) {
291305
this.lastSearchTerm = null;
292306
}
293307
this.prompt('Search:', this.lastSearchTerm, (value) => this.search(value));
294308
}
295309

296310
openGoToLine() {
311+
this.setMode('GOTO');
297312
this.prompt('Line:', '', (value) => this.moveToLine(parseInt(value, 10)-1));
298313
}
299314

@@ -408,7 +423,7 @@ class MainPanel extends BaseWidget {
408423
this.setLabel(`[{bold} ${this.file} {/}] [{bold} ${this.row+1}/${this.lastRow+1} {/}]`);
409424

410425
const columns = [
411-
{ title: 'Timestap', key: 'timestamp' },
426+
{ title: 'Timestamp', key: 'timestamp' },
412427
{ title: 'Level', key: 'level', format: v => levelColors[v](v) },
413428
{ title: 'D', key: 'data', length: 1, format: v => _.isEmpty(v) ? ' ' : '*' },
414429
{ title: 'Message', key: 'message' },
@@ -427,6 +442,8 @@ class MainPanel extends BaseWidget {
427442
const list = blessed.element({ tags: true, content });
428443
this.append(list);
429444
this.screen.render();
445+
this.log('update...', this.filters);
446+
this.emit('update');
430447
}
431448
}
432449

src/widgets/StatusLine.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
const blessed = require('blessed');
2+
const _ = require('lodash');
3+
4+
const BaseWidget = require('./BaseWidget');
5+
6+
class StatusLine extends blessed.Box {
7+
constructor(opts={}) {
8+
super(Object.assign({}, {
9+
top: opts.screen.height-1,
10+
left: 0,
11+
width: '100%',
12+
height: 1,
13+
tags: true,
14+
style: {
15+
fg: 'white',
16+
bg: 'blue',
17+
},
18+
}, opts));
19+
20+
this.mainPanel = opts.mainPanel;
21+
this.mainPanel.on('update', this.update.bind(this));
22+
this.update();
23+
}
24+
25+
log(...s) {
26+
this.screen.log(...s);
27+
}
28+
29+
get row() { return this.mainPanel.row+1; }
30+
get lastRow() { return this.mainPanel.lastRow+1; };
31+
get mode() { return this.mainPanel.mode.toUpperCase(); }
32+
get sort() { return this.mainPanel.sort; }
33+
get filters() {
34+
const { filters, levelFilter } = this.mainPanel;
35+
if (this.mainPanel.levelFilter) {
36+
return filters.concat({ key: 'level', value: levelFilter });
37+
}
38+
return filters;
39+
}
40+
41+
update() {
42+
const mode = `{yellow-bg}{black-fg}{bold} ${this.mode} {/}`;
43+
const line = `{bold}${this.row}{/}/{bold}${this.lastRow}{/}`;
44+
const sort = this.sort ? `| sort: {bold}${this.sort}{/}` : '';
45+
const filterExpr = this.filters.map(f => `${f.key}:${f.value}`).join(' ');
46+
const filters = filterExpr ? `| filters: {bold}${filterExpr}{/}` : '';
47+
this.log('status updated', this.filters, filters);
48+
this.log('filters', [ { key: 'level', value: 'error' } ].map(f => `${f.key}:${f.value}`));
49+
this.setContent(` ${mode} ${line} ${sort} ${filters}`);
50+
this.screen.render();
51+
}
52+
}
53+
54+
module.exports = StatusLine;

0 commit comments

Comments
 (0)