-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Expand file tree
/
Copy pathProgressAddon.ts
More file actions
102 lines (89 loc) · 2.84 KB
/
Copy pathProgressAddon.ts
File metadata and controls
102 lines (89 loc) · 2.84 KB
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
/**
* Copyright (c) 2024 The xterm.js authors. All rights reserved.
* @license MIT
*/
import type { Terminal, ITerminalAddon, IDisposable } from '@xterm/xterm';
import type { ProgressAddon as IProgressApi, IProgressState } from '@xterm/addon-progress';
import type { Emitter, IEvent } from 'common/primitives/Event';
const enum ProgressType {
REMOVE = 0,
SET = 1,
ERROR = 2,
INDETERMINATE = 3,
PAUSE = 4
}
/**
* Strict integer parsing, only decimal digits allowed.
*/
function toInt(s: string): number {
let v = 0;
for (let i = 0; i < s.length; ++i) {
const c = s.charCodeAt(i);
if (c < 0x30 || 0x39 < c) {
return -1;
}
v = v * 10 + c - 48;
}
return v;
}
export class ProgressAddon implements ITerminalAddon, IProgressApi {
private _seqHandler: IDisposable | undefined;
private _st: ProgressType = ProgressType.REMOVE;
private _pr = 0;
// HACK: This uses ! to align with the API, this should be fixed when 5283 is resolved
private _onChange!: Emitter<IProgressState>;
public onChange!: IEvent<IProgressState>;
public dispose(): void {
this._seqHandler?.dispose();
this._onChange?.dispose();
}
public activate(terminal: Terminal): void {
this._seqHandler = terminal.parser.registerOscHandler(9, data => {
if (!data.startsWith('4;')) {
return false;
}
const parts = data.split(';');
if (parts.length > 3) {
return true; // faulty sequence, just exit
}
if (parts.length === 2) {
parts.push('');
}
const st = toInt(parts[1]);
const pr = toInt(parts[2]);
switch (st) {
case ProgressType.REMOVE:
this.progress = { state: st, value: 0 };
break;
case ProgressType.SET:
if (pr < 0) return true; // faulty sequence, just exit
this.progress = { state: st, value: pr };
break;
case ProgressType.ERROR:
case ProgressType.PAUSE:
if (pr < 0) return true; // faulty sequence, just exit
this.progress = { state: st, value: pr || this._pr };
break;
case ProgressType.INDETERMINATE:
this.progress = { state: st, value: this._pr };
break;
}
return true;
});
// FIXME: borrow emitter ctor from xterm, to be changed once #5283 is resolved
this._onChange = new (terminal as any)._core._onData.constructor();
this.onChange = this._onChange!.event;
}
public get progress(): IProgressState {
return { state: this._st, value: this._pr };
}
public set progress(progress: IProgressState) {
if (progress.state < 0 || progress.state > 4) {
console.warn(`progress state out of bounds, not applied`);
return;
}
this._st = progress.state;
this._pr = Math.min(Math.max(progress.value, 0), 100);
this._onChange?.fire({ state: this._st, value: this._pr });
}
}