xtralab 0.15.0 → 0.15.2
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 +65 -30
- package/lib/about/icons.d.ts +0 -5
- package/lib/about/icons.js +0 -5
- package/lib/about/index.d.ts +4 -8
- package/lib/about/index.js +6 -17
- package/lib/agentSessions.d.ts +9 -29
- package/lib/agentSessions.js +2 -7
- package/lib/askAgent/editorSelection.d.ts +20 -26
- package/lib/askAgent/editorSelection.js +11 -26
- package/lib/askAgent/icons.d.ts +2 -3
- package/lib/askAgent/icons.js +2 -3
- package/lib/askAgent/index.d.ts +4 -26
- package/lib/askAgent/index.js +54 -158
- package/lib/askAgent/popup.d.ts +12 -16
- package/lib/askAgent/popup.js +18 -37
- package/lib/askAgent/prompt.d.ts +3 -5
- package/lib/askAgent/prompt.js +6 -19
- package/lib/askAgent/queue.d.ts +11 -21
- package/lib/askAgent/queue.js +9 -19
- package/lib/askAgent/queuePanel.d.ts +13 -18
- package/lib/askAgent/queuePanel.js +15 -37
- package/lib/askAgent/targetPicker.d.ts +2 -9
- package/lib/askAgent/targetPicker.js +6 -11
- package/lib/askAgent/tokens.d.ts +32 -46
- package/lib/askAgent/tokens.js +4 -6
- package/lib/commandBar/index.d.ts +4 -13
- package/lib/commandBar/index.js +21 -39
- package/lib/customPanel/index.js +15 -0
- package/lib/editorBreadcrumbs/index.d.ts +3 -6
- package/lib/editorBreadcrumbs/index.js +10 -6
- package/lib/editorBreadcrumbs/widget.d.ts +17 -4
- package/lib/editorBreadcrumbs/widget.js +11 -17
- package/lib/editorIndent/index.d.ts +4 -12
- package/lib/editorIndent/index.js +8 -23
- package/lib/fileBrowser/commands.d.ts +29 -19
- package/lib/fileBrowser/commands.js +83 -97
- package/lib/fileBrowser/contents.d.ts +3 -0
- package/lib/fileBrowser/dragAndDrop.d.ts +17 -4
- package/lib/fileBrowser/dragAndDrop.js +2 -7
- package/lib/fileBrowser/fileBrowser.d.ts +19 -9
- package/lib/fileBrowser/fileBrowser.js +70 -222
- package/lib/fileBrowser/gitStatus.d.ts +16 -10
- package/lib/fileBrowser/gitStatus.js +31 -30
- package/lib/fileBrowser/gitignore.d.ts +4 -17
- package/lib/fileBrowser/gitignore.js +4 -25
- package/lib/fileBrowser/icons.d.ts +7 -17
- package/lib/fileBrowser/icons.js +25 -80
- package/lib/fileBrowser/index.js +2 -4
- package/lib/fileBrowser/widget.d.ts +141 -48
- package/lib/fileBrowser/widget.js +102 -4
- package/lib/fileTypeIcons/index.js +0 -10
- package/lib/git/api.d.ts +5 -13
- package/lib/git/api.js +10 -36
- package/lib/git/askRequest.d.ts +4 -8
- package/lib/git/askRequest.js +6 -20
- package/lib/git/commands.d.ts +45 -5
- package/lib/git/commands.js +20 -13
- package/lib/git/diffModel.js +4 -0
- package/lib/git/diffPreferences.d.ts +90 -0
- package/lib/git/diffPreferences.js +107 -0
- package/lib/git/diffProvider.js +10 -2
- package/lib/git/diffSurface.d.ts +64 -63
- package/lib/git/diffSurface.js +72 -213
- package/lib/git/diffTheme.d.ts +7 -0
- package/lib/git/diffTheme.js +23 -0
- package/lib/git/diffWidget.d.ts +70 -14
- package/lib/git/diffWidget.js +100 -94
- package/lib/git/imageDiff.d.ts +14 -6
- package/lib/git/imageDiff.js +19 -75
- package/lib/git/index.d.ts +0 -3
- package/lib/git/index.js +44 -10
- package/lib/git/notebookDiff.d.ts +110 -33
- package/lib/git/notebookDiff.js +55 -197
- package/lib/git/tokens.d.ts +73 -31
- package/lib/git/tokens.js +2 -3
- package/lib/highlight/index.d.ts +4 -10
- package/lib/highlight/index.js +10 -41
- package/lib/index.d.ts +0 -9
- package/lib/index.js +0 -9
- package/lib/launcher/agents.d.ts +55 -51
- package/lib/launcher/agents.js +15 -57
- package/lib/launcher/availability.d.ts +3 -9
- package/lib/launcher/availability.js +3 -9
- package/lib/launcher/commands.d.ts +7 -32
- package/lib/launcher/commands.js +14 -45
- package/lib/launcher/dashboard.d.ts +19 -24
- package/lib/launcher/dashboard.js +21 -67
- package/lib/launcher/editorRegistry.d.ts +10 -22
- package/lib/launcher/editorRegistry.js +14 -18
- package/lib/launcher/editors.d.ts +39 -45
- package/lib/launcher/editors.js +8 -34
- package/lib/launcher/icons.d.ts +0 -12
- package/lib/launcher/icons.js +5 -39
- package/lib/launcher/index.js +12 -55
- package/lib/launcher/invocation.d.ts +4 -10
- package/lib/launcher/invocation.js +7 -22
- package/lib/launcher/registry.d.ts +9 -7
- package/lib/launcher/registry.js +9 -7
- package/lib/launcher/tokens.d.ts +10 -22
- package/lib/launcher/tokens.js +5 -8
- package/lib/menuBar/index.d.ts +3 -10
- package/lib/menuBar/index.js +11 -28
- package/lib/menus/index.d.ts +3 -9
- package/lib/menus/index.js +14 -30
- package/lib/omnibox/files.d.ts +2 -4
- package/lib/omnibox/files.js +5 -11
- package/lib/omnibox/index.d.ts +4 -14
- package/lib/omnibox/index.js +9 -27
- package/lib/omnibox/model.d.ts +38 -10
- package/lib/omnibox/model.js +15 -33
- package/lib/omnibox/recents.d.ts +15 -17
- package/lib/omnibox/recents.js +12 -17
- package/lib/omnibox/tokens.d.ts +5 -10
- package/lib/omnibox/tokens.js +2 -6
- package/lib/omnibox/widget.d.ts +11 -7
- package/lib/omnibox/widget.js +8 -16
- package/lib/searchReplace/index.d.ts +4 -20
- package/lib/searchReplace/index.js +7 -27
- package/lib/showOutput/index.d.ts +3 -12
- package/lib/showOutput/index.js +6 -22
- package/lib/sidebar/index.d.ts +4 -7
- package/lib/sidebar/index.js +5 -12
- package/lib/terminalNotifications/index.d.ts +4 -10
- package/lib/terminalNotifications/index.js +6 -20
- package/lib/terminals/agentTerminals.d.ts +12 -5
- package/lib/terminals/agentTerminals.js +25 -44
- package/lib/terminals/detection.d.ts +4 -8
- package/lib/terminals/detection.js +4 -8
- package/lib/terminals/index.d.ts +0 -35
- package/lib/terminals/index.js +12 -101
- package/lib/terminals/model.d.ts +64 -139
- package/lib/terminals/model.js +80 -220
- package/lib/terminals/tokens.d.ts +11 -22
- package/lib/terminals/tokens.js +2 -2
- package/lib/terminals/widget.d.ts +43 -13
- package/lib/terminals/widget.js +33 -18
- package/lib/topBar/icons.d.ts +3 -8
- package/lib/topBar/icons.js +3 -8
- package/lib/topBar/index.d.ts +4 -11
- package/lib/topBar/index.js +10 -38
- package/lib/walkthrough/index.d.ts +4 -9
- package/lib/walkthrough/index.js +6 -20
- package/lib/walkthrough/panel.d.ts +40 -9
- package/lib/walkthrough/panel.js +4 -10
- package/package.json +5 -3
- package/schema/git-diff-preferences.json +42 -0
- package/src/about/icons.ts +0 -5
- package/src/about/index.tsx +6 -17
- package/src/agentSessions.ts +9 -29
- package/src/askAgent/editorSelection.ts +22 -29
- package/src/askAgent/icons.ts +2 -3
- package/src/askAgent/index.ts +54 -158
- package/src/askAgent/popup.tsx +23 -45
- package/src/askAgent/prompt.ts +6 -19
- package/src/askAgent/queue.ts +13 -24
- package/src/askAgent/queuePanel.tsx +21 -46
- package/src/askAgent/targetPicker.tsx +5 -15
- package/src/askAgent/tokens.ts +32 -46
- package/src/commandBar/index.ts +24 -39
- package/src/customPanel/index.ts +15 -0
- package/src/editorBreadcrumbs/index.ts +10 -6
- package/src/editorBreadcrumbs/widget.ts +23 -17
- package/src/editorIndent/index.ts +17 -23
- package/src/fileBrowser/commands.ts +119 -96
- package/src/fileBrowser/contents.ts +3 -0
- package/src/fileBrowser/dragAndDrop.ts +17 -7
- package/src/fileBrowser/fileBrowser.tsx +86 -230
- package/src/fileBrowser/gitStatus.ts +36 -33
- package/src/fileBrowser/gitignore.ts +4 -25
- package/src/fileBrowser/icons.ts +25 -80
- package/src/fileBrowser/index.ts +2 -4
- package/src/fileBrowser/widget.tsx +171 -50
- package/src/fileTypeIcons/index.ts +0 -10
- package/src/git/api.ts +10 -36
- package/src/git/askRequest.ts +6 -20
- package/src/git/commands.ts +83 -11
- package/src/git/diffModel.ts +25 -0
- package/src/git/diffPreferences.ts +192 -0
- package/src/git/diffProvider.tsx +11 -2
- package/src/git/diffSurface.tsx +165 -286
- package/src/git/diffTheme.ts +24 -0
- package/src/git/diffWidget.tsx +194 -134
- package/src/git/imageDiff.tsx +56 -84
- package/src/git/index.ts +54 -10
- package/src/git/notebookDiff.tsx +214 -240
- package/src/git/tokens.ts +73 -31
- package/src/highlight/index.ts +10 -41
- package/src/index.ts +0 -9
- package/src/launcher/agents.ts +64 -95
- package/src/launcher/availability.ts +3 -9
- package/src/launcher/commands.ts +14 -51
- package/src/launcher/dashboard.tsx +49 -88
- package/src/launcher/editorRegistry.ts +21 -29
- package/src/launcher/editors.ts +39 -58
- package/src/launcher/icons.ts +5 -39
- package/src/launcher/index.ts +12 -55
- package/src/launcher/invocation.ts +7 -22
- package/src/launcher/registry.ts +9 -7
- package/src/launcher/tokens.ts +10 -22
- package/src/menuBar/index.ts +11 -28
- package/src/menus/index.ts +14 -30
- package/src/omnibox/files.ts +10 -14
- package/src/omnibox/index.ts +9 -27
- package/src/omnibox/model.ts +50 -38
- package/src/omnibox/recents.ts +17 -22
- package/src/omnibox/tokens.ts +5 -10
- package/src/omnibox/widget.tsx +14 -19
- package/src/searchReplace/index.ts +7 -27
- package/src/showOutput/index.ts +6 -22
- package/src/sidebar/index.ts +20 -12
- package/src/terminalNotifications/index.ts +42 -25
- package/src/terminals/agentTerminals.ts +25 -49
- package/src/terminals/detection.ts +4 -8
- package/src/terminals/index.ts +12 -101
- package/src/terminals/model.ts +130 -246
- package/src/terminals/tokens.ts +11 -22
- package/src/terminals/widget.tsx +48 -31
- package/src/topBar/icons.ts +3 -8
- package/src/topBar/index.ts +21 -44
- package/src/walkthrough/index.ts +6 -20
- package/src/walkthrough/panel.ts +40 -10
- package/style/about.css +2 -7
- package/style/askAgent.css +8 -40
- package/style/base.css +9 -45
- package/style/chrome.css +108 -308
- package/style/commandBar.css +4 -20
- package/style/customPanel.css +1 -4
- package/style/git.css +26 -186
- package/style/highlight.css +1 -3
- package/style/launcher.css +6 -70
- package/style/omnibox.css +2 -14
- package/style/showOutput.css +0 -6
- package/style/sidebar.css +29 -9
- package/style/tabs.css +5 -13
- package/style/terminals.css +6 -53
- package/style/topBar.css +2 -22
- package/style/walkthrough.css +0 -8
package/lib/omnibox/files.js
CHANGED
|
@@ -2,13 +2,9 @@ import { URLExt } from '@jupyterlab/coreutils';
|
|
|
2
2
|
import { ServerConnection } from '@jupyterlab/services';
|
|
3
3
|
/**
|
|
4
4
|
* Fetch and flatten the workspace file list from `jupyterlab-quickopen`'s
|
|
5
|
-
* server endpoint
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* listing honors the same server-side `.gitignore` filtering quickopen does
|
|
9
|
-
* (xtralab ships `respectGitignore: true`) in a single request. The endpoint
|
|
10
|
-
* only exists when quickopen's server extension is installed and the server
|
|
11
|
-
* reads a local filesystem; callers treat a rejection as "no file results".
|
|
5
|
+
* server endpoint, which applies server-side `.gitignore` filtering in one
|
|
6
|
+
* request. Rejects when the server extension is absent; callers treat that as
|
|
7
|
+
* "no file results".
|
|
12
8
|
*/
|
|
13
9
|
async function fetchWorkspaceFiles(respectGitignore = true) {
|
|
14
10
|
const settings = ServerConnection.makeSettings();
|
|
@@ -36,10 +32,8 @@ async function fetchWorkspaceFiles(respectGitignore = true) {
|
|
|
36
32
|
const CACHE_TTL_MS = 15000;
|
|
37
33
|
let cache = null;
|
|
38
34
|
/**
|
|
39
|
-
* The workspace file list, cached briefly so reopening the omnibox
|
|
40
|
-
*
|
|
41
|
-
* extension is absent) resolves to an empty list so file search degrades to
|
|
42
|
-
* "no results" instead of surfacing an error.
|
|
35
|
+
* The workspace file list, cached briefly so reopening the omnibox reuses one
|
|
36
|
+
* scan. A failed fetch resolves to an empty list.
|
|
43
37
|
*/
|
|
44
38
|
export function loadWorkspaceFiles() {
|
|
45
39
|
const now = Date.now();
|
package/lib/omnibox/index.d.ts
CHANGED
|
@@ -1,20 +1,10 @@
|
|
|
1
1
|
import { JupyterFrontEndPlugin } from '@jupyterlab/application';
|
|
2
2
|
import { IOmnibox } from './tokens';
|
|
3
3
|
/**
|
|
4
|
-
* The omnibox: a
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* (running it in a fresh terminal through the launcher's
|
|
9
|
-
* `xtralab:start-agent:<id>` commands). It is opened by the top-bar command
|
|
10
|
-
* bar.
|
|
11
|
-
*
|
|
12
|
-
* Commands run and files opened through the overlay are remembered (persisted
|
|
13
|
-
* in the state database) and offered again at the top while the query is
|
|
14
|
-
* empty; the `maxNumberRecents` setting caps how many of each are kept.
|
|
15
|
-
*
|
|
16
|
-
* The agent rows come from the launcher's `IAgentRegistry`; when the launcher
|
|
17
|
-
* is disabled the omnibox still searches files and commands.
|
|
4
|
+
* The omnibox: a launcher overlay that fuzzy-searches workspace files and
|
|
5
|
+
* commands and routes a typed prompt to a configured agent in a fresh
|
|
6
|
+
* terminal. Recently used commands and files persist in the state database;
|
|
7
|
+
* without the launcher it still searches files and commands.
|
|
18
8
|
*/
|
|
19
9
|
declare const plugin: JupyterFrontEndPlugin<IOmnibox>;
|
|
20
10
|
export default plugin;
|
package/lib/omnibox/index.js
CHANGED
|
@@ -9,20 +9,10 @@ import { IOmnibox, OMNIBOX_OPEN_COMMAND } from './tokens';
|
|
|
9
9
|
import { OmniboxWidget } from './widget';
|
|
10
10
|
const PLUGIN_ID = 'xtralab:omnibox';
|
|
11
11
|
/**
|
|
12
|
-
* The omnibox: a
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* (running it in a fresh terminal through the launcher's
|
|
17
|
-
* `xtralab:start-agent:<id>` commands). It is opened by the top-bar command
|
|
18
|
-
* bar.
|
|
19
|
-
*
|
|
20
|
-
* Commands run and files opened through the overlay are remembered (persisted
|
|
21
|
-
* in the state database) and offered again at the top while the query is
|
|
22
|
-
* empty; the `maxNumberRecents` setting caps how many of each are kept.
|
|
23
|
-
*
|
|
24
|
-
* The agent rows come from the launcher's `IAgentRegistry`; when the launcher
|
|
25
|
-
* is disabled the omnibox still searches files and commands.
|
|
12
|
+
* The omnibox: a launcher overlay that fuzzy-searches workspace files and
|
|
13
|
+
* commands and routes a typed prompt to a configured agent in a fresh
|
|
14
|
+
* terminal. Recently used commands and files persist in the state database;
|
|
15
|
+
* without the launcher it still searches files and commands.
|
|
26
16
|
*/
|
|
27
17
|
const plugin = {
|
|
28
18
|
id: PLUGIN_ID,
|
|
@@ -40,21 +30,15 @@ const plugin = {
|
|
|
40
30
|
const { commands, docRegistry } = app;
|
|
41
31
|
const trans = (translator !== null && translator !== void 0 ? translator : nullTranslator).load('jupyterlab');
|
|
42
32
|
const placeholder = trans.__('Search files and commands, or ask an agent…');
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
// exposes no item list and the widget itself is unreachable through the
|
|
46
|
-
// shell (`LabShell.add` defers it until layout restore, after which the
|
|
47
|
-
// modal setting re-parents it out of the left area). The wrapper's
|
|
48
|
-
// `_palette` field is private in TypeScript only, so read it guarded.
|
|
33
|
+
// `ICommandPalette` exposes no item list and the palette widget is
|
|
34
|
+
// unreachable through the shell; duck-read the wrapper's TS-only-private `_palette`.
|
|
49
35
|
const paletteItems = () => {
|
|
50
36
|
const widget = palette === null || palette === void 0 ? void 0 : palette._palette;
|
|
51
37
|
return widget instanceof CommandPalette ? [...widget.items] : [];
|
|
52
38
|
};
|
|
53
39
|
const recents = new OmniboxRecents({ state });
|
|
54
|
-
// Restore
|
|
55
|
-
// `
|
|
56
|
-
// would permanently drop entries beyond it whenever the user configured a
|
|
57
|
-
// larger cap and the state fetch won the race against the settings load.
|
|
40
|
+
// Restore only after the configured cap is known: `restore` trims to
|
|
41
|
+
// `maxItems`, so restoring at the default could permanently drop entries.
|
|
58
42
|
if (settingRegistry) {
|
|
59
43
|
void settingRegistry
|
|
60
44
|
.load(PLUGIN_ID)
|
|
@@ -85,7 +69,7 @@ const plugin = {
|
|
|
85
69
|
};
|
|
86
70
|
const open = (query) => {
|
|
87
71
|
// Reopen fresh each time so the input resets and the agent snapshot is
|
|
88
|
-
// current; the file list
|
|
72
|
+
// current; the file list stays cached (files.ts).
|
|
89
73
|
close();
|
|
90
74
|
const widget = new OmniboxWidget({
|
|
91
75
|
commands,
|
|
@@ -110,7 +94,6 @@ const plugin = {
|
|
|
110
94
|
label: trans.__('Search…'),
|
|
111
95
|
caption: trans.__('Search files and commands, or ask an agent'),
|
|
112
96
|
execute: args => {
|
|
113
|
-
// Toggle: a second press (e.g. of the keyboard shortcut) closes it.
|
|
114
97
|
if (current && !current.isDisposed) {
|
|
115
98
|
close();
|
|
116
99
|
return;
|
|
@@ -119,7 +102,6 @@ const plugin = {
|
|
|
119
102
|
open(typeof query === 'string' ? query : undefined);
|
|
120
103
|
}
|
|
121
104
|
});
|
|
122
|
-
// Open the omnibox with Cmd/Ctrl+K, the common "command center" chord.
|
|
123
105
|
commands.addKeyBinding({
|
|
124
106
|
command: OMNIBOX_OPEN_COMMAND,
|
|
125
107
|
keys: ['Accel K'],
|
package/lib/omnibox/model.d.ts
CHANGED
|
@@ -5,14 +5,14 @@ import type { CommandRegistry } from '@lumino/commands';
|
|
|
5
5
|
import type { CommandPalette } from '@lumino/widgets';
|
|
6
6
|
import type { IAgent } from '../launcher/agents';
|
|
7
7
|
import type { OmniboxRecents } from './recents';
|
|
8
|
-
/**
|
|
9
|
-
* The source a result row came from, used to group rows under a header.
|
|
10
|
-
*/
|
|
11
8
|
type OmniboxItemKind = 'command' | 'file' | 'agent';
|
|
12
9
|
/**
|
|
13
10
|
* A single result row, with the action it runs when chosen.
|
|
14
11
|
*/
|
|
15
12
|
export interface IOmniboxItem {
|
|
13
|
+
/**
|
|
14
|
+
* The source category of the row: command, file, or agent.
|
|
15
|
+
*/
|
|
16
16
|
kind: OmniboxItemKind;
|
|
17
17
|
/**
|
|
18
18
|
* Stable React key.
|
|
@@ -47,34 +47,62 @@ interface IOmniboxSections {
|
|
|
47
47
|
* Recently used commands and files, shown while the term is empty.
|
|
48
48
|
*/
|
|
49
49
|
recent: IOmniboxItem[];
|
|
50
|
+
/**
|
|
51
|
+
* Commands matching the term.
|
|
52
|
+
*/
|
|
50
53
|
commands: IOmniboxItem[];
|
|
54
|
+
/**
|
|
55
|
+
* Workspace files matching the term.
|
|
56
|
+
*/
|
|
51
57
|
files: IOmniboxItem[];
|
|
58
|
+
/**
|
|
59
|
+
* Per-agent "Ask" rows carrying the term as a prompt.
|
|
60
|
+
*/
|
|
52
61
|
agents: IOmniboxItem[];
|
|
53
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Inputs for {@link computeSections}.
|
|
65
|
+
*/
|
|
54
66
|
interface IComputeOptions {
|
|
67
|
+
/**
|
|
68
|
+
* Raw query text from the input.
|
|
69
|
+
*/
|
|
55
70
|
query: string;
|
|
71
|
+
/**
|
|
72
|
+
* The command registry used to look up and execute commands.
|
|
73
|
+
*/
|
|
56
74
|
commands: CommandRegistry;
|
|
57
75
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
76
|
+
* Palette items, whose labels are computed with each item's args — the only
|
|
77
|
+
* form in which entries like "Use Theme: …" exist.
|
|
60
78
|
*/
|
|
61
79
|
paletteItems: ReadonlyArray<CommandPalette.IItem>;
|
|
80
|
+
/**
|
|
81
|
+
* The document registry used to pick file icons.
|
|
82
|
+
*/
|
|
62
83
|
docRegistry: DocumentRegistry;
|
|
84
|
+
/**
|
|
85
|
+
* The available agents; prompt-capable ones get "Ask" rows.
|
|
86
|
+
*/
|
|
63
87
|
agents: IAgent[];
|
|
88
|
+
/**
|
|
89
|
+
* Workspace-relative file paths to match against.
|
|
90
|
+
*/
|
|
64
91
|
files: string[];
|
|
65
92
|
/**
|
|
66
93
|
* Recently-used tracker; `null` disables the recent rows and recording.
|
|
67
94
|
*/
|
|
68
95
|
recents: OmniboxRecents | null;
|
|
96
|
+
/**
|
|
97
|
+
* Translation bundle for row labels.
|
|
98
|
+
*/
|
|
69
99
|
trans: TranslationBundle;
|
|
70
100
|
}
|
|
71
101
|
/**
|
|
72
102
|
* Build the grouped result set for a query. A leading `>` searches only
|
|
73
|
-
* commands
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* rows for the active mode instead (and the widget shows a hint when there
|
|
77
|
-
* are none).
|
|
103
|
+
* commands, `/` only files; otherwise every prompt-capable agent also gets an
|
|
104
|
+
* "Ask" row carrying the query as its prompt. An empty term yields the
|
|
105
|
+
* recently used rows for the active mode.
|
|
78
106
|
*/
|
|
79
107
|
export declare function computeSections(options: IComputeOptions): IOmniboxSections;
|
|
80
108
|
export {};
|
package/lib/omnibox/model.js
CHANGED
|
@@ -3,20 +3,14 @@ import { StringExt } from '@lumino/algorithm';
|
|
|
3
3
|
import { agentCommandId } from '../launcher/tokens';
|
|
4
4
|
const COMMAND_LIMIT = 7;
|
|
5
5
|
const FILE_LIMIT = 10;
|
|
6
|
-
/**
|
|
7
|
-
* Prefixes that narrow the search to a single source: a leading `>` to
|
|
8
|
-
* commands, a leading `/` to files (relative paths never start with `/`, so it
|
|
9
|
-
* is unambiguous). Without a prefix, every source is searched.
|
|
10
|
-
*/
|
|
11
6
|
const COMMAND_PREFIX = '>';
|
|
7
|
+
// Unambiguous: workspace-relative paths never start with '/'.
|
|
12
8
|
const FILE_PREFIX = '/';
|
|
13
9
|
/**
|
|
14
10
|
* Build the grouped result set for a query. A leading `>` searches only
|
|
15
|
-
* commands
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* rows for the active mode instead (and the widget shows a hint when there
|
|
19
|
-
* are none).
|
|
11
|
+
* commands, `/` only files; otherwise every prompt-capable agent also gets an
|
|
12
|
+
* "Ask" row carrying the query as its prompt. An empty term yields the
|
|
13
|
+
* recently used rows for the active mode.
|
|
20
14
|
*/
|
|
21
15
|
export function computeSections(options) {
|
|
22
16
|
const { query, commands, agents, trans } = options;
|
|
@@ -43,13 +37,11 @@ export function computeSections(options) {
|
|
|
43
37
|
recent: [],
|
|
44
38
|
commands: mode === 'files' ? [] : matchCommands(options, term),
|
|
45
39
|
files: mode === 'commands' ? [] : matchFiles(options, term),
|
|
46
|
-
// Agents only in the unprefixed view; the prompt is the full typed query.
|
|
47
40
|
agents: mode === 'all' ? buildAgentItems(commands, agents, term, trans) : []
|
|
48
41
|
};
|
|
49
42
|
}
|
|
50
43
|
/**
|
|
51
|
-
* Run a command and record the use on success, so
|
|
52
|
-
* the recents list.
|
|
44
|
+
* Run a command and record the use on success, so failures never enter the recents.
|
|
53
45
|
*/
|
|
54
46
|
function executeCommand(commands, recents, id, args) {
|
|
55
47
|
void commands
|
|
@@ -61,9 +53,6 @@ function executeCommand(commands, recents, id, args) {
|
|
|
61
53
|
console.error(`xtralab omnibox: command "${id}" failed`, reason);
|
|
62
54
|
});
|
|
63
55
|
}
|
|
64
|
-
/**
|
|
65
|
-
* Open a file and record the use on success.
|
|
66
|
-
*/
|
|
67
56
|
function openFile(commands, recents, path) {
|
|
68
57
|
void commands
|
|
69
58
|
.execute('docmanager:open', { path })
|
|
@@ -76,9 +65,8 @@ function openFile(commands, recents, path) {
|
|
|
76
65
|
}
|
|
77
66
|
/**
|
|
78
67
|
* Read a command's label, visibility and caption, or `null` when the command
|
|
79
|
-
* is missing, hidden, label-less, or its accessors throw (a
|
|
80
|
-
*
|
|
81
|
-
* doesn't provide).
|
|
68
|
+
* is missing, hidden, label-less, or its accessors throw (they can assume a
|
|
69
|
+
* context the omnibox doesn't provide).
|
|
82
70
|
*/
|
|
83
71
|
function commandDisplay(commands, id, args) {
|
|
84
72
|
if (!commands.hasCommand(id)) {
|
|
@@ -97,10 +85,9 @@ function commandDisplay(commands, id, args) {
|
|
|
97
85
|
}
|
|
98
86
|
/**
|
|
99
87
|
* The recently used rows for the empty term: both kinds interleaved by
|
|
100
|
-
* recency
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
* unavailable — file entries are shown as recorded).
|
|
88
|
+
* recency, or only the mode's kind under a bare `>` or `/`. Unresolvable
|
|
89
|
+
* commands are dropped, as are files absent from the workspace listing once
|
|
90
|
+
* it loads.
|
|
104
91
|
*/
|
|
105
92
|
function buildRecentItems(options, mode) {
|
|
106
93
|
var _a;
|
|
@@ -147,11 +134,10 @@ function buildRecentItems(options, mode) {
|
|
|
147
134
|
return items;
|
|
148
135
|
}
|
|
149
136
|
/**
|
|
150
|
-
* Match
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
* pass so a command never also surfaces under its argless label.
|
|
137
|
+
* Match palette items first — their labels carry per-item args (one "Use
|
|
138
|
+
* Theme: …" per theme), which a registry scan can never produce — then
|
|
139
|
+
* registry commands the palette doesn't present, skipping palette-covered ids
|
|
140
|
+
* so a command never also surfaces under its argless label.
|
|
155
141
|
*/
|
|
156
142
|
function matchCommands(options, term) {
|
|
157
143
|
const { commands, paletteItems, recents } = options;
|
|
@@ -166,8 +152,6 @@ function matchCommands(options, term) {
|
|
|
166
152
|
let visible = true;
|
|
167
153
|
let caption = '';
|
|
168
154
|
try {
|
|
169
|
-
// An item's accessors can throw if the command assumes a context (e.g.
|
|
170
|
-
// an active notebook) the omnibox doesn't provide; skip those.
|
|
171
155
|
label = item.label;
|
|
172
156
|
visible = item.isVisible;
|
|
173
157
|
caption = item.caption;
|
|
@@ -209,8 +193,6 @@ function matchCommands(options, term) {
|
|
|
209
193
|
let visible = true;
|
|
210
194
|
let caption = '';
|
|
211
195
|
try {
|
|
212
|
-
// A command's accessors can throw if they assume a context (e.g. an
|
|
213
|
-
// active notebook) the omnibox doesn't provide; skip those.
|
|
214
196
|
label = commands.label(id);
|
|
215
197
|
visible = commands.isVisible(id);
|
|
216
198
|
caption = commands.caption(id);
|
|
@@ -276,7 +258,7 @@ function buildAgentItems(commands, agents, prompt, trans) {
|
|
|
276
258
|
const items = [];
|
|
277
259
|
for (const agent of agents) {
|
|
278
260
|
// Agents without `promptArgs` can't take an inline prompt (the launcher
|
|
279
|
-
// would drop it)
|
|
261
|
+
// would drop it).
|
|
280
262
|
if (agent.promptArgs === undefined) {
|
|
281
263
|
continue;
|
|
282
264
|
}
|
package/lib/omnibox/recents.d.ts
CHANGED
|
@@ -1,52 +1,50 @@
|
|
|
1
1
|
import type { IStateDB } from '@jupyterlab/statedb';
|
|
2
2
|
import type { ReadonlyPartialJSONObject } from '@lumino/coreutils';
|
|
3
|
-
/**
|
|
4
|
-
* Kinds of omnibox results whose uses are recorded.
|
|
5
|
-
*/
|
|
6
3
|
export type RecentKind = 'command' | 'file';
|
|
7
4
|
/**
|
|
8
5
|
* A single recorded use: a command that was run or a file that was opened.
|
|
9
6
|
*/
|
|
10
7
|
interface IRecentEntry {
|
|
8
|
+
/**
|
|
9
|
+
* Whether the entry records a command run or a file opened.
|
|
10
|
+
*/
|
|
11
11
|
kind: RecentKind;
|
|
12
12
|
/**
|
|
13
13
|
* The command id, or the workspace-relative file path.
|
|
14
14
|
*/
|
|
15
15
|
id: string;
|
|
16
16
|
/**
|
|
17
|
-
* Arguments the command ran with, for palette-style entries whose label
|
|
18
|
-
*
|
|
17
|
+
* Arguments the command ran with, for palette-style entries whose label and
|
|
18
|
+
* behavior depend on them.
|
|
19
19
|
*/
|
|
20
20
|
args?: ReadonlyPartialJSONObject;
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
|
-
* A most-recently-used list of omnibox results,
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* state database so they survive reloads. Without a state database the list
|
|
27
|
-
* still works for the lifetime of the page.
|
|
23
|
+
* A most-recently-used list of omnibox results, most-recent-first, capped at
|
|
24
|
+
* `maxItems` per kind and persisted through the state database. Without a
|
|
25
|
+
* state database it still works for the lifetime of the page.
|
|
28
26
|
*/
|
|
29
27
|
export declare class OmniboxRecents {
|
|
30
28
|
constructor(options?: OmniboxRecents.IOptions);
|
|
31
29
|
/**
|
|
32
|
-
* Maximum
|
|
33
|
-
* immediately; `0` disables recents entirely.
|
|
30
|
+
* Maximum entries kept per kind; lowering trims immediately, `0` disables recents.
|
|
34
31
|
*/
|
|
35
32
|
get maxItems(): number;
|
|
33
|
+
/**
|
|
34
|
+
* Set the maximum entries kept per kind.
|
|
35
|
+
*/
|
|
36
36
|
set maxItems(value: number);
|
|
37
37
|
/**
|
|
38
|
-
* The recorded entries, most recent first
|
|
39
|
-
* one kind.
|
|
38
|
+
* The recorded entries, most recent first, optionally filtered to one kind.
|
|
40
39
|
*/
|
|
41
40
|
entries(kind?: RecentKind): IRecentEntry[];
|
|
42
41
|
/**
|
|
43
|
-
* Record a use
|
|
44
|
-
* the front of its kind's list.
|
|
42
|
+
* Record a use, moving the entry to the front of its kind's list.
|
|
45
43
|
*/
|
|
46
44
|
touch(kind: RecentKind, id: string, args?: ReadonlyPartialJSONObject): void;
|
|
47
45
|
/**
|
|
48
46
|
* Load the persisted list. Entries recorded before the load completes stay
|
|
49
|
-
*
|
|
47
|
+
* ahead of the restored history.
|
|
50
48
|
*/
|
|
51
49
|
restore(): Promise<void>;
|
|
52
50
|
/**
|
package/lib/omnibox/recents.js
CHANGED
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Identity of an entry: two uses only match when kind, id and args all do,
|
|
3
|
-
*
|
|
2
|
+
* Identity of an entry: two uses only match when kind, id and args all do, so
|
|
3
|
+
* runs of one command with different args stay distinct.
|
|
4
4
|
*/
|
|
5
5
|
function entryKey(entry) {
|
|
6
6
|
var _a;
|
|
7
7
|
return `${entry.kind}\0${entry.id}\0${JSON.stringify((_a = entry.args) !== null && _a !== void 0 ? _a : null)}`;
|
|
8
8
|
}
|
|
9
|
-
/**
|
|
10
|
-
* State database key the recents list is persisted under.
|
|
11
|
-
*/
|
|
12
9
|
const STATE_KEY = 'xtralab:omnibox:recents';
|
|
13
10
|
/**
|
|
14
|
-
* A most-recently-used list of omnibox results,
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* state database so they survive reloads. Without a state database the list
|
|
18
|
-
* still works for the lifetime of the page.
|
|
11
|
+
* A most-recently-used list of omnibox results, most-recent-first, capped at
|
|
12
|
+
* `maxItems` per kind and persisted through the state database. Without a
|
|
13
|
+
* state database it still works for the lifetime of the page.
|
|
19
14
|
*/
|
|
20
15
|
export class OmniboxRecents {
|
|
21
16
|
constructor(options = {}) {
|
|
@@ -25,12 +20,14 @@ export class OmniboxRecents {
|
|
|
25
20
|
this._state = (_a = options.state) !== null && _a !== void 0 ? _a : null;
|
|
26
21
|
}
|
|
27
22
|
/**
|
|
28
|
-
* Maximum
|
|
29
|
-
* immediately; `0` disables recents entirely.
|
|
23
|
+
* Maximum entries kept per kind; lowering trims immediately, `0` disables recents.
|
|
30
24
|
*/
|
|
31
25
|
get maxItems() {
|
|
32
26
|
return this._maxItems;
|
|
33
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Set the maximum entries kept per kind.
|
|
30
|
+
*/
|
|
34
31
|
set maxItems(value) {
|
|
35
32
|
const normalized = Math.max(0, Math.floor(value));
|
|
36
33
|
if (normalized === this._maxItems) {
|
|
@@ -44,8 +41,7 @@ export class OmniboxRecents {
|
|
|
44
41
|
}
|
|
45
42
|
}
|
|
46
43
|
/**
|
|
47
|
-
* The recorded entries, most recent first
|
|
48
|
-
* one kind.
|
|
44
|
+
* The recorded entries, most recent first, optionally filtered to one kind.
|
|
49
45
|
*/
|
|
50
46
|
entries(kind) {
|
|
51
47
|
return kind
|
|
@@ -53,8 +49,7 @@ export class OmniboxRecents {
|
|
|
53
49
|
: [...this._entries];
|
|
54
50
|
}
|
|
55
51
|
/**
|
|
56
|
-
* Record a use
|
|
57
|
-
* the front of its kind's list.
|
|
52
|
+
* Record a use, moving the entry to the front of its kind's list.
|
|
58
53
|
*/
|
|
59
54
|
touch(kind, id, args) {
|
|
60
55
|
const entry = args === undefined ? { kind, id } : { kind, id, args };
|
|
@@ -65,7 +60,7 @@ export class OmniboxRecents {
|
|
|
65
60
|
}
|
|
66
61
|
/**
|
|
67
62
|
* Load the persisted list. Entries recorded before the load completes stay
|
|
68
|
-
*
|
|
63
|
+
* ahead of the restored history.
|
|
69
64
|
*/
|
|
70
65
|
async restore() {
|
|
71
66
|
if (!this._state) {
|
package/lib/omnibox/tokens.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Token } from '@lumino/coreutils';
|
|
2
2
|
/**
|
|
3
|
-
* A launcher overlay that fuzzy-searches
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* by the top-bar command bar, which opens it on click.
|
|
3
|
+
* A launcher overlay that fuzzy-searches workspace files and commands and
|
|
4
|
+
* routes a typed prompt to a configured agent. Provided by `xtralab:omnibox`;
|
|
5
|
+
* opened by the top-bar command bar.
|
|
7
6
|
*/
|
|
8
7
|
export interface IOmnibox {
|
|
9
8
|
/**
|
|
@@ -15,13 +14,9 @@ export interface IOmnibox {
|
|
|
15
14
|
*/
|
|
16
15
|
close(): void;
|
|
17
16
|
}
|
|
18
|
-
/**
|
|
19
|
-
* DI token for {@link IOmnibox}. Provided by `xtralab:omnibox`; consumed by
|
|
20
|
-
* `xtralab:command-bar` so the top-bar pill opens the omnibox.
|
|
21
|
-
*/
|
|
22
17
|
export declare const IOmnibox: Token<IOmnibox>;
|
|
23
18
|
/**
|
|
24
|
-
* Command id that opens the omnibox
|
|
25
|
-
*
|
|
19
|
+
* Command id that opens the omnibox, shared so the command bar can look up
|
|
20
|
+
* its keybinding for the shortcut hint.
|
|
26
21
|
*/
|
|
27
22
|
export declare const OMNIBOX_OPEN_COMMAND = "xtralab:omnibox:open";
|
package/lib/omnibox/tokens.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { Token } from '@lumino/coreutils';
|
|
2
|
-
/**
|
|
3
|
-
* DI token for {@link IOmnibox}. Provided by `xtralab:omnibox`; consumed by
|
|
4
|
-
* `xtralab:command-bar` so the top-bar pill opens the omnibox.
|
|
5
|
-
*/
|
|
6
2
|
export const IOmnibox = new Token('xtralab:IOmnibox', 'Opens the omnibox overlay that searches files and commands and prompts agents.');
|
|
7
3
|
/**
|
|
8
|
-
* Command id that opens the omnibox
|
|
9
|
-
*
|
|
4
|
+
* Command id that opens the omnibox, shared so the command bar can look up
|
|
5
|
+
* its keybinding for the shortcut hint.
|
|
10
6
|
*/
|
|
11
7
|
export const OMNIBOX_OPEN_COMMAND = 'xtralab:omnibox:open';
|
package/lib/omnibox/widget.d.ts
CHANGED
|
@@ -6,30 +6,34 @@ import type { CommandPalette } from '@lumino/widgets';
|
|
|
6
6
|
import type { IAgent } from '../launcher/agents';
|
|
7
7
|
import type { OmniboxRecents } from './recents';
|
|
8
8
|
/**
|
|
9
|
-
* The omnibox overlay widget
|
|
10
|
-
*
|
|
11
|
-
* theme CSS variables resolve outside the shell, and its own `jp-xtralab-Omnibox`
|
|
12
|
-
* class for the overlay/panel styling (style/omnibox.css).
|
|
9
|
+
* The omnibox overlay widget, attached to `document.body`; `jp-ThemedContainer`
|
|
10
|
+
* makes JupyterLab's theme CSS variables resolve outside the shell.
|
|
13
11
|
*/
|
|
14
12
|
export declare class OmniboxWidget extends ReactWidget {
|
|
15
13
|
constructor(options: OmniboxWidget.IOptions);
|
|
14
|
+
/**
|
|
15
|
+
* Render the omnibox overlay content.
|
|
16
|
+
*/
|
|
16
17
|
render(): JSX.Element;
|
|
17
18
|
private _options;
|
|
18
19
|
}
|
|
19
|
-
/**
|
|
20
|
-
* A namespace for `OmniboxWidget` statics.
|
|
21
|
-
*/
|
|
22
20
|
export declare namespace OmniboxWidget {
|
|
23
21
|
/**
|
|
24
22
|
* Construction options for {@link OmniboxWidget}.
|
|
25
23
|
*/
|
|
26
24
|
interface IOptions {
|
|
25
|
+
/**
|
|
26
|
+
* The command registry used to look up and execute commands.
|
|
27
|
+
*/
|
|
27
28
|
commands: CommandRegistry;
|
|
28
29
|
/**
|
|
29
30
|
* Snapshot of the command palette's items, read once when the overlay
|
|
30
31
|
* opens; empty when the palette isn't available.
|
|
31
32
|
*/
|
|
32
33
|
paletteItems: ReadonlyArray<CommandPalette.IItem>;
|
|
34
|
+
/**
|
|
35
|
+
* The document registry used to pick file icons.
|
|
36
|
+
*/
|
|
33
37
|
docRegistry: DocumentRegistry;
|
|
34
38
|
/**
|
|
35
39
|
* Snapshot of the available agents, read once when the overlay opens.
|
package/lib/omnibox/widget.js
CHANGED
|
@@ -2,19 +2,13 @@ import { ReactWidget } from '@jupyterlab/ui-components';
|
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { computeSections } from './model';
|
|
4
4
|
import { loadWorkspaceFiles } from './files';
|
|
5
|
-
/**
|
|
6
|
-
* DOM id of the results listbox, referenced by the input's `aria-controls`.
|
|
7
|
-
*/
|
|
8
5
|
const LIST_ID = 'jp-xtralab-Omnibox-list';
|
|
9
|
-
/**
|
|
10
|
-
* Stable DOM id for the result row at `index`, for `aria-activedescendant`.
|
|
11
|
-
*/
|
|
12
6
|
function optionId(index) {
|
|
13
7
|
return `jp-xtralab-Omnibox-option-${index}`;
|
|
14
8
|
}
|
|
15
9
|
/**
|
|
16
10
|
* Render `text` with the fuzzy-matched characters at `indices` wrapped in a
|
|
17
|
-
* highlight span
|
|
11
|
+
* highlight span.
|
|
18
12
|
*/
|
|
19
13
|
function renderHighlight(text, indices) {
|
|
20
14
|
if (indices.length === 0) {
|
|
@@ -77,19 +71,16 @@ function OmniboxComponent(props) {
|
|
|
77
71
|
...sections.agents
|
|
78
72
|
], [sections]);
|
|
79
73
|
const hasResults = flat.length > 0;
|
|
80
|
-
// Reset the highlighted row whenever the result set changes, and keep the
|
|
81
|
-
// index in range when results shrink.
|
|
82
74
|
React.useEffect(() => {
|
|
83
75
|
setActive(current => (current < flat.length ? current : 0));
|
|
84
76
|
}, [flat]);
|
|
85
|
-
// Keep the highlighted row scrolled into view as it moves.
|
|
86
77
|
React.useEffect(() => {
|
|
87
78
|
var _a, _b;
|
|
88
79
|
(_b = (_a = listRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('.jp-mod-active')) === null || _b === void 0 ? void 0 : _b.scrollIntoView({ block: 'nearest' });
|
|
89
80
|
}, [active, flat]);
|
|
90
81
|
const dismiss = React.useCallback(() => {
|
|
91
|
-
// Defer so unmounting this React root
|
|
92
|
-
//
|
|
82
|
+
// Defer so unmounting this React root never happens synchronously inside
|
|
83
|
+
// the event handler that triggered it.
|
|
93
84
|
window.setTimeout(onClose, 0);
|
|
94
85
|
}, [onClose]);
|
|
95
86
|
const run = React.useCallback((item) => {
|
|
@@ -162,10 +153,8 @@ function OmniboxComponent(props) {
|
|
|
162
153
|
: trans.__('Search files and commands, or type a prompt and pick an agent. Prefix with > for commands or / for files.')))))));
|
|
163
154
|
}
|
|
164
155
|
/**
|
|
165
|
-
* The omnibox overlay widget
|
|
166
|
-
*
|
|
167
|
-
* theme CSS variables resolve outside the shell, and its own `jp-xtralab-Omnibox`
|
|
168
|
-
* class for the overlay/panel styling (style/omnibox.css).
|
|
156
|
+
* The omnibox overlay widget, attached to `document.body`; `jp-ThemedContainer`
|
|
157
|
+
* makes JupyterLab's theme CSS variables resolve outside the shell.
|
|
169
158
|
*/
|
|
170
159
|
export class OmniboxWidget extends ReactWidget {
|
|
171
160
|
constructor(options) {
|
|
@@ -175,6 +164,9 @@ export class OmniboxWidget extends ReactWidget {
|
|
|
175
164
|
this.addClass('jp-xtralab-Omnibox');
|
|
176
165
|
this.addClass('jp-ThemedContainer');
|
|
177
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Render the omnibox overlay content.
|
|
169
|
+
*/
|
|
178
170
|
render() {
|
|
179
171
|
return React.createElement(OmniboxComponent, { ...this._options });
|
|
180
172
|
}
|