-
Notifications
You must be signed in to change notification settings - Fork 795
/
Copy pathprogressTerminal.ts
80 lines (71 loc) · 2.71 KB
/
progressTerminal.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
/*---------------------------------------------------------
* Copyright 2025 The Go Authors. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for license information.
*--------------------------------------------------------*/
import vscode = require('vscode');
import { ProgressToken } from 'vscode-languageclient';
// ActiveProgressTerminals maps progress tokens to their corresponding terminals.
// Entries are added when terminals are created for workdone progress and
// deleted when closed by the user, which is interpreted as the user discarding
// any further information.
// There is no guarantee a terminal will remain available for the entire
// duration of a workdone progress notification.
// Logs can be appended to the terminal even after the workdone progress
// notification finishes, allowing responses from requests extending
// WorkDoneProgressOptions to be displayed in the same terminal.
export const ActiveProgressTerminals = new Map<ProgressToken, IProgressTerminal>();
export interface IProgressTerminal {
appendLine: (str: string) => void;
show: (preserveFocus?: boolean) => void;
exit: () => void;
}
export class ProgressTerminal implements IProgressTerminal {
private progressToken?: ProgressToken;
private term: vscode.Terminal;
private writeEmitter = new vscode.EventEmitter<string>();
// Buffer messages emitted before vscode is ready. VSC calls pty.open when it is ready.
private ptyReady = false;
private buf: string[] = [];
// Constructor function to stub during test.
static Open(name = 'progress', token?: ProgressToken): IProgressTerminal {
return new ProgressTerminal(name, token);
}
// ProgressTerminal created with token will be managed by map
// ActiveProgressTerminals.
private constructor(name: string, token?: ProgressToken) {
const pty: vscode.Pseudoterminal = {
onDidWrite: this.writeEmitter.event,
handleInput: () => this.exit(),
open: () => {
this.ptyReady = true;
this.buf.forEach((l) => this.writeEmitter.fire(l));
this.buf = [];
},
close: () => {
if (this.progressToken !== undefined) {
ActiveProgressTerminals.delete(this.progressToken);
}
}
};
this.term = vscode.window.createTerminal({ name: name, pty }); // TODO: iconPath
if (token !== undefined) {
this.progressToken = token;
ActiveProgressTerminals.set(this.progressToken, this);
}
}
appendLine(str: string) {
if (!str.endsWith('\n')) {
str += '\n';
}
str = str.replace(/\n/g, '\n\r'); // replaceAll('\n', '\n\r').
if (!this.ptyReady) {
this.buf.push(str); // print when `open` is called.
} else {
this.writeEmitter.fire(str);
}
}
show(preserveFocus?: boolean) {
this.term.show(preserveFocus);
}
exit() {}
}