jupyterlab_open_in_terminal_extension 1.0.3 → 1.0.10
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 +7 -3
- package/lib/index.js +24 -23
- package/package.json +2 -1
- package/src/__tests__/jupyterlab_open_in_terminal_extension.spec.ts +5 -6
- package/src/index.ts +24 -33
package/README.md
CHANGED
|
@@ -8,14 +8,18 @@
|
|
|
8
8
|
[](https://kolomolo.com)
|
|
9
9
|
[](https://www.paypal.com/donate/?hosted_button_id=B4KPBJDLLXTSA)
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
> [!TIP]
|
|
12
|
+
> This extension is part of the [stellars_jupyterlab_extensions](https://github.com/stellarshenson/stellars_jupyterlab_extensions) metapackage. Install all Stellars extensions at once: `pip install stellars_jupyterlab_extensions`
|
|
13
|
+
|
|
14
|
+
Open any folder or file from the file browser directly in a terminal. Right-click on a folder and select "Open Location in Terminal" to launch a new terminal session with that directory as the working directory. Right-click on a file to open a terminal in its parent folder.
|
|
12
15
|
|
|
13
16
|

|
|
14
17
|
|
|
15
18
|
## Features
|
|
16
19
|
|
|
17
|
-
- **Context menu on folders** - Right-click any folder
|
|
18
|
-
- **
|
|
20
|
+
- **Context menu on folders** - Right-click any folder to open a terminal at that location
|
|
21
|
+
- **Context menu on files** - Right-click any file to open a terminal in its parent folder
|
|
22
|
+
- **Opens terminal at selected path** - New terminal session starts with cwd set to the target folder
|
|
19
23
|
- **Seamless integration** - Works with JupyterLab's native terminal
|
|
20
24
|
|
|
21
25
|
## Requirements
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { IDefaultFileBrowser } from '@jupyterlab/filebrowser';
|
|
2
2
|
import { showErrorMessage } from '@jupyterlab/apputils';
|
|
3
3
|
import { terminalIcon } from '@jupyterlab/ui-components';
|
|
4
|
+
import { PathExt } from '@jupyterlab/coreutils';
|
|
4
5
|
/**
|
|
5
6
|
* The command ID for opening a terminal at a directory.
|
|
6
7
|
*/
|
|
@@ -18,35 +19,35 @@ const plugin = {
|
|
|
18
19
|
const { commands, serviceManager } = app;
|
|
19
20
|
// Add the command
|
|
20
21
|
commands.addCommand(COMMAND_ID, {
|
|
21
|
-
label: 'Open in Terminal',
|
|
22
|
-
caption: 'Open a terminal at this
|
|
22
|
+
label: 'Open Location in Terminal',
|
|
23
|
+
caption: 'Open a terminal at this location',
|
|
23
24
|
icon: terminalIcon,
|
|
24
25
|
isVisible: () => {
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
if (item.done || !item.value) {
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
return item.value.type === 'directory';
|
|
26
|
+
// Always visible - works for files, directories, and empty area
|
|
27
|
+
return true;
|
|
31
28
|
},
|
|
32
29
|
execute: async () => {
|
|
33
30
|
const item = fileBrowser.selectedItems().next();
|
|
31
|
+
// Get the target path
|
|
32
|
+
let targetPath;
|
|
34
33
|
if (item.done || !item.value) {
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
// No selection - use current directory from file browser
|
|
35
|
+
targetPath = fileBrowser.model.path;
|
|
37
36
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
else {
|
|
38
|
+
const selectedItem = item.value;
|
|
39
|
+
if (selectedItem.type === 'directory') {
|
|
40
|
+
targetPath = selectedItem.path;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
// For files, get the parent directory
|
|
44
|
+
targetPath = PathExt.dirname(selectedItem.path);
|
|
45
|
+
}
|
|
43
46
|
}
|
|
44
|
-
// Get the path - this is relative to the server root
|
|
45
|
-
const relativePath = selectedItem.path;
|
|
46
47
|
try {
|
|
47
|
-
// Create a new terminal session with cwd set to the
|
|
48
|
+
// Create a new terminal session with cwd set to the target directory
|
|
48
49
|
const session = await serviceManager.terminals.startNew({
|
|
49
|
-
cwd:
|
|
50
|
+
cwd: targetPath
|
|
50
51
|
});
|
|
51
52
|
// Create the terminal widget
|
|
52
53
|
const terminal = await commands.execute('terminal:create-new', {
|
|
@@ -58,18 +59,18 @@ const plugin = {
|
|
|
58
59
|
name: session.name
|
|
59
60
|
});
|
|
60
61
|
}
|
|
61
|
-
console.log(`Opened terminal "${session.name}" at path: ${
|
|
62
|
+
console.log(`Opened terminal "${session.name}" at path: ${targetPath}`);
|
|
62
63
|
}
|
|
63
64
|
catch (error) {
|
|
64
65
|
console.error('Failed to open terminal:', error);
|
|
65
|
-
await showErrorMessage('Terminal Error', `Failed to open terminal at: ${
|
|
66
|
+
await showErrorMessage('Terminal Error', `Failed to open terminal at: ${targetPath}\nError: ${error}`);
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
});
|
|
69
|
-
// Add context menu item for
|
|
70
|
+
// Add context menu item for file browser (works for files, folders, and empty area)
|
|
70
71
|
app.contextMenu.addItem({
|
|
71
72
|
command: COMMAND_ID,
|
|
72
|
-
selector: '.jp-DirListing-
|
|
73
|
+
selector: '.jp-DirListing-content',
|
|
73
74
|
rank: 3
|
|
74
75
|
});
|
|
75
76
|
console.log(`Command registered: ${COMMAND_ID}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jupyterlab_open_in_terminal_extension",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"description": "Jupyterlab extension that adds item to the context menu in the file browser to open folder in terminal",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jupyter",
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"@jupyterlab/application": "^4.0.0",
|
|
60
60
|
"@jupyterlab/apputils": "^4.0.0",
|
|
61
|
+
"@jupyterlab/coreutils": "^6.0.0",
|
|
61
62
|
"@jupyterlab/filebrowser": "^4.0.0",
|
|
62
63
|
"@jupyterlab/services": "^7.0.0",
|
|
63
64
|
"@jupyterlab/ui-components": "^4.0.0"
|
|
@@ -17,14 +17,13 @@ describe('jupyterlab_open_in_terminal_extension', () => {
|
|
|
17
17
|
expect(pluginId).toContain(':plugin');
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
-
it('should target
|
|
21
|
-
const selector = '.jp-DirListing-
|
|
22
|
-
expect(selector).
|
|
23
|
-
expect(selector).toContain('.jp-DirListing-item');
|
|
20
|
+
it('should target file browser content area', () => {
|
|
21
|
+
const selector = '.jp-DirListing-content';
|
|
22
|
+
expect(selector).toBe('.jp-DirListing-content');
|
|
24
23
|
});
|
|
25
24
|
|
|
26
25
|
it('should have correct menu label', () => {
|
|
27
|
-
const label = 'Open in Terminal';
|
|
28
|
-
expect(label).toBe('Open in Terminal');
|
|
26
|
+
const label = 'Open Location in Terminal';
|
|
27
|
+
expect(label).toBe('Open Location in Terminal');
|
|
29
28
|
});
|
|
30
29
|
});
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
import { IDefaultFileBrowser } from '@jupyterlab/filebrowser';
|
|
6
6
|
import { showErrorMessage } from '@jupyterlab/apputils';
|
|
7
7
|
import { terminalIcon } from '@jupyterlab/ui-components';
|
|
8
|
+
import { PathExt } from '@jupyterlab/coreutils';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* The command ID for opening a terminal at a directory.
|
|
@@ -29,45 +30,35 @@ const plugin: JupyterFrontEndPlugin<void> = {
|
|
|
29
30
|
|
|
30
31
|
// Add the command
|
|
31
32
|
commands.addCommand(COMMAND_ID, {
|
|
32
|
-
label: 'Open in Terminal',
|
|
33
|
-
caption: 'Open a terminal at this
|
|
33
|
+
label: 'Open Location in Terminal',
|
|
34
|
+
caption: 'Open a terminal at this location',
|
|
34
35
|
icon: terminalIcon,
|
|
35
36
|
isVisible: () => {
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
if (item.done || !item.value) {
|
|
39
|
-
return false;
|
|
40
|
-
}
|
|
41
|
-
return item.value.type === 'directory';
|
|
37
|
+
// Always visible - works for files, directories, and empty area
|
|
38
|
+
return true;
|
|
42
39
|
},
|
|
43
40
|
execute: async () => {
|
|
44
41
|
const item = fileBrowser.selectedItems().next();
|
|
45
|
-
if (item.done || !item.value) {
|
|
46
|
-
await showErrorMessage(
|
|
47
|
-
'No Selection',
|
|
48
|
-
'No folder selected in file browser.'
|
|
49
|
-
);
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
42
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
)
|
|
61
|
-
|
|
43
|
+
// Get the target path
|
|
44
|
+
let targetPath: string;
|
|
45
|
+
if (item.done || !item.value) {
|
|
46
|
+
// No selection - use current directory from file browser
|
|
47
|
+
targetPath = fileBrowser.model.path;
|
|
48
|
+
} else {
|
|
49
|
+
const selectedItem = item.value;
|
|
50
|
+
if (selectedItem.type === 'directory') {
|
|
51
|
+
targetPath = selectedItem.path;
|
|
52
|
+
} else {
|
|
53
|
+
// For files, get the parent directory
|
|
54
|
+
targetPath = PathExt.dirname(selectedItem.path);
|
|
55
|
+
}
|
|
62
56
|
}
|
|
63
57
|
|
|
64
|
-
// Get the path - this is relative to the server root
|
|
65
|
-
const relativePath = selectedItem.path;
|
|
66
|
-
|
|
67
58
|
try {
|
|
68
|
-
// Create a new terminal session with cwd set to the
|
|
59
|
+
// Create a new terminal session with cwd set to the target directory
|
|
69
60
|
const session = await serviceManager.terminals.startNew({
|
|
70
|
-
cwd:
|
|
61
|
+
cwd: targetPath
|
|
71
62
|
});
|
|
72
63
|
|
|
73
64
|
// Create the terminal widget
|
|
@@ -83,22 +74,22 @@ const plugin: JupyterFrontEndPlugin<void> = {
|
|
|
83
74
|
}
|
|
84
75
|
|
|
85
76
|
console.log(
|
|
86
|
-
`Opened terminal "${session.name}" at path: ${
|
|
77
|
+
`Opened terminal "${session.name}" at path: ${targetPath}`
|
|
87
78
|
);
|
|
88
79
|
} catch (error) {
|
|
89
80
|
console.error('Failed to open terminal:', error);
|
|
90
81
|
await showErrorMessage(
|
|
91
82
|
'Terminal Error',
|
|
92
|
-
`Failed to open terminal at: ${
|
|
83
|
+
`Failed to open terminal at: ${targetPath}\nError: ${error}`
|
|
93
84
|
);
|
|
94
85
|
}
|
|
95
86
|
}
|
|
96
87
|
});
|
|
97
88
|
|
|
98
|
-
// Add context menu item for
|
|
89
|
+
// Add context menu item for file browser (works for files, folders, and empty area)
|
|
99
90
|
app.contextMenu.addItem({
|
|
100
91
|
command: COMMAND_ID,
|
|
101
|
-
selector: '.jp-DirListing-
|
|
92
|
+
selector: '.jp-DirListing-content',
|
|
102
93
|
rank: 3
|
|
103
94
|
});
|
|
104
95
|
|