@theia/notebook 1.52.0 → 1.53.0-next.18
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/lib/browser/contributions/cell-operations.d.ts +1 -1
- package/lib/browser/contributions/cell-operations.d.ts.map +1 -1
- package/lib/browser/contributions/cell-operations.js +10 -2
- package/lib/browser/contributions/cell-operations.js.map +1 -1
- package/lib/browser/contributions/notebook-actions-contribution.d.ts +2 -0
- package/lib/browser/contributions/notebook-actions-contribution.d.ts.map +1 -1
- package/lib/browser/contributions/notebook-actions-contribution.js +43 -24
- package/lib/browser/contributions/notebook-actions-contribution.js.map +1 -1
- package/lib/browser/contributions/notebook-cell-actions-contribution.d.ts +4 -0
- package/lib/browser/contributions/notebook-cell-actions-contribution.d.ts.map +1 -1
- package/lib/browser/contributions/notebook-cell-actions-contribution.js +61 -16
- package/lib/browser/contributions/notebook-cell-actions-contribution.js.map +1 -1
- package/lib/browser/contributions/notebook-status-bar-contribution.d.ts +14 -0
- package/lib/browser/contributions/notebook-status-bar-contribution.d.ts.map +1 -0
- package/lib/browser/contributions/notebook-status-bar-contribution.js +75 -0
- package/lib/browser/contributions/notebook-status-bar-contribution.js.map +1 -0
- package/lib/browser/contributions/notebook-undo-redo-handler.d.ts +10 -0
- package/lib/browser/contributions/notebook-undo-redo-handler.d.ts.map +1 -0
- package/lib/browser/contributions/notebook-undo-redo-handler.js +49 -0
- package/lib/browser/contributions/notebook-undo-redo-handler.js.map +1 -0
- package/lib/browser/notebook-editor-widget.d.ts +6 -0
- package/lib/browser/notebook-editor-widget.d.ts.map +1 -1
- package/lib/browser/notebook-editor-widget.js +40 -4
- package/lib/browser/notebook-editor-widget.js.map +1 -1
- package/lib/browser/notebook-frontend-module.d.ts.map +1 -1
- package/lib/browser/notebook-frontend-module.js +6 -0
- package/lib/browser/notebook-frontend-module.js.map +1 -1
- package/lib/browser/service/notebook-context-manager.d.ts +2 -1
- package/lib/browser/service/notebook-context-manager.d.ts.map +1 -1
- package/lib/browser/service/notebook-context-manager.js +6 -3
- package/lib/browser/service/notebook-context-manager.js.map +1 -1
- package/lib/browser/service/notebook-options.d.ts +1 -0
- package/lib/browser/service/notebook-options.d.ts.map +1 -1
- package/lib/browser/service/notebook-options.js +1 -0
- package/lib/browser/service/notebook-options.js.map +1 -1
- package/lib/browser/service/notebook-service.d.ts +1 -0
- package/lib/browser/service/notebook-service.d.ts.map +1 -1
- package/lib/browser/service/notebook-service.js +7 -0
- package/lib/browser/service/notebook-service.js.map +1 -1
- package/lib/browser/view/notebook-cell-editor.d.ts +8 -1
- package/lib/browser/view/notebook-cell-editor.d.ts.map +1 -1
- package/lib/browser/view/notebook-cell-editor.js +89 -5
- package/lib/browser/view/notebook-cell-editor.js.map +1 -1
- package/lib/browser/view/notebook-cell-list-view.d.ts +3 -0
- package/lib/browser/view/notebook-cell-list-view.d.ts.map +1 -1
- package/lib/browser/view/notebook-cell-list-view.js +33 -2
- package/lib/browser/view/notebook-cell-list-view.js.map +1 -1
- package/lib/browser/view/notebook-code-cell-view.d.ts +1 -1
- package/lib/browser/view/notebook-code-cell-view.d.ts.map +1 -1
- package/lib/browser/view/notebook-code-cell-view.js +19 -17
- package/lib/browser/view/notebook-code-cell-view.js.map +1 -1
- package/lib/browser/view/notebook-find-widget.d.ts +63 -0
- package/lib/browser/view/notebook-find-widget.d.ts.map +1 -0
- package/lib/browser/view/notebook-find-widget.js +225 -0
- package/lib/browser/view/notebook-find-widget.js.map +1 -0
- package/lib/browser/view/notebook-markdown-cell-view.d.ts +4 -0
- package/lib/browser/view/notebook-markdown-cell-view.d.ts.map +1 -1
- package/lib/browser/view/notebook-markdown-cell-view.js +105 -8
- package/lib/browser/view/notebook-markdown-cell-view.js.map +1 -1
- package/lib/browser/view-model/notebook-cell-model.d.ts +27 -1
- package/lib/browser/view-model/notebook-cell-model.d.ts.map +1 -1
- package/lib/browser/view-model/notebook-cell-model.js +76 -1
- package/lib/browser/view-model/notebook-cell-model.js.map +1 -1
- package/lib/browser/view-model/notebook-model.d.ts +8 -1
- package/lib/browser/view-model/notebook-model.d.ts.map +1 -1
- package/lib/browser/view-model/notebook-model.js +66 -14
- package/lib/browser/view-model/notebook-model.js.map +1 -1
- package/package.json +8 -7
- package/src/browser/contributions/cell-operations.ts +8 -2
- package/src/browser/contributions/notebook-actions-contribution.ts +47 -22
- package/src/browser/contributions/notebook-cell-actions-contribution.ts +65 -17
- package/src/browser/contributions/notebook-status-bar-contribution.ts +77 -0
- package/src/browser/contributions/notebook-undo-redo-handler.ts +41 -0
- package/src/browser/notebook-editor-widget.tsx +50 -5
- package/src/browser/notebook-frontend-module.ts +9 -1
- package/src/browser/service/notebook-context-manager.ts +8 -4
- package/src/browser/service/notebook-options.ts +2 -1
- package/src/browser/service/notebook-service.ts +7 -1
- package/src/browser/style/index.css +165 -6
- package/src/browser/view/notebook-cell-editor.tsx +94 -5
- package/src/browser/view/notebook-cell-list-view.tsx +40 -4
- package/src/browser/view/notebook-code-cell-view.tsx +19 -17
- package/src/browser/view/notebook-find-widget.tsx +335 -0
- package/src/browser/view/notebook-markdown-cell-view.tsx +134 -17
- package/src/browser/view-model/notebook-cell-model.ts +101 -8
- package/src/browser/view-model/notebook-model.ts +77 -20
|
@@ -22,7 +22,8 @@ import { NotebookCellModel } from '../view-model/notebook-cell-model';
|
|
|
22
22
|
import {
|
|
23
23
|
NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_TYPE,
|
|
24
24
|
NotebookContextKeys, NOTEBOOK_CELL_EXECUTING, NOTEBOOK_EDITOR_FOCUSED,
|
|
25
|
-
NOTEBOOK_CELL_FOCUSED
|
|
25
|
+
NOTEBOOK_CELL_FOCUSED,
|
|
26
|
+
NOTEBOOK_CELL_LIST_FOCUSED
|
|
26
27
|
} from './notebook-context-keys';
|
|
27
28
|
import { ContextKeyService } from '@theia/core/lib/browser/context-key-service';
|
|
28
29
|
import { NotebookExecutionService } from '../service/notebook-execution-service';
|
|
@@ -32,16 +33,19 @@ import { NotebookEditorWidgetService } from '../service/notebook-editor-widget-s
|
|
|
32
33
|
import { NotebookCommands } from './notebook-actions-contribution';
|
|
33
34
|
import { changeCellType } from './cell-operations';
|
|
34
35
|
import { EditorLanguageQuickPickService } from '@theia/editor/lib/browser/editor-language-quick-pick-service';
|
|
36
|
+
import { NotebookService } from '../service/notebook-service';
|
|
35
37
|
|
|
36
38
|
export namespace NotebookCellCommands {
|
|
37
39
|
/** Parameters: notebookModel: NotebookModel | undefined, cell: NotebookCellModel */
|
|
38
40
|
export const EDIT_COMMAND = Command.toDefaultLocalizedCommand({
|
|
39
41
|
id: 'notebook.cell.edit',
|
|
42
|
+
category: 'Notebook',
|
|
40
43
|
iconClass: codicon('edit')
|
|
41
44
|
});
|
|
42
45
|
/** Parameters: notebookModel: NotebookModel | undefined, cell: NotebookCellModel */
|
|
43
46
|
export const STOP_EDIT_COMMAND = Command.toDefaultLocalizedCommand({
|
|
44
47
|
id: 'notebook.cell.stop-edit',
|
|
48
|
+
category: 'Notebook',
|
|
45
49
|
iconClass: codicon('check')
|
|
46
50
|
});
|
|
47
51
|
/** Parameters: notebookModel: NotebookModel, cell: NotebookCellModel */
|
|
@@ -57,11 +61,21 @@ export namespace NotebookCellCommands {
|
|
|
57
61
|
/** Parameters: notebookModel: NotebookModel, cell: NotebookCellModel */
|
|
58
62
|
export const EXECUTE_SINGLE_CELL_COMMAND = Command.toDefaultLocalizedCommand({
|
|
59
63
|
id: 'notebook.cell.execute-cell',
|
|
64
|
+
category: 'Notebook',
|
|
65
|
+
label: nls.localizeByDefault('Execute Cell'),
|
|
60
66
|
iconClass: codicon('play'),
|
|
61
67
|
});
|
|
62
68
|
/** Parameters: notebookModel: NotebookModel, cell: NotebookCellModel */
|
|
63
69
|
export const EXECUTE_SINGLE_CELL_AND_FOCUS_NEXT_COMMAND = Command.toDefaultLocalizedCommand({
|
|
64
70
|
id: 'notebook.cell.execute-cell-and-focus-next',
|
|
71
|
+
label: nls.localizeByDefault('Execute Notebook Cell and Select Below'),
|
|
72
|
+
category: 'Notebook',
|
|
73
|
+
});
|
|
74
|
+
/** Parameters: notebookModel: NotebookModel, cell: NotebookCellModel */
|
|
75
|
+
export const EXECUTE_SINGLE_CELL_AND_INSERT_BELOW_COMMAND = Command.toDefaultLocalizedCommand({
|
|
76
|
+
id: 'notebook.cell.execute-cell-and-insert-below',
|
|
77
|
+
label: nls.localizeByDefault('Execute Notebook Cell and Insert Below'),
|
|
78
|
+
category: 'Notebook',
|
|
65
79
|
});
|
|
66
80
|
|
|
67
81
|
export const EXECUTE_ABOVE_CELLS_COMMAND = Command.toDefaultLocalizedCommand({
|
|
@@ -83,11 +97,13 @@ export namespace NotebookCellCommands {
|
|
|
83
97
|
/** Parameters: notebookModel: NotebookModel | undefined, cell: NotebookCellModel */
|
|
84
98
|
export const CLEAR_OUTPUTS_COMMAND = Command.toDefaultLocalizedCommand({
|
|
85
99
|
id: 'notebook.cell.clear-outputs',
|
|
100
|
+
category: 'Notebook',
|
|
86
101
|
label: 'Clear Cell Outputs',
|
|
87
102
|
});
|
|
88
103
|
/** Parameters: notebookModel: NotebookModel | undefined, cell: NotebookCellModel | undefined, output: NotebookCellOutputModel */
|
|
89
104
|
export const CHANGE_OUTPUT_PRESENTATION_COMMAND = Command.toDefaultLocalizedCommand({
|
|
90
105
|
id: 'notebook.cell.change-presentation',
|
|
106
|
+
category: 'Notebook',
|
|
91
107
|
label: 'Change Presentation',
|
|
92
108
|
});
|
|
93
109
|
|
|
@@ -112,12 +128,14 @@ export namespace NotebookCellCommands {
|
|
|
112
128
|
|
|
113
129
|
export const TO_CODE_CELL_COMMAND = Command.toLocalizedCommand({
|
|
114
130
|
id: 'notebook.cell.changeToCode',
|
|
131
|
+
category: 'Notebook',
|
|
115
132
|
label: 'Change Cell to Code'
|
|
116
133
|
});
|
|
117
134
|
|
|
118
135
|
export const TO_MARKDOWN_CELL_COMMAND = Command.toLocalizedCommand({
|
|
119
136
|
id: 'notebook.cell.changeToMarkdown',
|
|
120
|
-
|
|
137
|
+
category: 'Notebook',
|
|
138
|
+
label: 'Change Cell to Markdown'
|
|
121
139
|
});
|
|
122
140
|
|
|
123
141
|
export const TOGGLE_CELL_OUTPUT = Command.toDefaultLocalizedCommand({
|
|
@@ -146,6 +164,9 @@ export class NotebookCellActionContribution implements MenuContribution, Command
|
|
|
146
164
|
@inject(ContextKeyService)
|
|
147
165
|
protected contextKeyService: ContextKeyService;
|
|
148
166
|
|
|
167
|
+
@inject(NotebookService)
|
|
168
|
+
protected notebookService: NotebookService;
|
|
169
|
+
|
|
149
170
|
@inject(NotebookExecutionService)
|
|
150
171
|
protected notebookExecutionService: NotebookExecutionService;
|
|
151
172
|
|
|
@@ -297,6 +318,23 @@ export class NotebookCellActionContribution implements MenuContribution, Command
|
|
|
297
318
|
}
|
|
298
319
|
})
|
|
299
320
|
);
|
|
321
|
+
commands.registerCommand(NotebookCellCommands.EXECUTE_SINGLE_CELL_AND_INSERT_BELOW_COMMAND, this.editableCellCommandHandler(
|
|
322
|
+
async (notebookModel, cell) => {
|
|
323
|
+
if (cell.cellKind === CellKind.Code) {
|
|
324
|
+
await commands.executeCommand(NotebookCellCommands.EXECUTE_SINGLE_CELL_COMMAND.id, notebookModel, cell);
|
|
325
|
+
}
|
|
326
|
+
await commands.executeCommand(NotebookCellCommands.STOP_EDIT_COMMAND.id, notebookModel, cell);
|
|
327
|
+
|
|
328
|
+
if (cell.cellKind === CellKind.Code) {
|
|
329
|
+
await commands.executeCommand(NotebookCellCommands.INSERT_NEW_CELL_BELOW_COMMAND.id);
|
|
330
|
+
} else {
|
|
331
|
+
await commands.executeCommand(NotebookCellCommands.INSERT_MARKDOWN_CELL_BELOW_COMMAND.id);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const index = notebookModel.cells.indexOf(cell);
|
|
335
|
+
notebookModel.setSelectedCell(notebookModel.cells[index + 1]);
|
|
336
|
+
})
|
|
337
|
+
);
|
|
300
338
|
|
|
301
339
|
commands.registerCommand(NotebookCellCommands.EXECUTE_ABOVE_CELLS_COMMAND, this.editableCellCommandHandler(
|
|
302
340
|
(notebookModel, cell) => {
|
|
@@ -345,7 +383,7 @@ export class NotebookCellActionContribution implements MenuContribution, Command
|
|
|
345
383
|
commands.registerCommand(NotebookCellCommands.INSERT_MARKDOWN_CELL_BELOW_COMMAND, insertCommand(CellKind.Markup, 'below'));
|
|
346
384
|
|
|
347
385
|
commands.registerCommand(NotebookCellCommands.TO_CODE_CELL_COMMAND, this.editableCellCommandHandler((notebookModel, cell) => {
|
|
348
|
-
changeCellType(notebookModel, cell, CellKind.Code);
|
|
386
|
+
changeCellType(notebookModel, cell, CellKind.Code, this.notebookService.getCodeCellLanguage(notebookModel));
|
|
349
387
|
}));
|
|
350
388
|
commands.registerCommand(NotebookCellCommands.TO_MARKDOWN_CELL_COMMAND, this.editableCellCommandHandler((notebookModel, cell) => {
|
|
351
389
|
changeCellType(notebookModel, cell, CellKind.Markup);
|
|
@@ -369,18 +407,23 @@ export class NotebookCellActionContribution implements MenuContribution, Command
|
|
|
369
407
|
return;
|
|
370
408
|
}
|
|
371
409
|
const language = await this.languageQuickPickService.pickEditorLanguage(selectedCell.language);
|
|
372
|
-
if (!language?.value || language.value === 'autoDetect') {
|
|
410
|
+
if (!language?.value || language.value === 'autoDetect' || language.value.id === selectedCell.language) {
|
|
373
411
|
return;
|
|
374
412
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
413
|
+
const isMarkdownCell = selectedCell.cellKind === CellKind.Markup;
|
|
414
|
+
const isMarkdownLanguage = language.value.id === 'markdown';
|
|
415
|
+
if (isMarkdownLanguage) {
|
|
416
|
+
changeCellType(activeNotebook, selectedCell, CellKind.Markup, language.value.id);
|
|
378
417
|
} else {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
418
|
+
if (isMarkdownCell) {
|
|
419
|
+
changeCellType(activeNotebook, selectedCell, CellKind.Code, language.value.id);
|
|
420
|
+
} else {
|
|
421
|
+
this.notebookEditorWidgetService.focusedEditor?.model?.applyEdits([{
|
|
422
|
+
editType: CellEditType.CellLanguage,
|
|
423
|
+
index: activeNotebook.cells.indexOf(selectedCell),
|
|
424
|
+
language: language.value.id
|
|
425
|
+
}], true);
|
|
426
|
+
}
|
|
384
427
|
}
|
|
385
428
|
}
|
|
386
429
|
});
|
|
@@ -418,12 +461,12 @@ export class NotebookCellActionContribution implements MenuContribution, Command
|
|
|
418
461
|
{
|
|
419
462
|
command: NotebookCellCommands.EDIT_COMMAND.id,
|
|
420
463
|
keybinding: 'Enter',
|
|
421
|
-
when: `!editorTextFocus && ${NOTEBOOK_EDITOR_FOCUSED} && ${NOTEBOOK_CELL_FOCUSED}`,
|
|
464
|
+
when: `!editorTextFocus && !inputFocus && ${NOTEBOOK_EDITOR_FOCUSED} && ${NOTEBOOK_CELL_FOCUSED}`,
|
|
422
465
|
},
|
|
423
466
|
{
|
|
424
467
|
command: NotebookCellCommands.STOP_EDIT_COMMAND.id,
|
|
425
|
-
keybinding: KeyCode.createKeyCode({ first: Key.ENTER, modifiers: [KeyModifier.Alt] }).toString(),
|
|
426
|
-
when: `editorTextFocus && ${NOTEBOOK_EDITOR_FOCUSED}`,
|
|
468
|
+
keybinding: KeyCode.createKeyCode({ first: Key.ENTER, modifiers: [KeyModifier.Alt, KeyModifier.CtrlCmd] }).toString(),
|
|
469
|
+
when: `editorTextFocus && ${NOTEBOOK_EDITOR_FOCUSED} && ${NOTEBOOK_CELL_TYPE} == 'markdown'`,
|
|
427
470
|
},
|
|
428
471
|
{
|
|
429
472
|
command: NotebookCellCommands.STOP_EDIT_COMMAND.id,
|
|
@@ -433,12 +476,17 @@ export class NotebookCellActionContribution implements MenuContribution, Command
|
|
|
433
476
|
{
|
|
434
477
|
command: NotebookCellCommands.EXECUTE_SINGLE_CELL_COMMAND.id,
|
|
435
478
|
keybinding: KeyCode.createKeyCode({ first: Key.ENTER, modifiers: [KeyModifier.CtrlCmd] }).toString(),
|
|
436
|
-
when: `${NOTEBOOK_EDITOR_FOCUSED} && ${NOTEBOOK_CELL_FOCUSED} && ${NOTEBOOK_CELL_TYPE} == 'code'`,
|
|
479
|
+
when: `${NOTEBOOK_CELL_LIST_FOCUSED} && ${NOTEBOOK_EDITOR_FOCUSED} && ${NOTEBOOK_CELL_FOCUSED} && ${NOTEBOOK_CELL_TYPE} == 'code'`,
|
|
437
480
|
},
|
|
438
481
|
{
|
|
439
482
|
command: NotebookCellCommands.EXECUTE_SINGLE_CELL_AND_FOCUS_NEXT_COMMAND.id,
|
|
440
483
|
keybinding: KeyCode.createKeyCode({ first: Key.ENTER, modifiers: [KeyModifier.Shift] }).toString(),
|
|
441
|
-
when: `${NOTEBOOK_EDITOR_FOCUSED} && ${NOTEBOOK_CELL_FOCUSED}`,
|
|
484
|
+
when: `${NOTEBOOK_CELL_LIST_FOCUSED} && ${NOTEBOOK_EDITOR_FOCUSED} && ${NOTEBOOK_CELL_FOCUSED}`,
|
|
485
|
+
},
|
|
486
|
+
{
|
|
487
|
+
command: NotebookCellCommands.EXECUTE_SINGLE_CELL_AND_INSERT_BELOW_COMMAND.id,
|
|
488
|
+
keybinding: KeyCode.createKeyCode({ first: Key.ENTER, modifiers: [KeyModifier.Alt] }).toString(),
|
|
489
|
+
when: `${NOTEBOOK_CELL_LIST_FOCUSED} && ${NOTEBOOK_EDITOR_FOCUSED} && ${NOTEBOOK_CELL_FOCUSED}`,
|
|
442
490
|
},
|
|
443
491
|
{
|
|
444
492
|
command: NotebookCellCommands.CLEAR_OUTPUTS_COMMAND.id,
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2024 TypeFox and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
18
|
+
import { FrontendApplicationContribution, StatusBar, StatusBarAlignment } from '@theia/core/lib/browser';
|
|
19
|
+
import { Disposable } from '@theia/core/lib/common';
|
|
20
|
+
import { NotebookEditorWidgetService } from '../service/notebook-editor-widget-service';
|
|
21
|
+
import { NotebookEditorWidget } from '../notebook-editor-widget';
|
|
22
|
+
import { nls } from '@theia/core';
|
|
23
|
+
import { NotebookCommands } from './notebook-actions-contribution';
|
|
24
|
+
|
|
25
|
+
export const NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID = 'notebook-cell-selection-position';
|
|
26
|
+
|
|
27
|
+
@injectable()
|
|
28
|
+
export class NotebookStatusBarContribution implements FrontendApplicationContribution {
|
|
29
|
+
|
|
30
|
+
@inject(StatusBar) protected readonly statusBar: StatusBar;
|
|
31
|
+
@inject(NotebookEditorWidgetService) protected readonly editorWidgetService: NotebookEditorWidgetService;
|
|
32
|
+
|
|
33
|
+
protected currentCellSelectionListener: Disposable | undefined;
|
|
34
|
+
protected lastFocusedEditor: NotebookEditorWidget | undefined;
|
|
35
|
+
|
|
36
|
+
onStart(): void {
|
|
37
|
+
this.editorWidgetService.onDidChangeFocusedEditor(editor => {
|
|
38
|
+
this.currentCellSelectionListener?.dispose();
|
|
39
|
+
this.currentCellSelectionListener = editor?.model?.onDidChangeSelectedCell(() =>
|
|
40
|
+
this.updateStatusbar(editor)
|
|
41
|
+
);
|
|
42
|
+
editor?.onDidDispose(() => {
|
|
43
|
+
this.lastFocusedEditor = undefined;
|
|
44
|
+
this.updateStatusbar();
|
|
45
|
+
});
|
|
46
|
+
this.updateStatusbar(editor);
|
|
47
|
+
this.lastFocusedEditor = editor;
|
|
48
|
+
});
|
|
49
|
+
if (this.editorWidgetService.focusedEditor) {
|
|
50
|
+
this.updateStatusbar();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
protected async updateStatusbar(editor?: NotebookEditorWidget): Promise<void> {
|
|
55
|
+
if ((!editor && !this.lastFocusedEditor?.isVisible) || editor?.model?.cells.length === 0) {
|
|
56
|
+
this.statusBar.removeElement(NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
await editor?.ready;
|
|
61
|
+
if (!editor?.model) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const selectedCellIndex = editor.model.selectedCell ? editor.model.cells.indexOf(editor.model.selectedCell) + 1 : '';
|
|
66
|
+
|
|
67
|
+
this.statusBar.setElement(NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID, {
|
|
68
|
+
text: nls.localizeByDefault('Cell {0} of {1}', selectedCellIndex, editor.model.cells.length),
|
|
69
|
+
alignment: StatusBarAlignment.RIGHT,
|
|
70
|
+
priority: 100,
|
|
71
|
+
command: NotebookCommands.CENTER_ACTIVE_CELL.id,
|
|
72
|
+
arguments: [editor]
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2024 TypeFox and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
18
|
+
import { ApplicationShell, UndoRedoHandler } from '@theia/core/lib/browser';
|
|
19
|
+
import { NotebookEditorWidget } from '../notebook-editor-widget';
|
|
20
|
+
|
|
21
|
+
@injectable()
|
|
22
|
+
export class NotebookUndoRedoHandler implements UndoRedoHandler<NotebookEditorWidget> {
|
|
23
|
+
|
|
24
|
+
@inject(ApplicationShell)
|
|
25
|
+
protected readonly applicationShell: ApplicationShell;
|
|
26
|
+
|
|
27
|
+
priority = 200;
|
|
28
|
+
select(): NotebookEditorWidget | undefined {
|
|
29
|
+
const current = this.applicationShell.currentWidget;
|
|
30
|
+
if (current instanceof NotebookEditorWidget) {
|
|
31
|
+
return current;
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
undo(item: NotebookEditorWidget): void {
|
|
36
|
+
item.undo();
|
|
37
|
+
}
|
|
38
|
+
redo(item: NotebookEditorWidget): void {
|
|
39
|
+
item.redo();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -33,6 +33,8 @@ import { MarkdownString } from '@theia/core/lib/common/markdown-rendering';
|
|
|
33
33
|
import { NotebookContextManager } from './service/notebook-context-manager';
|
|
34
34
|
import { NotebookViewportService } from './view/notebook-viewport-service';
|
|
35
35
|
import { NotebookCellCommands } from './contributions/notebook-cell-actions-contribution';
|
|
36
|
+
import { NotebookFindWidget } from './view/notebook-find-widget';
|
|
37
|
+
import debounce = require('lodash/debounce');
|
|
36
38
|
const PerfectScrollbar = require('react-perfect-scrollbar');
|
|
37
39
|
|
|
38
40
|
export const NotebookEditorWidgetContainerFactory = Symbol('NotebookEditorWidgetContainerFactory');
|
|
@@ -126,7 +128,16 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
126
128
|
protected readonly renderers = new Map<CellKind, CellRenderer>();
|
|
127
129
|
protected _model?: NotebookModel;
|
|
128
130
|
protected _ready: Deferred<NotebookModel> = new Deferred();
|
|
131
|
+
protected _findWidgetVisible = false;
|
|
132
|
+
protected _findWidgetRef = React.createRef<NotebookFindWidget>();
|
|
129
133
|
protected scrollBarRef = React.createRef<{ updateScroll(): void }>();
|
|
134
|
+
protected debounceFind = debounce(() => {
|
|
135
|
+
this._findWidgetRef.current?.search({});
|
|
136
|
+
}, 30, {
|
|
137
|
+
trailing: true,
|
|
138
|
+
maxWait: 100,
|
|
139
|
+
leading: false
|
|
140
|
+
});
|
|
130
141
|
|
|
131
142
|
get notebookType(): string {
|
|
132
143
|
return this.props.notebookType;
|
|
@@ -143,7 +154,6 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
143
154
|
@postConstruct()
|
|
144
155
|
protected init(): void {
|
|
145
156
|
this.id = NOTEBOOK_EDITOR_ID_PREFIX + this.props.uri.toString();
|
|
146
|
-
this.node.tabIndex = -1;
|
|
147
157
|
|
|
148
158
|
this.scrollOptions = {
|
|
149
159
|
suppressScrollY: true
|
|
@@ -163,8 +173,6 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
163
173
|
this.commandRegistry.executeCommand(NotebookCellCommands.EDIT_COMMAND.id, model, model.cells[0]);
|
|
164
174
|
model.setSelectedCell(model.cells[0]);
|
|
165
175
|
}
|
|
166
|
-
model.cells.forEach(cell => cell.onWillBlurCellEditor(() => this.node.focus()));
|
|
167
|
-
model.onDidAddOrRemoveCell(e => e.newCellIds?.forEach(cellId => model.cells.find(cell => cell.handle === cellId)?.onWillBlurCellEditor(() => this.node.focus())));
|
|
168
176
|
});
|
|
169
177
|
}
|
|
170
178
|
|
|
@@ -177,6 +185,11 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
177
185
|
// Wait one frame to ensure that the content has been rendered
|
|
178
186
|
animationFrame().then(() => this.scrollBarRef.current?.updateScroll());
|
|
179
187
|
}));
|
|
188
|
+
this.toDispose.push(this._model.onContentChanged(() => {
|
|
189
|
+
if (this._findWidgetVisible) {
|
|
190
|
+
this.debounceFind();
|
|
191
|
+
}
|
|
192
|
+
}));
|
|
180
193
|
this.toDispose.push(this._model.onDidChangeReadOnly(readOnly => {
|
|
181
194
|
if (readOnly) {
|
|
182
195
|
lock(this.title);
|
|
@@ -191,6 +204,7 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
191
204
|
}
|
|
192
205
|
// Ensure that the model is loaded before adding the editor
|
|
193
206
|
this.notebookEditorService.addNotebookEditor(this);
|
|
207
|
+
this._model.selectedCell = this._model.cells[0];
|
|
194
208
|
this.update();
|
|
195
209
|
this.notebookContextManager.init(this);
|
|
196
210
|
return this._model;
|
|
@@ -220,18 +234,41 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
220
234
|
protected render(): ReactNode {
|
|
221
235
|
if (this._model) {
|
|
222
236
|
return <div className='theia-notebook-main-container'>
|
|
237
|
+
<div className='theia-notebook-overlay'>
|
|
238
|
+
<NotebookFindWidget
|
|
239
|
+
ref={this._findWidgetRef}
|
|
240
|
+
hidden={!this._findWidgetVisible}
|
|
241
|
+
onClose={() => {
|
|
242
|
+
this._findWidgetVisible = false;
|
|
243
|
+
this._model?.findMatches({
|
|
244
|
+
activeFilters: [],
|
|
245
|
+
matchCase: false,
|
|
246
|
+
regex: false,
|
|
247
|
+
search: '',
|
|
248
|
+
wholeWord: false
|
|
249
|
+
});
|
|
250
|
+
this.update();
|
|
251
|
+
}}
|
|
252
|
+
onSearch={options => this._model?.findMatches(options) ?? []}
|
|
253
|
+
onReplace={(matches, replaceText) => this._model?.replaceAll(matches, replaceText)}
|
|
254
|
+
/>
|
|
255
|
+
</div>
|
|
223
256
|
{this.notebookMainToolbarRenderer.render(this._model, this.node)}
|
|
224
|
-
<div
|
|
257
|
+
<div
|
|
258
|
+
className='theia-notebook-viewport'
|
|
259
|
+
ref={(ref: HTMLDivElement) => this.viewportService.viewportElement = ref}
|
|
260
|
+
>
|
|
225
261
|
<PerfectScrollbar className='theia-notebook-scroll-container'
|
|
226
262
|
ref={this.scrollBarRef}
|
|
227
263
|
onScrollY={(e: HTMLDivElement) => this.viewportService.onScroll(e)}>
|
|
228
264
|
<NotebookCellListView renderers={this.renderers}
|
|
229
265
|
notebookModel={this._model}
|
|
266
|
+
notebookContext={this.notebookContextManager}
|
|
230
267
|
toolbarRenderer={this.cellToolbarFactory}
|
|
231
268
|
commandRegistry={this.commandRegistry} />
|
|
232
269
|
</PerfectScrollbar>
|
|
233
270
|
</div>
|
|
234
|
-
</div
|
|
271
|
+
</div>;
|
|
235
272
|
} else {
|
|
236
273
|
return <div className='theia-notebook-main-container'>
|
|
237
274
|
<div className='theia-notebook-main-loading-indicator'></div>
|
|
@@ -260,6 +297,14 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
|
|
|
260
297
|
this.onDidChangeOutputInputFocusEmitter.fire(focused);
|
|
261
298
|
}
|
|
262
299
|
|
|
300
|
+
showFindWidget(): void {
|
|
301
|
+
if (!this._findWidgetVisible) {
|
|
302
|
+
this._findWidgetVisible = true;
|
|
303
|
+
this.update();
|
|
304
|
+
}
|
|
305
|
+
this._findWidgetRef.current?.focusSearch(this._model?.selectedText);
|
|
306
|
+
}
|
|
307
|
+
|
|
263
308
|
override dispose(): void {
|
|
264
309
|
this.notebookContextManager.dispose();
|
|
265
310
|
this.onDidChangeModelEmitter.dispose();
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import '../../src/browser/style/index.css';
|
|
17
17
|
|
|
18
18
|
import { ContainerModule } from '@theia/core/shared/inversify';
|
|
19
|
-
import { FrontendApplicationContribution, KeybindingContribution, LabelProviderContribution, OpenHandler, WidgetFactory } from '@theia/core/lib/browser';
|
|
19
|
+
import { FrontendApplicationContribution, KeybindingContribution, LabelProviderContribution, OpenHandler, UndoRedoHandler, WidgetFactory } from '@theia/core/lib/browser';
|
|
20
20
|
import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution';
|
|
21
21
|
import { NotebookOpenHandler } from './notebook-open-handler';
|
|
22
22
|
import { CommandContribution, MenuContribution, ResourceResolver, } from '@theia/core';
|
|
@@ -46,6 +46,8 @@ import { NotebookOutputActionContribution } from './contributions/notebook-outpu
|
|
|
46
46
|
import { NotebookClipboardService } from './service/notebook-clipboard-service';
|
|
47
47
|
import { bindNotebookPreferences } from './contributions/notebook-preferences';
|
|
48
48
|
import { NotebookOptionsService } from './service/notebook-options';
|
|
49
|
+
import { NotebookUndoRedoHandler } from './contributions/notebook-undo-redo-handler';
|
|
50
|
+
import { NotebookStatusBarContribution } from './contributions/notebook-status-bar-contribution';
|
|
49
51
|
|
|
50
52
|
export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
51
53
|
bind(NotebookColorContribution).toSelf().inSingletonScope();
|
|
@@ -108,4 +110,10 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
|
108
110
|
|
|
109
111
|
bindNotebookPreferences(bind);
|
|
110
112
|
bind(NotebookOptionsService).toSelf().inSingletonScope();
|
|
113
|
+
|
|
114
|
+
bind(NotebookUndoRedoHandler).toSelf().inSingletonScope();
|
|
115
|
+
bind(UndoRedoHandler).toService(NotebookUndoRedoHandler);
|
|
116
|
+
|
|
117
|
+
bind(NotebookStatusBarContribution).toSelf().inSingletonScope();
|
|
118
|
+
bind(FrontendApplicationContribution).toService(NotebookStatusBarContribution);
|
|
111
119
|
});
|
|
@@ -21,7 +21,7 @@ import { NotebookKernelService } from './notebook-kernel-service';
|
|
|
21
21
|
import {
|
|
22
22
|
NOTEBOOK_CELL_EDITABLE,
|
|
23
23
|
NOTEBOOK_CELL_EXECUTING, NOTEBOOK_CELL_EXECUTION_STATE,
|
|
24
|
-
NOTEBOOK_CELL_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE,
|
|
24
|
+
NOTEBOOK_CELL_FOCUSED, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE,
|
|
25
25
|
NOTEBOOK_CELL_TYPE, NOTEBOOK_HAS_OUTPUTS, NOTEBOOK_KERNEL, NOTEBOOK_KERNEL_SELECTED,
|
|
26
26
|
NOTEBOOK_OUTPUT_INPUT_FOCUSED,
|
|
27
27
|
NOTEBOOK_VIEW_TYPE
|
|
@@ -85,7 +85,7 @@ export class NotebookContextManager {
|
|
|
85
85
|
|
|
86
86
|
this.scopedStore.setContext(NOTEBOOK_HAS_OUTPUTS, !!widget.model?.cells.find(cell => cell.outputs.length > 0));
|
|
87
87
|
|
|
88
|
-
// Cell Selection
|
|
88
|
+
// Cell Selection related keys
|
|
89
89
|
this.scopedStore.setContext(NOTEBOOK_CELL_FOCUSED, !!widget.model?.selectedCell);
|
|
90
90
|
widget.model?.onDidChangeSelectedCell(e => {
|
|
91
91
|
this.selectedCellChanged(e.cell);
|
|
@@ -144,8 +144,12 @@ export class NotebookContextManager {
|
|
|
144
144
|
return this.contextKeyService.createOverlay(Object.entries(this.cellContexts.get(cellHandle) ?? {}));
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
|
|
148
|
-
this.scopedStore.setContext(
|
|
147
|
+
changeCellFocus(focus: boolean): void {
|
|
148
|
+
this.scopedStore.setContext(NOTEBOOK_CELL_FOCUSED, focus);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
changeCellListFocus(focus: boolean): void {
|
|
152
|
+
this.scopedStore.setContext(NOTEBOOK_CELL_LIST_FOCUSED, focus);
|
|
149
153
|
}
|
|
150
154
|
|
|
151
155
|
createContextKeyChangedEvent(affectedKeys: string[]): ContextKeyChangeEvent {
|
|
@@ -37,7 +37,7 @@ const notebookOutputOptionsRelevantPreferences = [
|
|
|
37
37
|
|
|
38
38
|
export interface NotebookOutputOptions {
|
|
39
39
|
// readonly outputNodePadding: number;
|
|
40
|
-
|
|
40
|
+
readonly outputNodeLeftPadding: number;
|
|
41
41
|
// readonly previewNodePadding: number;
|
|
42
42
|
// readonly markdownLeftMargin: number;
|
|
43
43
|
// readonly leftMargin: number;
|
|
@@ -95,6 +95,7 @@ export class NotebookOptionsService {
|
|
|
95
95
|
fontSize,
|
|
96
96
|
outputFontSize: outputFontSize,
|
|
97
97
|
fontFamily: this.preferenceService.get<string>('editor.fontFamily')!,
|
|
98
|
+
outputNodeLeftPadding: 8,
|
|
98
99
|
outputFontFamily: this.getNotebookPreferenceWithDefault<string>(NotebookPreferences.OUTPUT_FONT_FAMILY),
|
|
99
100
|
outputLineHeight: this.computeOutputLineHeight(outputLineHeight, outputFontSize ?? fontSize),
|
|
100
101
|
outputScrolling: this.getNotebookPreferenceWithDefault<boolean>(NotebookPreferences.OUTPUT_SCROLLING)!,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
import { Disposable, DisposableCollection, Emitter, Resource, URI } from '@theia/core';
|
|
18
18
|
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
19
19
|
import { BinaryBuffer } from '@theia/core/lib/common/buffer';
|
|
20
|
-
import { NotebookData, TransientOptions } from '../../common';
|
|
20
|
+
import { CellKind, NotebookData, TransientOptions } from '../../common';
|
|
21
21
|
import { NotebookModel, NotebookModelFactory, NotebookModelProps } from '../view-model/notebook-model';
|
|
22
22
|
import { FileService } from '@theia/filesystem/lib/browser/file-service';
|
|
23
23
|
import { NotebookCellModel, NotebookCellModelFactory, NotebookCellModelProps } from '../view-model/notebook-cell-model';
|
|
@@ -206,4 +206,10 @@ export class NotebookService implements Disposable {
|
|
|
206
206
|
return false;
|
|
207
207
|
}
|
|
208
208
|
}
|
|
209
|
+
|
|
210
|
+
getCodeCellLanguage(model: NotebookModel): string {
|
|
211
|
+
const firstCodeCell = model.cells.find(cellModel => cellModel.cellKind === CellKind.Code);
|
|
212
|
+
const cellLanguage = firstCodeCell?.language ?? 'plaintext';
|
|
213
|
+
return cellLanguage;
|
|
214
|
+
}
|
|
209
215
|
}
|