-
Notifications
You must be signed in to change notification settings - Fork 103
/
app-terminal.component.ts
127 lines (110 loc) · 3.83 KB
/
app-terminal.component.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import { Component, ElementRef, OnInit, Input, SimpleChange, EventEmitter } from '@angular/core';
import * as AnsiUp from 'ansi_up';
@Component({
selector: 'app-terminal',
templateUrl: 'app-terminal.component.html'
})
export class AppTerminalComponent implements OnInit {
@Input() data: any;
@Input() options: { size: 'normal' | 'large' };
au: any;
commands: { command: string, visible: boolean, output: string, time: string }[];
noData: boolean;
constructor(private elementRef: ElementRef) {
this.commands = [];
}
ngOnInit() {
this.au = new AnsiUp.default();
this.au.use_classes = true;
this.commands = [];
this.noData = true;
}
ngOnChanges(changes: SimpleChange) {
if (!this.data) {
return;
}
this.noData = false;
if (typeof this.data.clear !== 'undefined') {
this.commands = [];
} else {
const output: string = this.au.ansi_to_html(this.data);
const regex = /==[>|>](.*)/g;
let match;
let commands: string[] = [];
if (output.match(regex)) {
while (match = regex.exec(output)) {
commands.push(match[0]);
}
if (commands.length > 1) {
this.commands = [];
}
let retime = new RegExp('exectime.*(\\d)', 'igm');
let times = [];
while (match = retime.exec(output)) {
let t = match[0].replace('exectime]: ', '').replace(/<span.*/, '');
times.push(t);
}
this.commands = commands.reduce((acc, curr, i) => {
let next = commands[i + 1] || '';
next = next.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
const c = curr.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
let re = new RegExp('(' + c + ')(' + '[\\s\\S]+' + ')(' + next + ')');
if (!output.match(re)) {
re = new RegExp('(' + c + ')' + '[\\s\\S]+');
}
let retime = new RegExp('exectime.*(\\d)', 'igm');
let t = times[i] ? parseFloat(<any>(times[i] / 10)).toFixed(0) : null;
let time = t && parseInt(<any>t, 10);
return acc.concat({
command: curr.trim(),
visible: i === commands.length - 1 ? true : false,
output: output.match(re) && output.match(re)[2] ? output.match(re)[2].trim() : '',
time: times[i] ? this.getDuration(time) : null
});
}, this.commands);
} else {
if (output.includes('[exectime]')) {
const time = parseInt(output.replace('[exectime]', ''), 10);
console.log(time);
} else {
this.commands[this.commands.length - 1].output += output;
}
}
this.commands = this.commands.map((cmd, i) => {
cmd.visible = i === this.commands.length - 1 ? true : false;
return cmd;
});
}
this.checkScrollBottom();
}
checkScrollBottom(): void {
// TODO: make this work actually
// const element = window.document.documentElement;
// if (element.scrollTop + element.clientHeight == element.scrollHeight) {
window.scrollTo(0, document.body.scrollHeight);
// }
}
toogleCommand(index: number) {
this.commands[index].visible = !this.commands[index].visible;
}
getDuration(millis: number): string {
const dur = {};
const units = [
{label: 'millis', mod: 100 }, // millis
{label: 'seconds', mod: 60 },
{label: 'minutes', mod: 60 },
{label: 'hours', mod: 24 },
{label: 'days', mod: 31 }
];
units.forEach(u => millis = (millis - (dur[u.label] = (millis % u.mod))) / u.mod);
const nonZero = (u) => { return dur[u.label]; };
dur.toString = () => {
return units
.reverse()
.filter(nonZero)
.map(u => dur[u.label] + ' ' + (dur[u.label] === 1 ? u.label.slice(0, -1) : u.label))
.join(', ');
};
return dur.toString();
}
}