@jupyterlite/terminal 0.2.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/lib/client.d.ts +5 -0
- package/lib/client.js +22 -3
- package/lib/index.js +37 -2
- package/lib/tokens.d.ts +15 -0
- package/package.json +15 -5
- package/src/client.ts +28 -4
- package/src/index.ts +47 -3
- package/src/tokens.ts +18 -0
package/README.md
CHANGED
|
@@ -46,6 +46,17 @@ Then build a new JupyterLite site:
|
|
|
46
46
|
jupyter lite build
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
## Version compatibility
|
|
50
|
+
|
|
51
|
+
Each `jupyterlite-terminal` release is built against a specific version of `cockle`. If you need to
|
|
52
|
+
include imports from both `jupyterlite-terminal` and `cockle`, such as if you are implementing
|
|
53
|
+
`cockle` external commands, you should ensure that you are using the correct version combination.
|
|
54
|
+
|
|
55
|
+
| `jupyterlite-terminal` | `cockle` | `jupyterlite-core` |
|
|
56
|
+
| ---------------------- | -------- | ------------------ |
|
|
57
|
+
| 1.0.0 | 1.0.0 | >= 0.6, < 0.7 |
|
|
58
|
+
| 0.2.2 | 0.1.3 | >= 0.6, < 0.7 |
|
|
59
|
+
|
|
49
60
|
## Contributing
|
|
50
61
|
|
|
51
62
|
### Development install
|
package/lib/client.d.ts
CHANGED
|
@@ -17,10 +17,15 @@ export declare class LiteTerminalAPIClient implements ILiteTerminalAPIClient {
|
|
|
17
17
|
readonly serverSettings: ServerConnection.ISettings;
|
|
18
18
|
startNew(options?: Terminal.ITerminal.IOptions): Promise<Terminal.IModel>;
|
|
19
19
|
listRunning(): Promise<Terminal.IModel[]>;
|
|
20
|
+
registerAlias(key: string, value: string): void;
|
|
21
|
+
registerEnvironmentVariable(key: string, value: string | undefined): void;
|
|
20
22
|
registerExternalCommand(options: IExternalCommand.IOptions): void;
|
|
21
23
|
shutdown(name: string): Promise<void>;
|
|
24
|
+
themeChange(isDarkMode?: boolean): void;
|
|
22
25
|
private get _models();
|
|
23
26
|
private _nextAvailableName;
|
|
27
|
+
private _aliases?;
|
|
28
|
+
private _environment?;
|
|
24
29
|
private _browsingContextId?;
|
|
25
30
|
private _externalCommands;
|
|
26
31
|
private _shellManager;
|
package/lib/client.js
CHANGED
|
@@ -39,6 +39,9 @@ export class LiteTerminalAPIClient {
|
|
|
39
39
|
baseUrl,
|
|
40
40
|
wasmBaseUrl: URLExt.join(baseUrl, 'extensions/@jupyterlite/terminal/static/wasm/'),
|
|
41
41
|
browsingContextId: this._browsingContextId,
|
|
42
|
+
aliases: this._aliases,
|
|
43
|
+
environment: this._environment,
|
|
44
|
+
externalCommands: this._externalCommands,
|
|
42
45
|
shellId: name,
|
|
43
46
|
shellManager: this._shellManager,
|
|
44
47
|
outputCallback: text => {
|
|
@@ -48,9 +51,6 @@ export class LiteTerminalAPIClient {
|
|
|
48
51
|
}
|
|
49
52
|
});
|
|
50
53
|
this._shells.set(name, shell);
|
|
51
|
-
for (const externalCommand of this._externalCommands) {
|
|
52
|
-
shell.registerExternalCommand(externalCommand);
|
|
53
|
-
}
|
|
54
54
|
// Hook to connect socket to shell.
|
|
55
55
|
const hook = async (shell, socket) => {
|
|
56
56
|
shell.socket = socket;
|
|
@@ -89,6 +89,18 @@ export class LiteTerminalAPIClient {
|
|
|
89
89
|
async listRunning() {
|
|
90
90
|
return this._models;
|
|
91
91
|
}
|
|
92
|
+
registerAlias(key, value) {
|
|
93
|
+
if (this._aliases === undefined) {
|
|
94
|
+
this._aliases = {};
|
|
95
|
+
}
|
|
96
|
+
this._aliases[key] = value;
|
|
97
|
+
}
|
|
98
|
+
registerEnvironmentVariable(key, value) {
|
|
99
|
+
if (this._environment === undefined) {
|
|
100
|
+
this._environment = {};
|
|
101
|
+
}
|
|
102
|
+
this._environment[key] = value;
|
|
103
|
+
}
|
|
92
104
|
registerExternalCommand(options) {
|
|
93
105
|
this._externalCommands.push(options);
|
|
94
106
|
}
|
|
@@ -102,6 +114,13 @@ export class LiteTerminalAPIClient {
|
|
|
102
114
|
shell.dispose();
|
|
103
115
|
}
|
|
104
116
|
}
|
|
117
|
+
themeChange(isDarkMode) {
|
|
118
|
+
for (const shell of this._shells.values()) {
|
|
119
|
+
// Can pass isDarkMode when cockle is released with PR #232.
|
|
120
|
+
//shell.themeChange(isDarkMode);
|
|
121
|
+
shell.themeChange();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
105
124
|
get _models() {
|
|
106
125
|
return Array.from(this._shells.keys(), name => {
|
|
107
126
|
return { name };
|
package/lib/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// Copyright (c) Jupyter Development Team.
|
|
2
2
|
// Distributed under the terms of the Modified BSD License.
|
|
3
|
-
import {
|
|
3
|
+
import { IThemeManager } from '@jupyterlab/apputils';
|
|
4
|
+
import { IServerSettings, ITerminalManager, ServerConnection, TerminalManager } from '@jupyterlab/services';
|
|
4
5
|
import { IServiceWorkerManager } from '@jupyterlite/server';
|
|
6
|
+
import { ISettingRegistry } from '@jupyterlab/settingregistry';
|
|
5
7
|
import { WebSocket } from 'mock-socket';
|
|
6
8
|
import { LiteTerminalAPIClient } from './client';
|
|
7
9
|
import { ILiteTerminalAPIClient } from './tokens';
|
|
@@ -60,10 +62,43 @@ const terminalServiceWorkerPlugin = {
|
|
|
60
62
|
}
|
|
61
63
|
}
|
|
62
64
|
};
|
|
65
|
+
const terminalThemeChangePlugin = {
|
|
66
|
+
id: '@jupyterlite/terminal:theme-change',
|
|
67
|
+
autoStart: true,
|
|
68
|
+
requires: [ILiteTerminalAPIClient, ISettingRegistry],
|
|
69
|
+
optional: [IThemeManager],
|
|
70
|
+
activate: (_, liteTerminalAPIClient, settingRegistry, themeManager) => {
|
|
71
|
+
// Cache latest terminal theme so can identify if it has changed.
|
|
72
|
+
let terminalTheme;
|
|
73
|
+
themeManager === null || themeManager === void 0 ? void 0 : themeManager.themeChanged.connect(async (_, changedArgs) => {
|
|
74
|
+
// An overall Lab theme change only affects terminals if the terminaTheme is 'inherit'.
|
|
75
|
+
if (terminalTheme === 'inherit') {
|
|
76
|
+
const isDarkMode = !themeManager.isLight(changedArgs.newValue);
|
|
77
|
+
liteTerminalAPIClient.themeChange(isDarkMode);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
// There is no signal for a terminal theme change, so use settings change.
|
|
81
|
+
settingRegistry
|
|
82
|
+
.load('@jupyterlab/terminal-extension:plugin')
|
|
83
|
+
.then(setting => {
|
|
84
|
+
terminalTheme = setting.composite.theme;
|
|
85
|
+
setting.changed.connect(() => {
|
|
86
|
+
// This signal is fired for any change to the terminal settings, not just the theme.
|
|
87
|
+
// Hence compare with the cached terminalTheme to identify if it has changed.
|
|
88
|
+
const newTerminalTheme = setting.composite.theme;
|
|
89
|
+
if (newTerminalTheme !== terminalTheme) {
|
|
90
|
+
liteTerminalAPIClient.themeChange();
|
|
91
|
+
terminalTheme = newTerminalTheme;
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
};
|
|
63
97
|
export default [
|
|
64
98
|
terminalClientPlugin,
|
|
65
99
|
terminalManagerPlugin,
|
|
66
|
-
terminalServiceWorkerPlugin
|
|
100
|
+
terminalServiceWorkerPlugin,
|
|
101
|
+
terminalThemeChangePlugin
|
|
67
102
|
];
|
|
68
103
|
// Export ILiteTerminalAPIClient so that other extensions can register external commands.
|
|
69
104
|
export { ILiteTerminalAPIClient };
|
package/lib/tokens.d.ts
CHANGED
|
@@ -11,8 +11,23 @@ export interface ILiteTerminalAPIClient extends Terminal.ITerminalAPIClient {
|
|
|
11
11
|
* Function that handles stdin requests received from service worker.
|
|
12
12
|
*/
|
|
13
13
|
handleStdin(request: IStdinRequest): Promise<IStdinReply>;
|
|
14
|
+
/**
|
|
15
|
+
* Register an alias that will be available in all terminals.
|
|
16
|
+
* If the key has already been registered, it will be overwritten.
|
|
17
|
+
*/
|
|
18
|
+
registerAlias(key: string, value: string): void;
|
|
19
|
+
/**
|
|
20
|
+
* Register an environment variable that will be available in all terminals.
|
|
21
|
+
* If the key has already been registered, it will be overwritten.
|
|
22
|
+
* A key with an undefined value will be deleted if already registered.
|
|
23
|
+
*/
|
|
24
|
+
registerEnvironmentVariable(key: string, value: string | undefined): void;
|
|
14
25
|
/**
|
|
15
26
|
* Register an external command that will be available in all terminals.
|
|
16
27
|
*/
|
|
17
28
|
registerExternalCommand(options: IExternalCommand.IOptions): void;
|
|
29
|
+
/**
|
|
30
|
+
* Inform all terminals that the theme has changed so that they can react to it if they wish.
|
|
31
|
+
*/
|
|
32
|
+
themeChange(isDarkMode?: boolean): void;
|
|
18
33
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jupyterlite/terminal",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "A terminal for JupyterLite",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jupyter",
|
|
@@ -59,9 +59,11 @@
|
|
|
59
59
|
"watch:labextension": "jupyter labextension watch ."
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
|
+
"@jupyterlab/apputils": "^4.5.3",
|
|
62
63
|
"@jupyterlab/coreutils": "^6.4.3",
|
|
63
64
|
"@jupyterlab/services": "^7.4.3",
|
|
64
|
-
"@
|
|
65
|
+
"@jupyterlab/settingregistry": "^4.4.3",
|
|
66
|
+
"@jupyterlite/cockle": "^1.0.0",
|
|
65
67
|
"@jupyterlite/contents": "^0.6.0",
|
|
66
68
|
"@jupyterlite/server": "^0.6.0",
|
|
67
69
|
"@lumino/coreutils": "^2.2.0",
|
|
@@ -74,8 +76,8 @@
|
|
|
74
76
|
"@types/json-schema": "^7.0.11",
|
|
75
77
|
"@types/react": "^18.0.26",
|
|
76
78
|
"@types/react-addons-linked-state-mixin": "^0.14.22",
|
|
77
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
78
|
-
"@typescript-eslint/parser": "^
|
|
79
|
+
"@typescript-eslint/eslint-plugin": "^7.16.1",
|
|
80
|
+
"@typescript-eslint/parser": "^7.16.1",
|
|
79
81
|
"css-loader": "^6.7.1",
|
|
80
82
|
"eslint": "^8.36.0",
|
|
81
83
|
"eslint-config-prettier": "^8.8.0",
|
|
@@ -92,7 +94,7 @@
|
|
|
92
94
|
"stylelint-csstree-validator": "^3.0.0",
|
|
93
95
|
"stylelint-prettier": "^4.0.0",
|
|
94
96
|
"ts-loader": "^9.5.2",
|
|
95
|
-
"typescript": "~5.0
|
|
97
|
+
"typescript": "~5.7.0",
|
|
96
98
|
"webpack": "^5.87.0",
|
|
97
99
|
"webpack-cli": "^5.1.4",
|
|
98
100
|
"yjs": "^13.5.0"
|
|
@@ -112,6 +114,14 @@
|
|
|
112
114
|
"extension": true,
|
|
113
115
|
"outputDir": "jupyterlite_terminal/labextension",
|
|
114
116
|
"sharedPackages": {
|
|
117
|
+
"@jupyterlab/apputils": {
|
|
118
|
+
"bundled": false,
|
|
119
|
+
"singleton": true
|
|
120
|
+
},
|
|
121
|
+
"@jupyterlab/settingregistry": {
|
|
122
|
+
"bundled": false,
|
|
123
|
+
"singleton": true
|
|
124
|
+
},
|
|
115
125
|
"@jupyterlite/contents": {
|
|
116
126
|
"bundled": false,
|
|
117
127
|
"singleton": true
|
package/src/client.ts
CHANGED
|
@@ -60,6 +60,9 @@ export class LiteTerminalAPIClient implements ILiteTerminalAPIClient {
|
|
|
60
60
|
'extensions/@jupyterlite/terminal/static/wasm/'
|
|
61
61
|
),
|
|
62
62
|
browsingContextId: this._browsingContextId,
|
|
63
|
+
aliases: this._aliases,
|
|
64
|
+
environment: this._environment,
|
|
65
|
+
externalCommands: this._externalCommands,
|
|
63
66
|
shellId: name,
|
|
64
67
|
shellManager: this._shellManager,
|
|
65
68
|
outputCallback: text => {
|
|
@@ -69,10 +72,6 @@ export class LiteTerminalAPIClient implements ILiteTerminalAPIClient {
|
|
|
69
72
|
});
|
|
70
73
|
this._shells.set(name, shell);
|
|
71
74
|
|
|
72
|
-
for (const externalCommand of this._externalCommands) {
|
|
73
|
-
shell.registerExternalCommand(externalCommand);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
75
|
// Hook to connect socket to shell.
|
|
77
76
|
const hook = async (
|
|
78
77
|
shell: Shell,
|
|
@@ -121,6 +120,20 @@ export class LiteTerminalAPIClient implements ILiteTerminalAPIClient {
|
|
|
121
120
|
return this._models;
|
|
122
121
|
}
|
|
123
122
|
|
|
123
|
+
registerAlias(key: string, value: string): void {
|
|
124
|
+
if (this._aliases === undefined) {
|
|
125
|
+
this._aliases = {};
|
|
126
|
+
}
|
|
127
|
+
this._aliases[key] = value;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
registerEnvironmentVariable(key: string, value: string | undefined): void {
|
|
131
|
+
if (this._environment === undefined) {
|
|
132
|
+
this._environment = {};
|
|
133
|
+
}
|
|
134
|
+
this._environment[key] = value;
|
|
135
|
+
}
|
|
136
|
+
|
|
124
137
|
registerExternalCommand(options: IExternalCommand.IOptions): void {
|
|
125
138
|
this._externalCommands.push(options);
|
|
126
139
|
}
|
|
@@ -135,6 +148,15 @@ export class LiteTerminalAPIClient implements ILiteTerminalAPIClient {
|
|
|
135
148
|
}
|
|
136
149
|
}
|
|
137
150
|
|
|
151
|
+
themeChange(isDarkMode?: boolean): void {
|
|
152
|
+
for (const shell of this._shells.values()) {
|
|
153
|
+
// Can pass isDarkMode when cockle is released with PR #232.
|
|
154
|
+
//shell.themeChange(isDarkMode);
|
|
155
|
+
|
|
156
|
+
shell.themeChange();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
138
160
|
private get _models(): Terminal.IModel[] {
|
|
139
161
|
return Array.from(this._shells.keys(), name => {
|
|
140
162
|
return { name };
|
|
@@ -150,6 +172,8 @@ export class LiteTerminalAPIClient implements ILiteTerminalAPIClient {
|
|
|
150
172
|
}
|
|
151
173
|
}
|
|
152
174
|
|
|
175
|
+
private _aliases?: { [key: string]: string };
|
|
176
|
+
private _environment?: { [key: string]: string | undefined };
|
|
153
177
|
private _browsingContextId?: string;
|
|
154
178
|
private _externalCommands: IExternalCommand.IOptions[] = [];
|
|
155
179
|
private _shellManager: IShellManager;
|
package/src/index.ts
CHANGED
|
@@ -5,15 +5,17 @@ import {
|
|
|
5
5
|
JupyterFrontEnd,
|
|
6
6
|
JupyterFrontEndPlugin
|
|
7
7
|
} from '@jupyterlab/application';
|
|
8
|
+
import { IThemeManager } from '@jupyterlab/apputils';
|
|
8
9
|
import {
|
|
10
|
+
IServerSettings,
|
|
9
11
|
ITerminalManager,
|
|
12
|
+
ServerConnection,
|
|
10
13
|
ServiceManagerPlugin,
|
|
11
14
|
Terminal,
|
|
12
|
-
ServerConnection,
|
|
13
|
-
IServerSettings,
|
|
14
15
|
TerminalManager
|
|
15
16
|
} from '@jupyterlab/services';
|
|
16
17
|
import { IServiceWorkerManager } from '@jupyterlite/server';
|
|
18
|
+
import { ISettingRegistry } from '@jupyterlab/settingregistry';
|
|
17
19
|
|
|
18
20
|
import { WebSocket } from 'mock-socket';
|
|
19
21
|
|
|
@@ -94,10 +96,52 @@ const terminalServiceWorkerPlugin: JupyterFrontEndPlugin<void> = {
|
|
|
94
96
|
}
|
|
95
97
|
};
|
|
96
98
|
|
|
99
|
+
const terminalThemeChangePlugin: JupyterFrontEndPlugin<void> = {
|
|
100
|
+
id: '@jupyterlite/terminal:theme-change',
|
|
101
|
+
autoStart: true,
|
|
102
|
+
requires: [ILiteTerminalAPIClient, ISettingRegistry],
|
|
103
|
+
optional: [IThemeManager],
|
|
104
|
+
activate: (
|
|
105
|
+
_: JupyterFrontEnd,
|
|
106
|
+
liteTerminalAPIClient: ILiteTerminalAPIClient,
|
|
107
|
+
settingRegistry: ISettingRegistry,
|
|
108
|
+
themeManager?: IThemeManager
|
|
109
|
+
): void => {
|
|
110
|
+
// Cache latest terminal theme so can identify if it has changed.
|
|
111
|
+
let terminalTheme: string | undefined;
|
|
112
|
+
|
|
113
|
+
themeManager?.themeChanged.connect(async (_, changedArgs) => {
|
|
114
|
+
// An overall Lab theme change only affects terminals if the terminaTheme is 'inherit'.
|
|
115
|
+
if (terminalTheme === 'inherit') {
|
|
116
|
+
const isDarkMode = !themeManager.isLight(changedArgs.newValue);
|
|
117
|
+
liteTerminalAPIClient.themeChange(isDarkMode);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// There is no signal for a terminal theme change, so use settings change.
|
|
122
|
+
settingRegistry
|
|
123
|
+
.load('@jupyterlab/terminal-extension:plugin')
|
|
124
|
+
.then(setting => {
|
|
125
|
+
terminalTheme = setting.composite.theme as string;
|
|
126
|
+
|
|
127
|
+
setting.changed.connect(() => {
|
|
128
|
+
// This signal is fired for any change to the terminal settings, not just the theme.
|
|
129
|
+
// Hence compare with the cached terminalTheme to identify if it has changed.
|
|
130
|
+
const newTerminalTheme = setting.composite.theme as string;
|
|
131
|
+
if (newTerminalTheme !== terminalTheme) {
|
|
132
|
+
liteTerminalAPIClient.themeChange();
|
|
133
|
+
terminalTheme = newTerminalTheme;
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
97
140
|
export default [
|
|
98
141
|
terminalClientPlugin,
|
|
99
142
|
terminalManagerPlugin,
|
|
100
|
-
terminalServiceWorkerPlugin
|
|
143
|
+
terminalServiceWorkerPlugin,
|
|
144
|
+
terminalThemeChangePlugin
|
|
101
145
|
];
|
|
102
146
|
|
|
103
147
|
// Export ILiteTerminalAPIClient so that other extensions can register external commands.
|
package/src/tokens.ts
CHANGED
|
@@ -21,8 +21,26 @@ export interface ILiteTerminalAPIClient extends Terminal.ITerminalAPIClient {
|
|
|
21
21
|
*/
|
|
22
22
|
handleStdin(request: IStdinRequest): Promise<IStdinReply>;
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Register an alias that will be available in all terminals.
|
|
26
|
+
* If the key has already been registered, it will be overwritten.
|
|
27
|
+
*/
|
|
28
|
+
registerAlias(key: string, value: string): void;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Register an environment variable that will be available in all terminals.
|
|
32
|
+
* If the key has already been registered, it will be overwritten.
|
|
33
|
+
* A key with an undefined value will be deleted if already registered.
|
|
34
|
+
*/
|
|
35
|
+
registerEnvironmentVariable(key: string, value: string | undefined): void;
|
|
36
|
+
|
|
24
37
|
/**
|
|
25
38
|
* Register an external command that will be available in all terminals.
|
|
26
39
|
*/
|
|
27
40
|
registerExternalCommand(options: IExternalCommand.IOptions): void;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Inform all terminals that the theme has changed so that they can react to it if they wish.
|
|
44
|
+
*/
|
|
45
|
+
themeChange(isDarkMode?: boolean): void;
|
|
28
46
|
}
|