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 CHANGED
@@ -8,14 +8,18 @@
8
8
  [![Brought To You By KOLOMOLO](https://img.shields.io/badge/Brought%20To%20You%20By-KOLOMOLO-00ffff?style=flat)](https://kolomolo.com)
9
9
  [![Donate PayPal](https://img.shields.io/badge/Donate-PayPal-blue?style=flat)](https://www.paypal.com/donate/?hosted_button_id=B4KPBJDLLXTSA)
10
10
 
11
- Open any folder from the file browser directly in a terminal. Right-click on a folder and select "Open in Terminal" to launch a new terminal session with that directory as the working directory.
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
  ![Open in Terminal](.resources/screenshot.png)
14
17
 
15
18
  ## Features
16
19
 
17
- - **Context menu on folders** - Right-click any folder in the file browser to reveal "Open in Terminal" option with terminal icon
18
- - **Opens terminal at selected path** - New terminal session starts with cwd set to the selected folder
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 directory',
22
+ label: 'Open Location in Terminal',
23
+ caption: 'Open a terminal at this location',
23
24
  icon: terminalIcon,
24
25
  isVisible: () => {
25
- // Only show for directories
26
- const item = fileBrowser.selectedItems().next();
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
- await showErrorMessage('No Selection', 'No folder selected in file browser.');
36
- return;
34
+ // No selection - use current directory from file browser
35
+ targetPath = fileBrowser.model.path;
37
36
  }
38
- const selectedItem = item.value;
39
- // Only allow directories
40
- if (selectedItem.type !== 'directory') {
41
- await showErrorMessage('Not a Directory', 'Please select a directory to open in terminal.');
42
- return;
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 selected directory
48
+ // Create a new terminal session with cwd set to the target directory
48
49
  const session = await serviceManager.terminals.startNew({
49
- cwd: relativePath
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: ${relativePath}`);
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: ${relativePath}\nError: ${error}`);
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 directories in file browser
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-item[data-isdir="true"]',
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",
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 directory items only', () => {
21
- const selector = '.jp-DirListing-item[data-isdir="true"]';
22
- expect(selector).toContain('data-isdir="true"');
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 directory',
33
+ label: 'Open Location in Terminal',
34
+ caption: 'Open a terminal at this location',
34
35
  icon: terminalIcon,
35
36
  isVisible: () => {
36
- // Only show for directories
37
- const item = fileBrowser.selectedItems().next();
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
- const selectedItem = item.value;
54
-
55
- // Only allow directories
56
- if (selectedItem.type !== 'directory') {
57
- await showErrorMessage(
58
- 'Not a Directory',
59
- 'Please select a directory to open in terminal.'
60
- );
61
- return;
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 selected directory
59
+ // Create a new terminal session with cwd set to the target directory
69
60
  const session = await serviceManager.terminals.startNew({
70
- cwd: relativePath
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: ${relativePath}`
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: ${relativePath}\nError: ${error}`
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 directories in file browser
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-item[data-isdir="true"]',
92
+ selector: '.jp-DirListing-content',
102
93
  rank: 3
103
94
  });
104
95