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
|
@@ -68,65 +68,116 @@ export class XtralabFileBrowser extends Widget {
|
|
|
68
68
|
this._section.addWidget(this._content);
|
|
69
69
|
layout.addWidget(this._section);
|
|
70
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* The contents manager backing the tree.
|
|
73
|
+
*/
|
|
71
74
|
get contentsManager() {
|
|
72
75
|
return this._contentsManager;
|
|
73
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* The toolbar above the tree.
|
|
79
|
+
*/
|
|
74
80
|
get toolbar() {
|
|
75
81
|
return this._toolbar;
|
|
76
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Canonical selected paths; folder paths carry a trailing slash.
|
|
85
|
+
*/
|
|
77
86
|
get selectedPaths() {
|
|
78
87
|
return this._selectedPaths;
|
|
79
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* A signal emitted when the tree's selection changes.
|
|
91
|
+
*/
|
|
80
92
|
get selectionChanged() {
|
|
81
93
|
return this._selectionChanged;
|
|
82
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* A signal emitted when {@link refresh} is called.
|
|
97
|
+
*/
|
|
83
98
|
get refreshRequested() {
|
|
84
99
|
return this._refreshRequested;
|
|
85
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* A signal emitting a newly-created canonical path for the tree to insert.
|
|
103
|
+
*/
|
|
86
104
|
get pathAdded() {
|
|
87
105
|
return this._pathAdded;
|
|
88
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* A signal emitting a canonical path to load, expand, select, and scroll to.
|
|
109
|
+
*/
|
|
89
110
|
get revealRequested() {
|
|
90
111
|
return this._revealRequested;
|
|
91
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* A signal emitted when the tree should return to the workspace root.
|
|
115
|
+
*/
|
|
92
116
|
get rootRequested() {
|
|
93
117
|
return this._rootRequested;
|
|
94
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* A signal emitted when every expanded folder should collapse.
|
|
121
|
+
*/
|
|
95
122
|
get collapseAllRequested() {
|
|
96
123
|
return this._collapseAllRequested;
|
|
97
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Whether the filter box above the tree is shown.
|
|
127
|
+
*/
|
|
98
128
|
get fileFilterVisible() {
|
|
99
129
|
return this._fileFilterVisible;
|
|
100
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* A signal emitted when {@link fileFilterVisible} changes.
|
|
133
|
+
*/
|
|
101
134
|
get fileFilterVisibleChanged() {
|
|
102
135
|
return this._fileFilterVisibleChanged;
|
|
103
136
|
}
|
|
104
137
|
/**
|
|
105
|
-
* Update the cached selection
|
|
106
|
-
* underlying `@pierre/trees` model emits a selection change.
|
|
138
|
+
* Update the cached selection from the React tree.
|
|
107
139
|
*/
|
|
108
140
|
updateSelection(paths) {
|
|
109
141
|
this._selectedPaths = paths;
|
|
110
142
|
this._selectionChanged.emit(paths);
|
|
111
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Trigger a refresh of every loaded directory in the tree.
|
|
146
|
+
*/
|
|
112
147
|
refresh() {
|
|
113
148
|
this._refreshRequested.emit();
|
|
114
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* Notify the tree that a new canonical path was created.
|
|
152
|
+
*/
|
|
115
153
|
notifyPathAdded(canonicalPath) {
|
|
116
154
|
this._pathAdded.emit(canonicalPath);
|
|
117
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Reveal a non-empty canonical path in the tree; use {@link scrollToRoot}
|
|
158
|
+
* for the workspace root, which has no tree row of its own.
|
|
159
|
+
*/
|
|
118
160
|
reveal(canonicalPath) {
|
|
119
161
|
if (canonicalPath.length === 0) {
|
|
120
162
|
throw new Error('XtralabFileBrowser.reveal requires a non-empty canonical path; use scrollToRoot for the workspace root.');
|
|
121
163
|
}
|
|
122
164
|
this._revealRequested.emit(canonicalPath);
|
|
123
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Return to the workspace root: clear the selection and scroll to the top.
|
|
168
|
+
*/
|
|
124
169
|
scrollToRoot() {
|
|
125
170
|
this._rootRequested.emit();
|
|
126
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* Ask the tree to collapse every currently expanded folder.
|
|
174
|
+
*/
|
|
127
175
|
collapseAll() {
|
|
128
176
|
this._collapseAllRequested.emit();
|
|
129
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* Show or hide the filter box above the tree.
|
|
180
|
+
*/
|
|
130
181
|
setFileFilterVisible(visible) {
|
|
131
182
|
if (this._fileFilterVisible === visible) {
|
|
132
183
|
return;
|
|
@@ -134,24 +185,45 @@ export class XtralabFileBrowser extends Widget {
|
|
|
134
185
|
this._fileFilterVisible = visible;
|
|
135
186
|
this._fileFilterVisibleChanged.emit(visible);
|
|
136
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* Toggle the filter box above the tree.
|
|
190
|
+
*/
|
|
137
191
|
toggleFileFilter() {
|
|
138
192
|
this.setFileFilterVisible(!this._fileFilterVisible);
|
|
139
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* The DOM node of the movable "Files" section.
|
|
196
|
+
*/
|
|
140
197
|
get sectionNode() {
|
|
141
198
|
return this._section.node;
|
|
142
199
|
}
|
|
200
|
+
/**
|
|
201
|
+
* Whether the panel currently holds no sections, its own tree included.
|
|
202
|
+
*/
|
|
143
203
|
get isEmpty() {
|
|
144
204
|
return this._panelLayout.widgets.length === 0;
|
|
145
205
|
}
|
|
206
|
+
/**
|
|
207
|
+
* A signal emitted when a section is added to or removed from the panel.
|
|
208
|
+
*/
|
|
146
209
|
get contentChanged() {
|
|
147
210
|
return this._contentChanged;
|
|
148
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* A signal emitting each section entry announced to the move plugin.
|
|
214
|
+
*/
|
|
149
215
|
get sectionAdded() {
|
|
150
216
|
return this._sectionAdded;
|
|
151
217
|
}
|
|
218
|
+
/**
|
|
219
|
+
* The accordion hosting the sections, or `null` while the tree sits alone.
|
|
220
|
+
*/
|
|
152
221
|
get accordionPanel() {
|
|
153
222
|
return this._accordion;
|
|
154
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Section widgets hosted from other panels; the tree section is excluded.
|
|
226
|
+
*/
|
|
155
227
|
get sections() {
|
|
156
228
|
if (!this._accordion) {
|
|
157
229
|
return [];
|
|
@@ -173,6 +245,10 @@ export class XtralabFileBrowser extends Widget {
|
|
|
173
245
|
]
|
|
174
246
|
: [];
|
|
175
247
|
}
|
|
248
|
+
/**
|
|
249
|
+
* Detach and return the tree section so the move plugin can re-host it;
|
|
250
|
+
* `null` for any other id or when the section is already away from home.
|
|
251
|
+
*/
|
|
176
252
|
removeSectionById(sectionId) {
|
|
177
253
|
if (sectionId !== TREE_SECTION_ID || !this._isSectionHome()) {
|
|
178
254
|
return null;
|
|
@@ -188,6 +264,9 @@ export class XtralabFileBrowser extends Widget {
|
|
|
188
264
|
this._contentChanged.emit();
|
|
189
265
|
return this._section;
|
|
190
266
|
}
|
|
267
|
+
/**
|
|
268
|
+
* Re-attach the tree section after a move back to this panel.
|
|
269
|
+
*/
|
|
191
270
|
reinsertSection(widget) {
|
|
192
271
|
if (this._accordion) {
|
|
193
272
|
this._accordion.insertWidget(0, widget);
|
|
@@ -228,6 +307,10 @@ export class XtralabFileBrowser extends Widget {
|
|
|
228
307
|
}
|
|
229
308
|
this._contentChanged.emit();
|
|
230
309
|
}
|
|
310
|
+
/**
|
|
311
|
+
* Remove a hosted section; the accordion is torn down once only the
|
|
312
|
+
* panel's own tree section (or nothing) remains.
|
|
313
|
+
*/
|
|
231
314
|
removeSectionWidget(widget) {
|
|
232
315
|
if (!this._accordion || widget.parent !== this._accordion) {
|
|
233
316
|
return;
|
|
@@ -262,14 +345,16 @@ export class XtralabFileBrowser extends Widget {
|
|
|
262
345
|
}
|
|
263
346
|
}
|
|
264
347
|
/**
|
|
265
|
-
* The React-rendered region
|
|
266
|
-
* widget below the toolbar and renders the actual tree.
|
|
348
|
+
* The React-rendered region below the toolbar that hosts the actual tree.
|
|
267
349
|
*/
|
|
268
350
|
class XtralabFileTreeContent extends ReactWidget {
|
|
269
351
|
constructor(options) {
|
|
270
352
|
super();
|
|
271
353
|
this._options = options;
|
|
272
354
|
}
|
|
355
|
+
/**
|
|
356
|
+
* Render the file browser React component.
|
|
357
|
+
*/
|
|
273
358
|
render() {
|
|
274
359
|
return (React.createElement(FileBrowserComponent, { contentsManager: this._options.contentsManager, docManager: this._options.docManager, onOpenFile: this._options.onOpenFile, translator: this._options.translator, widget: this._options.browser }));
|
|
275
360
|
}
|
|
@@ -11,12 +11,8 @@ function representativePath(fileType) {
|
|
|
11
11
|
if (extension === undefined || extension === '') {
|
|
12
12
|
return null;
|
|
13
13
|
}
|
|
14
|
-
// Extensions are stored with a leading dot (e.g. `.py`, `.tar.gz`).
|
|
15
14
|
return `file${extension.startsWith('.') ? extension : `.${extension}`}`;
|
|
16
15
|
}
|
|
17
|
-
/**
|
|
18
|
-
* Point a file type's icon at the tree glyph for its extension.
|
|
19
|
-
*/
|
|
20
16
|
function applyTreeIcon(fileType) {
|
|
21
17
|
const path = representativePath(fileType);
|
|
22
18
|
if (path === null) {
|
|
@@ -62,9 +58,6 @@ const EXTRA_FILE_TYPE_EXTENSIONS = [
|
|
|
62
58
|
'.graphql',
|
|
63
59
|
'.wasm'
|
|
64
60
|
];
|
|
65
|
-
/**
|
|
66
|
-
* Register icon-only file types for unclaimed source extensions.
|
|
67
|
-
*/
|
|
68
61
|
function registerExtraFileTypes(docRegistry) {
|
|
69
62
|
for (const extension of EXTRA_FILE_TYPE_EXTENSIONS) {
|
|
70
63
|
const icon = getSpecificTreeIcon(`file${extension}`);
|
|
@@ -100,7 +93,6 @@ const plugin = {
|
|
|
100
93
|
applyTreeIcon(fileType);
|
|
101
94
|
}
|
|
102
95
|
registerExtraFileTypes(docRegistry);
|
|
103
|
-
// Pick up file types registered after this plugin activates.
|
|
104
96
|
docRegistry.changed.connect((_, args) => {
|
|
105
97
|
if (args.type === 'fileType' &&
|
|
106
98
|
args.change === 'added' &&
|
|
@@ -120,8 +112,6 @@ const plugin = {
|
|
|
120
112
|
}
|
|
121
113
|
};
|
|
122
114
|
setIcon();
|
|
123
|
-
// Keep the tab icon right after a rename, and release the listener
|
|
124
|
-
// when the document closes.
|
|
125
115
|
widget.context.pathChanged.connect(setIcon);
|
|
126
116
|
widget.disposed.connect(() => {
|
|
127
117
|
widget.context.pathChanged.disconnect(setIcon);
|
package/lib/git/api.d.ts
CHANGED
|
@@ -1,24 +1,16 @@
|
|
|
1
1
|
import { GitReference, IFileChange, IGitContentResult, IGitStatusFile, IGitStatusResult } from './tokens';
|
|
2
2
|
/**
|
|
3
|
-
* Fetch `git status --porcelain` for the
|
|
4
|
-
*
|
|
5
|
-
* from the JupyterLab server's root directory.
|
|
3
|
+
* Fetch `git status --porcelain` for the repo at `repoPath` (empty string
|
|
4
|
+
* resolves from the server's root directory).
|
|
6
5
|
*/
|
|
7
6
|
export declare function status(repoPath: string): Promise<IGitStatusResult>;
|
|
8
7
|
/**
|
|
9
|
-
* Fetch a file's contents at a
|
|
10
|
-
*
|
|
11
|
-
* of {@link status}'s response).
|
|
8
|
+
* Fetch a file's contents at a git reference; `filename` is relative to the
|
|
9
|
+
* git repository root.
|
|
12
10
|
*/
|
|
13
11
|
export declare function content(repoPath: string, filename: string, reference: GitReference): Promise<IGitContentResult>;
|
|
14
12
|
/**
|
|
15
13
|
* Expand the porcelain `files` array into one entry per logical change.
|
|
16
|
-
*
|
|
17
|
-
* both staged and modified again in the worktree); callers that just want
|
|
18
|
-
* a flat list of all changes — without any staged-vs-unstaged grouping —
|
|
19
|
-
* can use this helper.
|
|
20
|
-
*
|
|
21
|
-
* Provided as a manual concat rather than `Array.prototype.flatMap` so we
|
|
22
|
-
* don't pin our `tsconfig.lib` to ES2019.
|
|
14
|
+
* Manual concat rather than `flatMap` so `tsconfig.lib` need not be ES2019.
|
|
23
15
|
*/
|
|
24
16
|
export declare function expandStatusFiles(files: IGitStatusFile[]): IFileChange[];
|
package/lib/git/api.js
CHANGED
|
@@ -1,24 +1,10 @@
|
|
|
1
1
|
import { URLExt } from '@jupyterlab/coreutils';
|
|
2
2
|
import { ServerConnection } from '@jupyterlab/services';
|
|
3
|
-
/**
|
|
4
|
-
* Root URL segment used by the `jupyterlab_git` server extension. Every
|
|
5
|
-
* endpoint hangs off this prefix; the `<repoPath>` between it and the
|
|
6
|
-
* endpoint suffix is the JupyterLab server-relative path of the git
|
|
7
|
-
* repository (URL-encoded). For an empty `repoPath` the URL collapses to
|
|
8
|
-
* `/git/<endpoint>` — a shape git's URL routing also accepts.
|
|
9
|
-
*/
|
|
10
3
|
const GIT_NAMESPACE = 'git';
|
|
11
|
-
/**
|
|
12
|
-
* Issue a `POST` against a `jupyterlab_git` endpoint that takes a `<path>`
|
|
13
|
-
* prefix (e.g. `/git/<path>/status`). The response body is decoded as JSON;
|
|
14
|
-
* non-2xx responses are surfaced via the JupyterLab `ServerConnection`
|
|
15
|
-
* machinery so callers can show their `message` field as-is.
|
|
16
|
-
*/
|
|
17
4
|
async function postWithPath(endpoint, repoPath, body) {
|
|
18
5
|
var _a, _b;
|
|
19
6
|
const settings = ServerConnection.makeSettings();
|
|
20
|
-
//
|
|
21
|
-
// between them — the server expects the path to look like a posix path.
|
|
7
|
+
// encodeParts keeps the slashes the server's posix-path routing expects.
|
|
22
8
|
const encodedPath = repoPath.length > 0 ? URLExt.encodeParts(repoPath) : '';
|
|
23
9
|
const url = URLExt.join(settings.baseUrl, GIT_NAMESPACE, encodedPath, endpoint);
|
|
24
10
|
const init = {
|
|
@@ -33,7 +19,7 @@ async function postWithPath(endpoint, repoPath, body) {
|
|
|
33
19
|
data = JSON.parse(text);
|
|
34
20
|
}
|
|
35
21
|
catch (_c) {
|
|
36
|
-
//
|
|
22
|
+
// Non-JSON bodies still surface via the ResponseError below.
|
|
37
23
|
}
|
|
38
24
|
}
|
|
39
25
|
if (!response.ok) {
|
|
@@ -43,17 +29,15 @@ async function postWithPath(endpoint, repoPath, body) {
|
|
|
43
29
|
return (data !== null && data !== void 0 ? data : {});
|
|
44
30
|
}
|
|
45
31
|
/**
|
|
46
|
-
* Fetch `git status --porcelain` for the
|
|
47
|
-
*
|
|
48
|
-
* from the JupyterLab server's root directory.
|
|
32
|
+
* Fetch `git status --porcelain` for the repo at `repoPath` (empty string
|
|
33
|
+
* resolves from the server's root directory).
|
|
49
34
|
*/
|
|
50
35
|
export async function status(repoPath) {
|
|
51
36
|
return postWithPath('status', repoPath, {});
|
|
52
37
|
}
|
|
53
38
|
/**
|
|
54
|
-
* Fetch a file's contents at a
|
|
55
|
-
*
|
|
56
|
-
* of {@link status}'s response).
|
|
39
|
+
* Fetch a file's contents at a git reference; `filename` is relative to the
|
|
40
|
+
* git repository root.
|
|
57
41
|
*/
|
|
58
42
|
export async function content(repoPath, filename, reference) {
|
|
59
43
|
return postWithPath('content', repoPath, {
|
|
@@ -63,13 +47,7 @@ export async function content(repoPath, filename, reference) {
|
|
|
63
47
|
}
|
|
64
48
|
/**
|
|
65
49
|
* Expand the porcelain `files` array into one entry per logical change.
|
|
66
|
-
*
|
|
67
|
-
* both staged and modified again in the worktree); callers that just want
|
|
68
|
-
* a flat list of all changes — without any staged-vs-unstaged grouping —
|
|
69
|
-
* can use this helper.
|
|
70
|
-
*
|
|
71
|
-
* Provided as a manual concat rather than `Array.prototype.flatMap` so we
|
|
72
|
-
* don't pin our `tsconfig.lib` to ES2019.
|
|
50
|
+
* Manual concat rather than `flatMap` so `tsconfig.lib` need not be ES2019.
|
|
73
51
|
*/
|
|
74
52
|
export function expandStatusFiles(files) {
|
|
75
53
|
const result = [];
|
|
@@ -81,16 +59,12 @@ export function expandStatusFiles(files) {
|
|
|
81
59
|
return result;
|
|
82
60
|
}
|
|
83
61
|
/**
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* per non-empty side, so a "modified-staged-and-then-modified-again" file
|
|
88
|
-
* shows up twice in the panel — once under "Staged Changes" and once under
|
|
89
|
-
* "Changes" — matching the layout the user sees in VS Code.
|
|
62
|
+
* Map one porcelain entry to up to two {@link IFileChange} rows — one per
|
|
63
|
+
* non-empty index/worktree side — so a staged-then-modified-again file
|
|
64
|
+
* appears under both groups, as in VS Code.
|
|
90
65
|
*/
|
|
91
66
|
function porcelainToFileChanges(file) {
|
|
92
67
|
const result = [];
|
|
93
|
-
// Untracked files are reported with `??` and only appear under "Changes".
|
|
94
68
|
if (file.x === '?' && file.y === '?') {
|
|
95
69
|
return [
|
|
96
70
|
{
|
package/lib/git/askRequest.d.ts
CHANGED
|
@@ -4,14 +4,10 @@ import type { IAskAgentRequest } from '../askAgent/tokens';
|
|
|
4
4
|
import type { IXtralabDiffModel } from './diffWidget';
|
|
5
5
|
/**
|
|
6
6
|
* Build the ask-agent request for a line range selected in a git diff.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* whose gutter shows new-side numbers — reads from the challenger text. A
|
|
12
|
-
* gutter drag that crosses the two split columns has endpoints in different
|
|
13
|
-
* line-number spaces, so it is described textually instead of as a numeric
|
|
14
|
-
* range.
|
|
7
|
+
* `deletions` ranges index the reference text; other ranges — including
|
|
8
|
+
* sideless unified context rows, whose gutter shows new-side numbers —
|
|
9
|
+
* index the challenger. A drag across the two split columns mixes
|
|
10
|
+
* line-number spaces, so it is described textually instead of numerically.
|
|
15
11
|
*/
|
|
16
12
|
export declare function buildDiffAskRequest(options: {
|
|
17
13
|
model: IXtralabDiffModel;
|
package/lib/git/askRequest.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { Git } from '@jupyterlab/git';
|
|
2
2
|
/**
|
|
3
|
-
* Agent-facing name of a diff content source
|
|
4
|
-
*
|
|
5
|
-
* side name. English on purpose — this ends up in the agent prompt, not in
|
|
6
|
-
* the UI.
|
|
3
|
+
* Agent-facing name of a diff content source. English on purpose — this
|
|
4
|
+
* ends up in the agent prompt, not in the UI.
|
|
7
5
|
*/
|
|
8
6
|
function describeSource(source, fallback) {
|
|
9
7
|
if (source === Git.Diff.SpecialRef.WORKING) {
|
|
@@ -23,9 +21,6 @@ function describeSource(source, fallback) {
|
|
|
23
21
|
function sideName(side) {
|
|
24
22
|
return side === 'deletions' ? 'old side' : 'new side';
|
|
25
23
|
}
|
|
26
|
-
/**
|
|
27
|
-
* Extract lines `startLine`–`endLine` (1-indexed, inclusive) from `text`.
|
|
28
|
-
*/
|
|
29
24
|
function sliceLines(text, startLine, endLine) {
|
|
30
25
|
return text
|
|
31
26
|
.split('\n')
|
|
@@ -34,14 +29,10 @@ function sliceLines(text, startLine, endLine) {
|
|
|
34
29
|
}
|
|
35
30
|
/**
|
|
36
31
|
* Build the ask-agent request for a line range selected in a git diff.
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* whose gutter shows new-side numbers — reads from the challenger text. A
|
|
42
|
-
* gutter drag that crosses the two split columns has endpoints in different
|
|
43
|
-
* line-number spaces, so it is described textually instead of as a numeric
|
|
44
|
-
* range.
|
|
32
|
+
* `deletions` ranges index the reference text; other ranges — including
|
|
33
|
+
* sideless unified context rows, whose gutter shows new-side numbers —
|
|
34
|
+
* index the challenger. A drag across the two split columns mixes
|
|
35
|
+
* line-number spaces, so it is described textually instead of numerically.
|
|
45
36
|
*/
|
|
46
37
|
export function buildDiffAskRequest(options) {
|
|
47
38
|
var _a, _b, _c;
|
|
@@ -75,14 +66,9 @@ export function buildDiffAskRequest(options) {
|
|
|
75
66
|
...base,
|
|
76
67
|
startLine,
|
|
77
68
|
endLine,
|
|
78
|
-
// Only new-side lines of a working-tree diff index the file on disk;
|
|
79
|
-
// old-side and historical line numbers must not be used to highlight
|
|
80
|
-
// the working file.
|
|
81
69
|
linesInWorkingFile: !isOld && model.challenger.source === Git.Diff.SpecialRef.WORKING,
|
|
82
70
|
text: sliceLines(isOld ? oldText : newText, startLine, endLine),
|
|
83
71
|
location: `the ${sideName(startSide)} (${ref}) of the current git diff`,
|
|
84
|
-
// New-side lines read as the file's current content, so only old-side
|
|
85
|
-
// ranges need a clarifying tag in the popup header.
|
|
86
72
|
...(isOld ? { note: trans.__('old version') } : {})
|
|
87
73
|
},
|
|
88
74
|
anchor
|
package/lib/git/commands.d.ts
CHANGED
|
@@ -17,15 +17,24 @@ export declare namespace CommandIDs {
|
|
|
17
17
|
* Argument shapes used by {@link CommandIDs.openDiff}.
|
|
18
18
|
*/
|
|
19
19
|
export declare namespace CommandArguments {
|
|
20
|
+
/**
|
|
21
|
+
* The arguments for the open-diff command.
|
|
22
|
+
*/
|
|
20
23
|
interface IOpenDiff {
|
|
24
|
+
/**
|
|
25
|
+
* The server-relative path of the repository containing the change.
|
|
26
|
+
*/
|
|
21
27
|
repoPath: string;
|
|
28
|
+
/**
|
|
29
|
+
* The file change to show.
|
|
30
|
+
*/
|
|
22
31
|
change: IFileChange;
|
|
32
|
+
/**
|
|
33
|
+
* Whether to open the diff as a pinned tab instead of the shared preview.
|
|
34
|
+
*/
|
|
23
35
|
pin?: boolean;
|
|
24
36
|
}
|
|
25
37
|
}
|
|
26
|
-
/**
|
|
27
|
-
* Widget id of the single, reused preview diff tab.
|
|
28
|
-
*/
|
|
29
38
|
export declare const PREVIEW_DIFF_WIDGET_ID = "xtralab:diff:preview";
|
|
30
39
|
/**
|
|
31
40
|
* Deterministic widget id for a pinned file/group pair.
|
|
@@ -36,18 +45,42 @@ export declare function pinnedDiffWidgetId(change: IFileChange): string;
|
|
|
36
45
|
*/
|
|
37
46
|
export declare class DiffMainAreaWidget extends MainAreaWidget<XtralabDiffWidget> {
|
|
38
47
|
constructor(options: MainAreaWidget.IOptions<XtralabDiffWidget>, change: IFileChange, pinned: boolean, trans: TranslationBundle);
|
|
48
|
+
/**
|
|
49
|
+
* The file change currently displayed.
|
|
50
|
+
*/
|
|
39
51
|
get change(): IFileChange;
|
|
52
|
+
/**
|
|
53
|
+
* Whether the widget is pinned rather than the shared preview.
|
|
54
|
+
*/
|
|
40
55
|
get pinned(): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Pin the widget; a no-op when already pinned.
|
|
58
|
+
*/
|
|
41
59
|
pin(): void;
|
|
60
|
+
/**
|
|
61
|
+
* A signal emitted when the widget becomes pinned.
|
|
62
|
+
*/
|
|
42
63
|
get pinnedChanged(): ISignal<this, boolean>;
|
|
64
|
+
/**
|
|
65
|
+
* Display a new file change and update the tab title, caption, and icon.
|
|
66
|
+
*/
|
|
43
67
|
setChange(repoPath: string, change: IFileChange): void;
|
|
44
68
|
private _change;
|
|
45
69
|
private _pinned;
|
|
46
70
|
private _trans;
|
|
47
71
|
private _pinnedChanged;
|
|
48
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* The options for {@link registerGitCommands}.
|
|
75
|
+
*/
|
|
49
76
|
interface IRegisterGitCommandsOptions {
|
|
77
|
+
/**
|
|
78
|
+
* The JupyterLab application, providing the commands registry and shell.
|
|
79
|
+
*/
|
|
50
80
|
app: JupyterFrontEnd;
|
|
81
|
+
/**
|
|
82
|
+
* Theme manager the diff views follow; may be `null`.
|
|
83
|
+
*/
|
|
51
84
|
themeManager: IThemeManager | null;
|
|
52
85
|
/**
|
|
53
86
|
* Contents manager used to write hunk-discard results.
|
|
@@ -73,11 +106,13 @@ interface IRegisterGitCommandsOptions {
|
|
|
73
106
|
* Look up an already-open diff widget for a file change.
|
|
74
107
|
*/
|
|
75
108
|
findDiff(change: IFileChange, pin?: boolean): DiffMainAreaWidget | undefined;
|
|
109
|
+
/**
|
|
110
|
+
* Callback invoked when a preview diff widget becomes pinned.
|
|
111
|
+
*/
|
|
76
112
|
onPinned(widget: DiffMainAreaWidget): void;
|
|
77
113
|
}
|
|
78
114
|
/**
|
|
79
|
-
* Register the launcher's git diff command
|
|
80
|
-
* registry.
|
|
115
|
+
* Register the launcher's git diff command.
|
|
81
116
|
*/
|
|
82
117
|
export declare function registerGitCommands(options: IRegisterGitCommandsOptions): void;
|
|
83
118
|
export {};
|
package/lib/git/commands.js
CHANGED
|
@@ -11,9 +11,6 @@ export var CommandIDs;
|
|
|
11
11
|
(function (CommandIDs) {
|
|
12
12
|
CommandIDs.openDiff = 'xtralab:git:open-diff';
|
|
13
13
|
})(CommandIDs || (CommandIDs = {}));
|
|
14
|
-
/**
|
|
15
|
-
* Widget id of the single, reused preview diff tab.
|
|
16
|
-
*/
|
|
17
14
|
export const PREVIEW_DIFF_WIDGET_ID = 'xtralab:diff:preview';
|
|
18
15
|
/**
|
|
19
16
|
* Deterministic widget id for a pinned file/group pair.
|
|
@@ -38,12 +35,21 @@ export class DiffMainAreaWidget extends MainAreaWidget {
|
|
|
38
35
|
this._pinned = pinned;
|
|
39
36
|
this._trans = trans;
|
|
40
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* The file change currently displayed.
|
|
40
|
+
*/
|
|
41
41
|
get change() {
|
|
42
42
|
return this._change;
|
|
43
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Whether the widget is pinned rather than the shared preview.
|
|
46
|
+
*/
|
|
44
47
|
get pinned() {
|
|
45
48
|
return this._pinned;
|
|
46
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Pin the widget; a no-op when already pinned.
|
|
52
|
+
*/
|
|
47
53
|
pin() {
|
|
48
54
|
if (this._pinned) {
|
|
49
55
|
return;
|
|
@@ -51,9 +57,15 @@ export class DiffMainAreaWidget extends MainAreaWidget {
|
|
|
51
57
|
this._pinned = true;
|
|
52
58
|
this._pinnedChanged.emit(true);
|
|
53
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* A signal emitted when the widget becomes pinned.
|
|
62
|
+
*/
|
|
54
63
|
get pinnedChanged() {
|
|
55
64
|
return this._pinnedChanged;
|
|
56
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Display a new file change and update the tab title, caption, and icon.
|
|
68
|
+
*/
|
|
57
69
|
setChange(repoPath, change) {
|
|
58
70
|
this._change = change;
|
|
59
71
|
this.content.setModel(fileChangeToDiffModel(repoPath, change));
|
|
@@ -62,9 +74,6 @@ export class DiffMainAreaWidget extends MainAreaWidget {
|
|
|
62
74
|
this.title.icon = getTreeIcon(change.path);
|
|
63
75
|
}
|
|
64
76
|
}
|
|
65
|
-
/**
|
|
66
|
-
* Build the launcher's diff tab around the shared diff widget.
|
|
67
|
-
*/
|
|
68
77
|
function createDiffWidget(options) {
|
|
69
78
|
var _a;
|
|
70
79
|
const { repoPath, change, themeManager, contentsManager, rendermime, askAgent, trans } = options;
|
|
@@ -89,7 +98,6 @@ function createDiffWidget(options) {
|
|
|
89
98
|
}
|
|
90
99
|
widget.toolbar.addItem('pin', pinButton);
|
|
91
100
|
addDiffToolbarItems(widget.toolbar, content);
|
|
92
|
-
// Keep chrome visible only while there is a relevant toolbar control.
|
|
93
101
|
const syncToolbarVisibility = () => {
|
|
94
102
|
if (widget.isDisposed) {
|
|
95
103
|
return;
|
|
@@ -115,7 +123,6 @@ function createDiffWidget(options) {
|
|
|
115
123
|
}
|
|
116
124
|
syncToolbarVisibility();
|
|
117
125
|
};
|
|
118
|
-
// Auto-close once a discard leaves nothing to show.
|
|
119
126
|
const onEmptied = () => {
|
|
120
127
|
if (!widget.isDisposed) {
|
|
121
128
|
widget.close();
|
|
@@ -135,8 +142,7 @@ function createDiffWidget(options) {
|
|
|
135
142
|
return widget;
|
|
136
143
|
}
|
|
137
144
|
/**
|
|
138
|
-
* Register the launcher's git diff command
|
|
139
|
-
* registry.
|
|
145
|
+
* Register the launcher's git diff command.
|
|
140
146
|
*/
|
|
141
147
|
export function registerGitCommands(options) {
|
|
142
148
|
const { app, themeManager, contentsManager, rendermime, askAgent, trans, trackDiff, findDiff, onPinned } = options;
|
package/lib/git/diffModel.js
CHANGED
|
@@ -40,6 +40,10 @@ function referenceSource(ref) {
|
|
|
40
40
|
class FileChangeDiffModel {
|
|
41
41
|
constructor(repoPath, change) {
|
|
42
42
|
var _a;
|
|
43
|
+
/**
|
|
44
|
+
* A signal emitted when the reference or challenger changes; this static
|
|
45
|
+
* model never emits it.
|
|
46
|
+
*/
|
|
43
47
|
this.changed = new Signal(this);
|
|
44
48
|
const { oldRef, newRef } = resolveReferences(change);
|
|
45
49
|
// Renames compare the new path against the old path's previous content.
|