xtralab 0.15.0 → 0.15.1
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 +10 -0
- 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 +28 -19
- package/lib/fileBrowser/commands.js +39 -98
- 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 +68 -216
- package/lib/fileBrowser/gitStatus.d.ts +4 -9
- package/lib/fileBrowser/gitStatus.js +7 -17
- 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 +126 -48
- package/lib/fileBrowser/widget.js +89 -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 +40 -5
- package/lib/git/commands.js +16 -10
- package/lib/git/diffModel.js +4 -0
- package/lib/git/diffSurface.d.ts +41 -55
- package/lib/git/diffSurface.js +42 -117
- package/lib/git/diffWidget.d.ts +81 -2
- package/lib/git/diffWidget.js +62 -12
- package/lib/git/imageDiff.d.ts +5 -6
- package/lib/git/imageDiff.js +18 -48
- package/lib/git/index.d.ts +0 -3
- package/lib/git/index.js +3 -8
- package/lib/git/notebookDiff.d.ts +110 -33
- package/lib/git/notebookDiff.js +52 -195
- 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 +2 -2
- 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 +57 -98
- package/src/fileBrowser/contents.ts +3 -0
- package/src/fileBrowser/dragAndDrop.ts +17 -7
- package/src/fileBrowser/fileBrowser.tsx +84 -223
- package/src/fileBrowser/gitStatus.ts +7 -17
- 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 +149 -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 +70 -10
- package/src/git/diffModel.ts +25 -0
- package/src/git/diffSurface.tsx +71 -159
- package/src/git/diffWidget.tsx +104 -14
- package/src/git/imageDiff.tsx +45 -51
- package/src/git/index.ts +3 -8
- package/src/git/notebookDiff.tsx +211 -238
- 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 +22 -184
- 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
|
@@ -42,10 +42,26 @@ const ACCORDION_CSS_CLASS = 'jp-xtralab-FileBrowser-accordion';
|
|
|
42
42
|
|
|
43
43
|
const MOVABLE_SECTION_CLASS = 'jp-movable-section';
|
|
44
44
|
|
|
45
|
+
/**
|
|
46
|
+
* The options used to create an {@link XtralabFileBrowser}.
|
|
47
|
+
*/
|
|
45
48
|
interface IXtralabFileBrowserOptions {
|
|
49
|
+
/**
|
|
50
|
+
* The contents manager backing the tree.
|
|
51
|
+
*/
|
|
46
52
|
contentsManager: Contents.IManager;
|
|
53
|
+
/**
|
|
54
|
+
* The document manager used to open files from the tree.
|
|
55
|
+
*/
|
|
47
56
|
docManager: IDocumentManager;
|
|
57
|
+
/**
|
|
58
|
+
* Callback invoked with a file's server path when its row is
|
|
59
|
+
* double-clicked. No double-click handler is installed when absent.
|
|
60
|
+
*/
|
|
48
61
|
onOpenFile?: (serverPath: string) => void;
|
|
62
|
+
/**
|
|
63
|
+
* The application language translator.
|
|
64
|
+
*/
|
|
49
65
|
translator?: ITranslator;
|
|
50
66
|
}
|
|
51
67
|
|
|
@@ -56,82 +72,62 @@ interface IXtralabFileBrowserOptions {
|
|
|
56
72
|
*/
|
|
57
73
|
export interface IXtralabFileBrowser {
|
|
58
74
|
/**
|
|
59
|
-
* The contents manager backing the tree
|
|
60
|
-
*
|
|
61
|
-
* drive the tree was loaded from.
|
|
75
|
+
* The contents manager backing the tree; command handlers issue rename,
|
|
76
|
+
* delete, copy, … against the same drive.
|
|
62
77
|
*/
|
|
63
78
|
readonly contentsManager: Contents.IManager;
|
|
64
79
|
|
|
65
80
|
/**
|
|
66
|
-
* The toolbar
|
|
67
|
-
* buttons after the widget is constructed.
|
|
81
|
+
* The toolbar above the tree, populated by plugin code after construction.
|
|
68
82
|
*/
|
|
69
83
|
readonly toolbar: Toolbar;
|
|
70
84
|
|
|
71
85
|
/**
|
|
72
|
-
* Canonical paths
|
|
73
|
-
* paths carry a trailing slash; file paths do not.
|
|
86
|
+
* Canonical selected paths; folder paths carry a trailing slash.
|
|
74
87
|
*/
|
|
75
88
|
readonly selectedPaths: readonly string[];
|
|
76
89
|
|
|
77
90
|
/**
|
|
78
|
-
* Emits when the tree's selection changes.
|
|
79
|
-
* `isVisible` / `isEnabled` predicate should listen so they re-evaluate.
|
|
91
|
+
* Emits when the tree's selection changes.
|
|
80
92
|
*/
|
|
81
93
|
readonly selectionChanged: ISignal<IXtralabFileBrowser, readonly string[]>;
|
|
82
94
|
|
|
83
95
|
/**
|
|
84
|
-
* Emits when {@link refresh} is called.
|
|
85
|
-
* re-fetches the directories that were previously loaded so the tree
|
|
86
|
-
* matches the contents on disk again.
|
|
96
|
+
* Emits when {@link refresh} is called.
|
|
87
97
|
*/
|
|
88
98
|
readonly refreshRequested: ISignal<IXtralabFileBrowser, void>;
|
|
89
99
|
|
|
90
100
|
/**
|
|
91
|
-
* Emits
|
|
92
|
-
*
|
|
93
|
-
* component listens and inserts the path into the model so the user
|
|
94
|
-
* sees the new item without a full refresh.
|
|
101
|
+
* Emits a newly-created canonical path so the tree inserts it without a
|
|
102
|
+
* full refresh.
|
|
95
103
|
*/
|
|
96
104
|
readonly pathAdded: ISignal<IXtralabFileBrowser, string>;
|
|
97
105
|
|
|
98
106
|
/**
|
|
99
|
-
* Emits
|
|
100
|
-
* the
|
|
101
|
-
* any unloaded ancestor directories, expands them, and selects the
|
|
102
|
-
* target. Used by the editor breadcrumbs to jump back to a file or
|
|
103
|
-
* folder shown in the breadcrumb trail.
|
|
107
|
+
* Emits a canonical path to load, expand, select, and scroll to. Used by
|
|
108
|
+
* the editor breadcrumbs.
|
|
104
109
|
*/
|
|
105
110
|
readonly revealRequested: ISignal<IXtralabFileBrowser, string>;
|
|
106
111
|
|
|
107
112
|
/**
|
|
108
|
-
* Emits when
|
|
109
|
-
*
|
|
110
|
-
* first row. Distinct from {@link revealRequested} because the
|
|
111
|
-
* workspace root has no tree row of its own — it cannot be reached
|
|
112
|
-
* by passing a path.
|
|
113
|
+
* Emits when the tree should return to the workspace root — the root has
|
|
114
|
+
* no tree row of its own, so it cannot be revealed by path.
|
|
113
115
|
*/
|
|
114
116
|
readonly rootRequested: ISignal<IXtralabFileBrowser, void>;
|
|
115
117
|
|
|
116
118
|
/**
|
|
117
|
-
* Emits when
|
|
118
|
-
* expanded folder. The React component listens and walks the loaded
|
|
119
|
-
* directories, calling `.collapse()` on each expanded one.
|
|
119
|
+
* Emits when every expanded folder should collapse.
|
|
120
120
|
*/
|
|
121
121
|
readonly collapseAllRequested: ISignal<IXtralabFileBrowser, void>;
|
|
122
122
|
|
|
123
123
|
/**
|
|
124
|
-
* Whether the filter box above the tree is shown
|
|
125
|
-
*
|
|
126
|
-
* toolbar toggle. Also forced to `true` when the tree opens a search
|
|
127
|
-
* session on its own — typing a letter while the tree has focus.
|
|
124
|
+
* Whether the filter box above the tree is shown; also forced `true` when
|
|
125
|
+
* the tree opens a search session itself (typing while it has focus).
|
|
128
126
|
*/
|
|
129
127
|
readonly fileFilterVisible: boolean;
|
|
130
128
|
|
|
131
129
|
/**
|
|
132
|
-
* Emits when {@link fileFilterVisible} changes.
|
|
133
|
-
* listens to show or hide the filter box; the toggle command listens
|
|
134
|
-
* to refresh its toggled state.
|
|
130
|
+
* Emits when {@link fileFilterVisible} changes.
|
|
135
131
|
*/
|
|
136
132
|
readonly fileFilterVisibleChanged: ISignal<IXtralabFileBrowser, boolean>;
|
|
137
133
|
|
|
@@ -141,24 +137,19 @@ export interface IXtralabFileBrowser {
|
|
|
141
137
|
refresh(): void;
|
|
142
138
|
|
|
143
139
|
/**
|
|
144
|
-
* Notify the React component that a new path was created and
|
|
145
|
-
* appear in the tree.
|
|
146
|
-
* convention: directories carry a trailing slash, files do not.
|
|
140
|
+
* Notify the React component that a new canonical path was created and
|
|
141
|
+
* should appear in the tree.
|
|
147
142
|
*/
|
|
148
143
|
notifyPathAdded(canonicalPath: string): void;
|
|
149
144
|
|
|
150
145
|
/**
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
* into view. `canonicalPath` follows the `@pierre/trees` convention
|
|
154
|
-
* (directories carry a trailing slash, files do not). Must be a
|
|
155
|
-
* non-empty path — use {@link scrollToRoot} for the root gesture.
|
|
146
|
+
* Reveal a non-empty canonical path: load and expand ancestors, then
|
|
147
|
+
* select and scroll to it. Use {@link scrollToRoot} for the root gesture.
|
|
156
148
|
*/
|
|
157
149
|
reveal(canonicalPath: string): void;
|
|
158
150
|
|
|
159
151
|
/**
|
|
160
|
-
*
|
|
161
|
-
* selection and scroll back to the top of the tree.
|
|
152
|
+
* Return to the workspace root: clear the selection and scroll to the top.
|
|
162
153
|
*/
|
|
163
154
|
scrollToRoot(): void;
|
|
164
155
|
|
|
@@ -177,6 +168,10 @@ export interface IXtralabFileBrowser {
|
|
|
177
168
|
*/
|
|
178
169
|
toggleFileFilter(): void;
|
|
179
170
|
|
|
171
|
+
/**
|
|
172
|
+
* The DOM node of the movable "Files" section, used to locate the panel
|
|
173
|
+
* currently hosting the tree.
|
|
174
|
+
*/
|
|
180
175
|
readonly sectionNode: HTMLElement;
|
|
181
176
|
}
|
|
182
177
|
|
|
@@ -228,67 +223,109 @@ export class XtralabFileBrowser
|
|
|
228
223
|
layout.addWidget(this._section);
|
|
229
224
|
}
|
|
230
225
|
|
|
226
|
+
/**
|
|
227
|
+
* The contents manager backing the tree.
|
|
228
|
+
*/
|
|
231
229
|
get contentsManager(): Contents.IManager {
|
|
232
230
|
return this._contentsManager;
|
|
233
231
|
}
|
|
234
232
|
|
|
233
|
+
/**
|
|
234
|
+
* The toolbar above the tree.
|
|
235
|
+
*/
|
|
235
236
|
get toolbar(): Toolbar {
|
|
236
237
|
return this._toolbar;
|
|
237
238
|
}
|
|
238
239
|
|
|
240
|
+
/**
|
|
241
|
+
* Canonical selected paths; folder paths carry a trailing slash.
|
|
242
|
+
*/
|
|
239
243
|
get selectedPaths(): readonly string[] {
|
|
240
244
|
return this._selectedPaths;
|
|
241
245
|
}
|
|
242
246
|
|
|
247
|
+
/**
|
|
248
|
+
* A signal emitted when the tree's selection changes.
|
|
249
|
+
*/
|
|
243
250
|
get selectionChanged(): ISignal<this, readonly string[]> {
|
|
244
251
|
return this._selectionChanged;
|
|
245
252
|
}
|
|
246
253
|
|
|
254
|
+
/**
|
|
255
|
+
* A signal emitted when {@link refresh} is called.
|
|
256
|
+
*/
|
|
247
257
|
get refreshRequested(): ISignal<this, void> {
|
|
248
258
|
return this._refreshRequested;
|
|
249
259
|
}
|
|
250
260
|
|
|
261
|
+
/**
|
|
262
|
+
* A signal emitting a newly-created canonical path for the tree to insert.
|
|
263
|
+
*/
|
|
251
264
|
get pathAdded(): ISignal<this, string> {
|
|
252
265
|
return this._pathAdded;
|
|
253
266
|
}
|
|
254
267
|
|
|
268
|
+
/**
|
|
269
|
+
* A signal emitting a canonical path to load, expand, select, and scroll to.
|
|
270
|
+
*/
|
|
255
271
|
get revealRequested(): ISignal<this, string> {
|
|
256
272
|
return this._revealRequested;
|
|
257
273
|
}
|
|
258
274
|
|
|
275
|
+
/**
|
|
276
|
+
* A signal emitted when the tree should return to the workspace root.
|
|
277
|
+
*/
|
|
259
278
|
get rootRequested(): ISignal<this, void> {
|
|
260
279
|
return this._rootRequested;
|
|
261
280
|
}
|
|
262
281
|
|
|
282
|
+
/**
|
|
283
|
+
* A signal emitted when every expanded folder should collapse.
|
|
284
|
+
*/
|
|
263
285
|
get collapseAllRequested(): ISignal<this, void> {
|
|
264
286
|
return this._collapseAllRequested;
|
|
265
287
|
}
|
|
266
288
|
|
|
289
|
+
/**
|
|
290
|
+
* Whether the filter box above the tree is shown.
|
|
291
|
+
*/
|
|
267
292
|
get fileFilterVisible(): boolean {
|
|
268
293
|
return this._fileFilterVisible;
|
|
269
294
|
}
|
|
270
295
|
|
|
296
|
+
/**
|
|
297
|
+
* A signal emitted when {@link fileFilterVisible} changes.
|
|
298
|
+
*/
|
|
271
299
|
get fileFilterVisibleChanged(): ISignal<this, boolean> {
|
|
272
300
|
return this._fileFilterVisibleChanged;
|
|
273
301
|
}
|
|
274
302
|
|
|
275
303
|
/**
|
|
276
|
-
* Update the cached selection
|
|
277
|
-
* underlying `@pierre/trees` model emits a selection change.
|
|
304
|
+
* Update the cached selection from the React tree.
|
|
278
305
|
*/
|
|
279
306
|
updateSelection(paths: readonly string[]): void {
|
|
280
307
|
this._selectedPaths = paths;
|
|
281
308
|
this._selectionChanged.emit(paths);
|
|
282
309
|
}
|
|
283
310
|
|
|
311
|
+
/**
|
|
312
|
+
* Trigger a refresh of every loaded directory in the tree.
|
|
313
|
+
*/
|
|
284
314
|
refresh(): void {
|
|
285
315
|
this._refreshRequested.emit();
|
|
286
316
|
}
|
|
287
317
|
|
|
318
|
+
/**
|
|
319
|
+
* Notify the tree that a new canonical path was created.
|
|
320
|
+
*/
|
|
288
321
|
notifyPathAdded(canonicalPath: string): void {
|
|
289
322
|
this._pathAdded.emit(canonicalPath);
|
|
290
323
|
}
|
|
291
324
|
|
|
325
|
+
/**
|
|
326
|
+
* Reveal a non-empty canonical path in the tree; use {@link scrollToRoot}
|
|
327
|
+
* for the workspace root, which has no tree row of its own.
|
|
328
|
+
*/
|
|
292
329
|
reveal(canonicalPath: string): void {
|
|
293
330
|
if (canonicalPath.length === 0) {
|
|
294
331
|
throw new Error(
|
|
@@ -298,14 +335,23 @@ export class XtralabFileBrowser
|
|
|
298
335
|
this._revealRequested.emit(canonicalPath);
|
|
299
336
|
}
|
|
300
337
|
|
|
338
|
+
/**
|
|
339
|
+
* Return to the workspace root: clear the selection and scroll to the top.
|
|
340
|
+
*/
|
|
301
341
|
scrollToRoot(): void {
|
|
302
342
|
this._rootRequested.emit();
|
|
303
343
|
}
|
|
304
344
|
|
|
345
|
+
/**
|
|
346
|
+
* Ask the tree to collapse every currently expanded folder.
|
|
347
|
+
*/
|
|
305
348
|
collapseAll(): void {
|
|
306
349
|
this._collapseAllRequested.emit();
|
|
307
350
|
}
|
|
308
351
|
|
|
352
|
+
/**
|
|
353
|
+
* Show or hide the filter box above the tree.
|
|
354
|
+
*/
|
|
309
355
|
setFileFilterVisible(visible: boolean): void {
|
|
310
356
|
if (this._fileFilterVisible === visible) {
|
|
311
357
|
return;
|
|
@@ -314,30 +360,51 @@ export class XtralabFileBrowser
|
|
|
314
360
|
this._fileFilterVisibleChanged.emit(visible);
|
|
315
361
|
}
|
|
316
362
|
|
|
363
|
+
/**
|
|
364
|
+
* Toggle the filter box above the tree.
|
|
365
|
+
*/
|
|
317
366
|
toggleFileFilter(): void {
|
|
318
367
|
this.setFileFilterVisible(!this._fileFilterVisible);
|
|
319
368
|
}
|
|
320
369
|
|
|
370
|
+
/**
|
|
371
|
+
* The DOM node of the movable "Files" section.
|
|
372
|
+
*/
|
|
321
373
|
get sectionNode(): HTMLElement {
|
|
322
374
|
return this._section.node;
|
|
323
375
|
}
|
|
324
376
|
|
|
377
|
+
/**
|
|
378
|
+
* Whether the panel currently holds no sections, its own tree included.
|
|
379
|
+
*/
|
|
325
380
|
get isEmpty(): boolean {
|
|
326
381
|
return this._panelLayout.widgets.length === 0;
|
|
327
382
|
}
|
|
328
383
|
|
|
384
|
+
/**
|
|
385
|
+
* A signal emitted when a section is added to or removed from the panel.
|
|
386
|
+
*/
|
|
329
387
|
get contentChanged(): ISignal<this, void> {
|
|
330
388
|
return this._contentChanged;
|
|
331
389
|
}
|
|
332
390
|
|
|
391
|
+
/**
|
|
392
|
+
* A signal emitting each section entry announced to the move plugin.
|
|
393
|
+
*/
|
|
333
394
|
get sectionAdded(): ISignal<this, ISectionEntry> {
|
|
334
395
|
return this._sectionAdded;
|
|
335
396
|
}
|
|
336
397
|
|
|
398
|
+
/**
|
|
399
|
+
* The accordion hosting the sections, or `null` while the tree sits alone.
|
|
400
|
+
*/
|
|
337
401
|
get accordionPanel(): AccordionPanel | null {
|
|
338
402
|
return this._accordion;
|
|
339
403
|
}
|
|
340
404
|
|
|
405
|
+
/**
|
|
406
|
+
* Section widgets hosted from other panels; the tree section is excluded.
|
|
407
|
+
*/
|
|
341
408
|
get sections(): ReadonlyArray<Widget> {
|
|
342
409
|
if (!this._accordion) {
|
|
343
410
|
return [];
|
|
@@ -361,6 +428,10 @@ export class XtralabFileBrowser
|
|
|
361
428
|
: [];
|
|
362
429
|
}
|
|
363
430
|
|
|
431
|
+
/**
|
|
432
|
+
* Detach and return the tree section so the move plugin can re-host it;
|
|
433
|
+
* `null` for any other id or when the section is already away from home.
|
|
434
|
+
*/
|
|
364
435
|
removeSectionById(sectionId: string): Widget | null {
|
|
365
436
|
if (sectionId !== TREE_SECTION_ID || !this._isSectionHome()) {
|
|
366
437
|
return null;
|
|
@@ -377,6 +448,9 @@ export class XtralabFileBrowser
|
|
|
377
448
|
return this._section;
|
|
378
449
|
}
|
|
379
450
|
|
|
451
|
+
/**
|
|
452
|
+
* Re-attach the tree section after a move back to this panel.
|
|
453
|
+
*/
|
|
380
454
|
reinsertSection(widget: Widget): void {
|
|
381
455
|
if (this._accordion) {
|
|
382
456
|
this._accordion.insertWidget(0, widget);
|
|
@@ -418,6 +492,10 @@ export class XtralabFileBrowser
|
|
|
418
492
|
this._contentChanged.emit();
|
|
419
493
|
}
|
|
420
494
|
|
|
495
|
+
/**
|
|
496
|
+
* Remove a hosted section; the accordion is torn down once only the
|
|
497
|
+
* panel's own tree section (or nothing) remains.
|
|
498
|
+
*/
|
|
421
499
|
removeSectionWidget(widget: Widget): void {
|
|
422
500
|
if (!this._accordion || widget.parent !== this._accordion) {
|
|
423
501
|
return;
|
|
@@ -475,17 +553,35 @@ export class XtralabFileBrowser
|
|
|
475
553
|
private _sectionAdded = new Signal<this, ISectionEntry>(this);
|
|
476
554
|
}
|
|
477
555
|
|
|
556
|
+
/**
|
|
557
|
+
* The options used to create an {@link XtralabFileTreeContent}.
|
|
558
|
+
*/
|
|
478
559
|
interface IFileTreeContentOptions {
|
|
560
|
+
/**
|
|
561
|
+
* The contents manager backing the tree.
|
|
562
|
+
*/
|
|
479
563
|
contentsManager: Contents.IManager;
|
|
564
|
+
/**
|
|
565
|
+
* The document manager used to open files from the tree.
|
|
566
|
+
*/
|
|
480
567
|
docManager: IDocumentManager;
|
|
568
|
+
/**
|
|
569
|
+
* Callback invoked with a file's server path when its row is
|
|
570
|
+
* double-clicked. No double-click handler is installed when absent.
|
|
571
|
+
*/
|
|
481
572
|
onOpenFile?: (serverPath: string) => void;
|
|
573
|
+
/**
|
|
574
|
+
* The application language translator.
|
|
575
|
+
*/
|
|
482
576
|
translator?: ITranslator;
|
|
577
|
+
/**
|
|
578
|
+
* The host widget the React tree reports selection and state changes to.
|
|
579
|
+
*/
|
|
483
580
|
browser: XtralabFileBrowser;
|
|
484
581
|
}
|
|
485
582
|
|
|
486
583
|
/**
|
|
487
|
-
* The React-rendered region
|
|
488
|
-
* widget below the toolbar and renders the actual tree.
|
|
584
|
+
* The React-rendered region below the toolbar that hosts the actual tree.
|
|
489
585
|
*/
|
|
490
586
|
class XtralabFileTreeContent extends ReactWidget {
|
|
491
587
|
constructor(options: IFileTreeContentOptions) {
|
|
@@ -493,6 +589,9 @@ class XtralabFileTreeContent extends ReactWidget {
|
|
|
493
589
|
this._options = options;
|
|
494
590
|
}
|
|
495
591
|
|
|
592
|
+
/**
|
|
593
|
+
* Render the file browser React component.
|
|
594
|
+
*/
|
|
496
595
|
protected render(): React.ReactElement {
|
|
497
596
|
return (
|
|
498
597
|
<FileBrowserComponent
|
|
@@ -25,13 +25,9 @@ function representativePath(
|
|
|
25
25
|
if (extension === undefined || extension === '') {
|
|
26
26
|
return null;
|
|
27
27
|
}
|
|
28
|
-
// Extensions are stored with a leading dot (e.g. `.py`, `.tar.gz`).
|
|
29
28
|
return `file${extension.startsWith('.') ? extension : `.${extension}`}`;
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
/**
|
|
33
|
-
* Point a file type's icon at the tree glyph for its extension.
|
|
34
|
-
*/
|
|
35
31
|
function applyTreeIcon(fileType: DocumentRegistry.IFileType): void {
|
|
36
32
|
const path = representativePath(fileType);
|
|
37
33
|
if (path === null) {
|
|
@@ -79,9 +75,6 @@ const EXTRA_FILE_TYPE_EXTENSIONS = [
|
|
|
79
75
|
'.wasm'
|
|
80
76
|
];
|
|
81
77
|
|
|
82
|
-
/**
|
|
83
|
-
* Register icon-only file types for unclaimed source extensions.
|
|
84
|
-
*/
|
|
85
78
|
function registerExtraFileTypes(docRegistry: DocumentRegistry): void {
|
|
86
79
|
for (const extension of EXTRA_FILE_TYPE_EXTENSIONS) {
|
|
87
80
|
const icon = getSpecificTreeIcon(`file${extension}`);
|
|
@@ -125,7 +118,6 @@ const plugin: JupyterFrontEndPlugin<void> = {
|
|
|
125
118
|
applyTreeIcon(fileType);
|
|
126
119
|
}
|
|
127
120
|
registerExtraFileTypes(docRegistry);
|
|
128
|
-
// Pick up file types registered after this plugin activates.
|
|
129
121
|
docRegistry.changed.connect((_, args) => {
|
|
130
122
|
if (
|
|
131
123
|
args.type === 'fileType' &&
|
|
@@ -148,8 +140,6 @@ const plugin: JupyterFrontEndPlugin<void> = {
|
|
|
148
140
|
}
|
|
149
141
|
};
|
|
150
142
|
setIcon();
|
|
151
|
-
// Keep the tab icon right after a rename, and release the listener
|
|
152
|
-
// when the document closes.
|
|
153
143
|
widget.context.pathChanged.connect(setIcon);
|
|
154
144
|
widget.disposed.connect(() => {
|
|
155
145
|
widget.context.pathChanged.disconnect(setIcon);
|
package/src/git/api.ts
CHANGED
|
@@ -9,29 +9,15 @@ import {
|
|
|
9
9
|
IGitStatusResult
|
|
10
10
|
} from './tokens';
|
|
11
11
|
|
|
12
|
-
/**
|
|
13
|
-
* Root URL segment used by the `jupyterlab_git` server extension. Every
|
|
14
|
-
* endpoint hangs off this prefix; the `<repoPath>` between it and the
|
|
15
|
-
* endpoint suffix is the JupyterLab server-relative path of the git
|
|
16
|
-
* repository (URL-encoded). For an empty `repoPath` the URL collapses to
|
|
17
|
-
* `/git/<endpoint>` — a shape git's URL routing also accepts.
|
|
18
|
-
*/
|
|
19
12
|
const GIT_NAMESPACE = 'git';
|
|
20
13
|
|
|
21
|
-
/**
|
|
22
|
-
* Issue a `POST` against a `jupyterlab_git` endpoint that takes a `<path>`
|
|
23
|
-
* prefix (e.g. `/git/<path>/status`). The response body is decoded as JSON;
|
|
24
|
-
* non-2xx responses are surfaced via the JupyterLab `ServerConnection`
|
|
25
|
-
* machinery so callers can show their `message` field as-is.
|
|
26
|
-
*/
|
|
27
14
|
async function postWithPath<T>(
|
|
28
15
|
endpoint: string,
|
|
29
16
|
repoPath: string,
|
|
30
17
|
body: unknown
|
|
31
18
|
): Promise<T> {
|
|
32
19
|
const settings = ServerConnection.makeSettings();
|
|
33
|
-
//
|
|
34
|
-
// between them — the server expects the path to look like a posix path.
|
|
20
|
+
// encodeParts keeps the slashes the server's posix-path routing expects.
|
|
35
21
|
const encodedPath = repoPath.length > 0 ? URLExt.encodeParts(repoPath) : '';
|
|
36
22
|
const url = URLExt.join(
|
|
37
23
|
settings.baseUrl,
|
|
@@ -50,7 +36,7 @@ async function postWithPath<T>(
|
|
|
50
36
|
try {
|
|
51
37
|
data = JSON.parse(text) as T;
|
|
52
38
|
} catch {
|
|
53
|
-
//
|
|
39
|
+
// Non-JSON bodies still surface via the ResponseError below.
|
|
54
40
|
}
|
|
55
41
|
}
|
|
56
42
|
if (!response.ok) {
|
|
@@ -62,18 +48,16 @@ async function postWithPath<T>(
|
|
|
62
48
|
}
|
|
63
49
|
|
|
64
50
|
/**
|
|
65
|
-
* Fetch `git status --porcelain` for the
|
|
66
|
-
*
|
|
67
|
-
* from the JupyterLab server's root directory.
|
|
51
|
+
* Fetch `git status --porcelain` for the repo at `repoPath` (empty string
|
|
52
|
+
* resolves from the server's root directory).
|
|
68
53
|
*/
|
|
69
54
|
export async function status(repoPath: string): Promise<IGitStatusResult> {
|
|
70
55
|
return postWithPath<IGitStatusResult>('status', repoPath, {});
|
|
71
56
|
}
|
|
72
57
|
|
|
73
58
|
/**
|
|
74
|
-
* Fetch a file's contents at a
|
|
75
|
-
*
|
|
76
|
-
* of {@link status}'s response).
|
|
59
|
+
* Fetch a file's contents at a git reference; `filename` is relative to the
|
|
60
|
+
* git repository root.
|
|
77
61
|
*/
|
|
78
62
|
export async function content(
|
|
79
63
|
repoPath: string,
|
|
@@ -88,13 +72,7 @@ export async function content(
|
|
|
88
72
|
|
|
89
73
|
/**
|
|
90
74
|
* Expand the porcelain `files` array into one entry per logical change.
|
|
91
|
-
*
|
|
92
|
-
* both staged and modified again in the worktree); callers that just want
|
|
93
|
-
* a flat list of all changes — without any staged-vs-unstaged grouping —
|
|
94
|
-
* can use this helper.
|
|
95
|
-
*
|
|
96
|
-
* Provided as a manual concat rather than `Array.prototype.flatMap` so we
|
|
97
|
-
* don't pin our `tsconfig.lib` to ES2019.
|
|
75
|
+
* Manual concat rather than `flatMap` so `tsconfig.lib` need not be ES2019.
|
|
98
76
|
*/
|
|
99
77
|
export function expandStatusFiles(files: IGitStatusFile[]): IFileChange[] {
|
|
100
78
|
const result: IFileChange[] = [];
|
|
@@ -107,16 +85,12 @@ export function expandStatusFiles(files: IGitStatusFile[]): IFileChange[] {
|
|
|
107
85
|
}
|
|
108
86
|
|
|
109
87
|
/**
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* per non-empty side, so a "modified-staged-and-then-modified-again" file
|
|
114
|
-
* shows up twice in the panel — once under "Staged Changes" and once under
|
|
115
|
-
* "Changes" — matching the layout the user sees in VS Code.
|
|
88
|
+
* Map one porcelain entry to up to two {@link IFileChange} rows — one per
|
|
89
|
+
* non-empty index/worktree side — so a staged-then-modified-again file
|
|
90
|
+
* appears under both groups, as in VS Code.
|
|
116
91
|
*/
|
|
117
92
|
function porcelainToFileChanges(file: IGitStatusFile): IFileChange[] {
|
|
118
93
|
const result: IFileChange[] = [];
|
|
119
|
-
// Untracked files are reported with `??` and only appear under "Changes".
|
|
120
94
|
if (file.x === '?' && file.y === '?') {
|
|
121
95
|
return [
|
|
122
96
|
{
|
package/src/git/askRequest.ts
CHANGED
|
@@ -9,10 +9,8 @@ import type { IXtralabDiffModel } from './diffWidget';
|
|
|
9
9
|
type DiffSide = 'deletions' | 'additions';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* Agent-facing name of a diff content source
|
|
13
|
-
*
|
|
14
|
-
* side name. English on purpose — this ends up in the agent prompt, not in
|
|
15
|
-
* the UI.
|
|
12
|
+
* Agent-facing name of a diff content source. English on purpose — this
|
|
13
|
+
* ends up in the agent prompt, not in the UI.
|
|
16
14
|
*/
|
|
17
15
|
function describeSource(source: unknown, fallback: string): string {
|
|
18
16
|
if (source === Git.Diff.SpecialRef.WORKING) {
|
|
@@ -34,9 +32,6 @@ function sideName(side: DiffSide): string {
|
|
|
34
32
|
return side === 'deletions' ? 'old side' : 'new side';
|
|
35
33
|
}
|
|
36
34
|
|
|
37
|
-
/**
|
|
38
|
-
* Extract lines `startLine`–`endLine` (1-indexed, inclusive) from `text`.
|
|
39
|
-
*/
|
|
40
35
|
function sliceLines(text: string, startLine: number, endLine: number): string {
|
|
41
36
|
return text
|
|
42
37
|
.split('\n')
|
|
@@ -46,14 +41,10 @@ function sliceLines(text: string, startLine: number, endLine: number): string {
|
|
|
46
41
|
|
|
47
42
|
/**
|
|
48
43
|
* Build the ask-agent request for a line range selected in a git diff.
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* whose gutter shows new-side numbers — reads from the challenger text. A
|
|
54
|
-
* gutter drag that crosses the two split columns has endpoints in different
|
|
55
|
-
* line-number spaces, so it is described textually instead of as a numeric
|
|
56
|
-
* range.
|
|
44
|
+
* `deletions` ranges index the reference text; other ranges — including
|
|
45
|
+
* sideless unified context rows, whose gutter shows new-side numbers —
|
|
46
|
+
* index the challenger. A drag across the two split columns mixes
|
|
47
|
+
* line-number spaces, so it is described textually instead of numerically.
|
|
57
48
|
*/
|
|
58
49
|
export function buildDiffAskRequest(options: {
|
|
59
50
|
model: IXtralabDiffModel;
|
|
@@ -97,15 +88,10 @@ export function buildDiffAskRequest(options: {
|
|
|
97
88
|
...base,
|
|
98
89
|
startLine,
|
|
99
90
|
endLine,
|
|
100
|
-
// Only new-side lines of a working-tree diff index the file on disk;
|
|
101
|
-
// old-side and historical line numbers must not be used to highlight
|
|
102
|
-
// the working file.
|
|
103
91
|
linesInWorkingFile:
|
|
104
92
|
!isOld && model.challenger.source === Git.Diff.SpecialRef.WORKING,
|
|
105
93
|
text: sliceLines(isOld ? oldText : newText, startLine, endLine),
|
|
106
94
|
location: `the ${sideName(startSide)} (${ref}) of the current git diff`,
|
|
107
|
-
// New-side lines read as the file's current content, so only old-side
|
|
108
|
-
// ranges need a clarifying tag in the popup header.
|
|
109
95
|
...(isOld ? { note: trans.__('old version') } : {})
|
|
110
96
|
},
|
|
111
97
|
anchor
|