@jupyterlab/debugger-extension 4.5.0-alpha.4 → 4.5.0-beta.0

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/src/index.ts CHANGED
@@ -16,14 +16,13 @@ import {
16
16
  Dialog,
17
17
  ICommandPalette,
18
18
  InputDialog,
19
+ ISanitizer,
19
20
  ISessionContextDialogs,
20
21
  IThemeManager,
21
22
  MainAreaWidget,
22
23
  SessionContextDialogs,
23
- showDialog,
24
- WidgetTracker
24
+ showDialog
25
25
  } from '@jupyterlab/apputils';
26
- import { CodeCell } from '@jupyterlab/cells';
27
26
  import { IEditorServices } from '@jupyterlab/codeeditor';
28
27
  import { ConsolePanel, IConsoleTracker } from '@jupyterlab/console';
29
28
  import { PageConfig, PathExt } from '@jupyterlab/coreutils';
@@ -38,7 +37,6 @@ import {
38
37
  } from '@jupyterlab/debugger';
39
38
  import { DocumentWidget } from '@jupyterlab/docregistry';
40
39
  import { FileEditor, IEditorTracker } from '@jupyterlab/fileeditor';
41
- import { ILoggerRegistry } from '@jupyterlab/logconsole';
42
40
  import {
43
41
  INotebookTracker,
44
42
  NotebookActions,
@@ -46,13 +44,18 @@ import {
46
44
  } from '@jupyterlab/notebook';
47
45
  import {
48
46
  standardRendererFactories as initialFactories,
47
+ IRenderMime,
49
48
  IRenderMimeRegistry,
50
49
  RenderMimeRegistry
51
50
  } from '@jupyterlab/rendermime';
52
51
  import { Session } from '@jupyterlab/services';
53
52
  import { ISettingRegistry } from '@jupyterlab/settingregistry';
54
53
  import { ITranslator, nullTranslator } from '@jupyterlab/translation';
54
+ import { ICompletionProviderManager } from '@jupyterlab/completer';
55
55
  import type { CommandRegistry } from '@lumino/commands';
56
+ import { WidgetTracker } from '@jupyterlab/apputils';
57
+ import { DebugConsoleCellExecutor } from './debug-console-executor';
58
+ import { DebuggerCompletionProvider } from './debugger-completion-provider';
56
59
 
57
60
  function notifyCommands(commands: CommandRegistry): void {
58
61
  Object.values(Debugger.CommandIDs).forEach(command => {
@@ -360,7 +363,8 @@ const sources: JupyterFrontEndPlugin<IDebugger.ISources> = {
360
363
  });
361
364
  }
362
365
  };
363
- /*
366
+
367
+ /**
364
368
  * A plugin to open detailed views for variables.
365
369
  */
366
370
  const variables: JupyterFrontEndPlugin<void> = {
@@ -835,13 +839,19 @@ const sourceViewer: JupyterFrontEndPlugin<IDebugger.ISourceViewer> = {
835
839
  const main: JupyterFrontEndPlugin<void> = {
836
840
  id: '@jupyterlab/debugger-extension:main',
837
841
  description: 'Initialize the debugger user interface.',
838
- requires: [IDebugger, IDebuggerSidebar, IEditorServices, ITranslator],
842
+ requires: [
843
+ IDebugger,
844
+ IDebuggerSidebar,
845
+ IEditorServices,
846
+ ITranslator,
847
+ ConsolePanel.IContentFactory,
848
+ IConsoleTracker
849
+ ],
839
850
  optional: [
840
851
  ICommandPalette,
841
852
  IDebuggerSourceViewer,
842
853
  ILabShell,
843
854
  ILayoutRestorer,
844
- ILoggerRegistry,
845
855
  ISettingRegistry
846
856
  ],
847
857
  autoStart: true,
@@ -851,11 +861,12 @@ const main: JupyterFrontEndPlugin<void> = {
851
861
  sidebar: IDebugger.ISidebar,
852
862
  editorServices: IEditorServices,
853
863
  translator: ITranslator,
864
+ consolePanelContentFactory: ConsolePanel.IContentFactory,
865
+ consoleTracker: IConsoleTracker,
854
866
  palette: ICommandPalette | null,
855
867
  sourceViewer: IDebugger.ISourceViewer | null,
856
868
  labShell: ILabShell | null,
857
869
  restorer: ILayoutRestorer | null,
858
- loggerRegistry: ILoggerRegistry | null,
859
870
  settingRegistry: ISettingRegistry | null
860
871
  ): Promise<void> => {
861
872
  const trans = translator.load('jupyterlab');
@@ -882,66 +893,6 @@ const main: JupyterFrontEndPlugin<void> = {
882
893
  }
883
894
  }
884
895
 
885
- // get the mime type of the kernel language for the current debug session
886
- const getMimeType = async (): Promise<string> => {
887
- const kernel = service.session?.connection?.kernel;
888
- if (!kernel) {
889
- return '';
890
- }
891
- const info = (await kernel.info).language_info;
892
- const name = info.name;
893
- const mimeType =
894
- editorServices.mimeTypeService.getMimeTypeByLanguage({ name }) ?? '';
895
- return mimeType;
896
- };
897
-
898
- const rendermime = new RenderMimeRegistry({ initialFactories });
899
-
900
- commands.addCommand(CommandIDs.evaluate, {
901
- label: trans.__('Evaluate Code'),
902
- caption: trans.__('Evaluate Code'),
903
- icon: Debugger.Icons.evaluateIcon,
904
- isEnabled: () => service.hasStoppedThreads(),
905
- execute: async () => {
906
- const mimeType = await getMimeType();
907
- const result = await Debugger.Dialogs.getCode({
908
- title: trans.__('Evaluate Code'),
909
- okLabel: trans.__('Evaluate'),
910
- cancelLabel: trans.__('Cancel'),
911
- mimeType,
912
- contentFactory: new CodeCell.ContentFactory({
913
- editorFactory: options =>
914
- editorServices.factoryService.newInlineEditor(options)
915
- }),
916
- rendermime
917
- });
918
- const code = result.value;
919
- if (!result.button.accept || !code) {
920
- return;
921
- }
922
- const reply = await service.evaluate(code);
923
- if (reply) {
924
- const data = reply.result;
925
- const path = service?.session?.connection?.path;
926
- const logger = path ? loggerRegistry?.getLogger?.(path) : undefined;
927
-
928
- if (logger) {
929
- // print to log console of the notebook currently being debugged
930
- logger.log({ type: 'text', data, level: logger.level });
931
- } else {
932
- // fallback to printing to devtools console
933
- console.debug(data);
934
- }
935
- }
936
- },
937
- describedBy: {
938
- args: {
939
- type: 'object',
940
- properties: {}
941
- }
942
- }
943
- });
944
-
945
896
  commands.addCommand(CommandIDs.debugContinue, {
946
897
  label: () => {
947
898
  return service.hasStoppedThreads()
@@ -1186,6 +1137,274 @@ const main: JupyterFrontEndPlugin<void> = {
1186
1137
  }
1187
1138
  };
1188
1139
 
1140
+ /**
1141
+ * A plugin that provides debugger-based completions.
1142
+ */
1143
+ const debuggerCompletions: JupyterFrontEndPlugin<void> = {
1144
+ id: '@jupyterlab/debugger-extension:completions',
1145
+ description: 'Provides debugger-based completions.',
1146
+ autoStart: true,
1147
+ requires: [IDebugger, ICompletionProviderManager],
1148
+ optional: [ITranslator],
1149
+ activate: (
1150
+ app: JupyterFrontEnd,
1151
+ debuggerService: IDebugger,
1152
+ completionManager: ICompletionProviderManager,
1153
+ translator: ITranslator | null
1154
+ ): void => {
1155
+ // Create and register the debugger completion provider
1156
+ const provider = new DebuggerCompletionProvider({
1157
+ debuggerService: debuggerService,
1158
+ translator: translator || nullTranslator
1159
+ });
1160
+
1161
+ // Register the provider with the completion manager
1162
+ completionManager.registerProvider(provider);
1163
+ }
1164
+ };
1165
+
1166
+ /**
1167
+ * A plugin that provides the debug console functionality.
1168
+ */
1169
+ const debugConsole: JupyterFrontEndPlugin<void> = {
1170
+ id: '@jupyterlab/debugger-extension:debug-console',
1171
+ description: 'Debugger console to enable evaluation in debugger context.',
1172
+ autoStart: true,
1173
+ requires: [
1174
+ IDebugger,
1175
+ ConsolePanel.IContentFactory,
1176
+ IEditorServices,
1177
+ ICompletionProviderManager,
1178
+ ISanitizer,
1179
+ ITranslator
1180
+ ],
1181
+ optional: [ILabShell],
1182
+ activate: (
1183
+ app: JupyterFrontEnd,
1184
+ service: IDebugger,
1185
+ consolePanelContentFactory: ConsolePanel.IContentFactory,
1186
+ editorServices: IEditorServices,
1187
+ manager: ICompletionProviderManager,
1188
+ sanitizer: IRenderMime.ISanitizer,
1189
+ translator: ITranslator,
1190
+ labShell: ILabShell | null
1191
+ ) => {
1192
+ const CommandIDs = Debugger.CommandIDs;
1193
+ const trans = translator.load('jupyterlab');
1194
+
1195
+ // Create our own tracker for debug consoles
1196
+ const debugConsoleTracker = new WidgetTracker<ConsolePanel>({
1197
+ namespace: 'debugger-debug-console'
1198
+ });
1199
+
1200
+ // Global debug console widget variable for toggling
1201
+ let debugConsoleWidget: ConsolePanel | null = null;
1202
+
1203
+ // Create the console
1204
+ const createDebugConsole = async () => {
1205
+ const rendermime = new RenderMimeRegistry({ initialFactories });
1206
+ const debugExecutor = new DebugConsoleCellExecutor({
1207
+ debuggerService: service,
1208
+ trans
1209
+ });
1210
+
1211
+ debugConsoleWidget = new ConsolePanel({
1212
+ manager: app.serviceManager,
1213
+ name: trans.__('Debug Console'),
1214
+ contentFactory: consolePanelContentFactory,
1215
+ rendermime,
1216
+ executor: debugExecutor,
1217
+ mimeTypeService: editorServices.mimeTypeService,
1218
+ kernelPreference: { shouldStart: false, canStart: false }
1219
+ });
1220
+
1221
+ debugConsoleWidget.title.label = trans.__('Debug Console');
1222
+ debugConsoleWidget.title.icon = Debugger.Icons.evaluateIcon;
1223
+
1224
+ // Add a specific class to distinguish debug console from regular consoles
1225
+ debugConsoleWidget.addClass('jp-DebugConsole');
1226
+ debugConsoleWidget.console.addClass('jp-DebugConsole-widget');
1227
+
1228
+ // Close console when debugger is terminated
1229
+ service.eventMessage.connect((_, event): void => {
1230
+ if (labShell && event.event === 'terminated') {
1231
+ debugConsoleWidget?.dispose();
1232
+ }
1233
+ });
1234
+
1235
+ const notifyCommands = () => {
1236
+ app.commands.notifyCommandChanged(CommandIDs.evaluate);
1237
+ app.commands.notifyCommandChanged(CommandIDs.executeConsole);
1238
+ app.commands.notifyCommandChanged(CommandIDs.invokeConsole);
1239
+ app.commands.notifyCommandChanged(CommandIDs.selectConsole);
1240
+ };
1241
+
1242
+ debugConsoleWidget.disposed.connect(() => {
1243
+ debugConsoleWidget = null;
1244
+ });
1245
+
1246
+ app.shell.add(debugConsoleWidget, 'main', {
1247
+ mode: 'split-bottom',
1248
+ activate: true,
1249
+ type: 'Debugger console'
1250
+ });
1251
+
1252
+ void debugConsoleTracker.add(debugConsoleWidget);
1253
+ app.shell.activateById(debugConsoleWidget.id);
1254
+
1255
+ await updateCompleter(undefined, debugConsoleWidget);
1256
+ debugConsoleWidget?.update();
1257
+
1258
+ notifyCommands();
1259
+ };
1260
+
1261
+ // Set up completer
1262
+ const updateCompleter = async (
1263
+ _: WidgetTracker<ConsolePanel> | undefined,
1264
+ consolePanel: ConsolePanel
1265
+ ) => {
1266
+ const completerContext = {
1267
+ editor: consolePanel.console.promptCell?.editor ?? null,
1268
+ session: consolePanel.console.sessionContext.session,
1269
+ widget: consolePanel
1270
+ };
1271
+ await manager.updateCompleter(completerContext);
1272
+ consolePanel.console.promptCellCreated.connect((codeConsole, cell) => {
1273
+ const newContext = {
1274
+ editor: cell.editor,
1275
+ session: codeConsole.sessionContext.session,
1276
+ widget: consolePanel,
1277
+ sanitizer: sanitizer
1278
+ };
1279
+ manager.updateCompleter(newContext).catch(console.error);
1280
+ });
1281
+ consolePanel.console.sessionContext.sessionChanged.connect(() => {
1282
+ const newContext = {
1283
+ editor: consolePanel.console.promptCell?.editor ?? null,
1284
+ session: consolePanel.console.sessionContext.session,
1285
+ widget: consolePanel,
1286
+ sanitizer: sanitizer
1287
+ };
1288
+ manager.updateCompleter(newContext).catch(console.error);
1289
+ });
1290
+ };
1291
+
1292
+ debugConsoleTracker.widgetAdded.connect(updateCompleter);
1293
+
1294
+ manager.activeProvidersChanged.connect(() => {
1295
+ debugConsoleTracker.forEach(consoleWidget => {
1296
+ updateCompleter(undefined, consoleWidget).catch(e => console.error(e));
1297
+ });
1298
+ });
1299
+
1300
+ // Add commands
1301
+ app.commands.addCommand(CommandIDs.invokeConsole, {
1302
+ label: trans.__('Display the tab completion widget.'),
1303
+ execute: () => {
1304
+ const id =
1305
+ debugConsoleTracker.currentWidget &&
1306
+ debugConsoleTracker.currentWidget.id;
1307
+
1308
+ if (id) {
1309
+ return manager.invoke(id);
1310
+ }
1311
+ },
1312
+ describedBy: {
1313
+ args: {
1314
+ type: 'object',
1315
+ properties: {}
1316
+ }
1317
+ }
1318
+ });
1319
+
1320
+ app.commands.addCommand(CommandIDs.selectConsole, {
1321
+ label: trans.__('Select the completion suggestion.'),
1322
+ execute: () => {
1323
+ const id =
1324
+ debugConsoleTracker.currentWidget &&
1325
+ debugConsoleTracker.currentWidget.id;
1326
+
1327
+ if (id) {
1328
+ return manager.select(id);
1329
+ }
1330
+ },
1331
+ describedBy: {
1332
+ args: {
1333
+ type: 'object',
1334
+ properties: {}
1335
+ }
1336
+ }
1337
+ });
1338
+
1339
+ // Add the debugger console execute command
1340
+ app.commands.addCommand(CommandIDs.executeConsole, {
1341
+ label: trans.__('Execute the current line in debug console.'),
1342
+ execute: async () => {
1343
+ const currentWidget = debugConsoleTracker.currentWidget;
1344
+ if (currentWidget && currentWidget.console) {
1345
+ await currentWidget.console.execute(true);
1346
+ // Ensure focus stays on the console prompt after execution
1347
+ const promptCell = currentWidget.console.promptCell;
1348
+ if (promptCell && promptCell.editor) {
1349
+ promptCell.editor.focus();
1350
+ }
1351
+ }
1352
+ },
1353
+ describedBy: {
1354
+ args: {
1355
+ type: 'object',
1356
+ properties: {}
1357
+ }
1358
+ }
1359
+ });
1360
+
1361
+ app.commands.addCommand(CommandIDs.evaluate, {
1362
+ label: trans.__('Evaluate Code'),
1363
+ caption: trans.__('Evaluate Code'),
1364
+ icon: Debugger.Icons.evaluateIcon,
1365
+ isEnabled: () => !!service.session?.isStarted,
1366
+ execute: async () => {
1367
+ if (debugConsoleWidget) {
1368
+ debugConsoleWidget.dispose();
1369
+ } else {
1370
+ void createDebugConsole();
1371
+ }
1372
+ },
1373
+ isToggled: () => {
1374
+ return debugConsoleWidget !== null;
1375
+ },
1376
+ describedBy: {
1377
+ args: {
1378
+ type: 'object',
1379
+ properties: {}
1380
+ }
1381
+ }
1382
+ });
1383
+
1384
+ // Add the keybindings
1385
+ app.commands.addKeyBinding({
1386
+ command: CommandIDs.selectConsole,
1387
+ keys: ['Enter'],
1388
+ selector:
1389
+ '.jp-ConsolePanel.jp-DebugConsole .jp-DebugConsole-widget .jp-mod-completer-active'
1390
+ });
1391
+
1392
+ app.commands.addKeyBinding({
1393
+ command: CommandIDs.invokeConsole,
1394
+ keys: ['Tab'],
1395
+ selector:
1396
+ '.jp-ConsolePanel.jp-DebugConsole .jp-DebugConsole-widget .jp-CodeConsole-promptCell .jp-mod-completer-enabled:not(.jp-mod-at-line-beginning)'
1397
+ });
1398
+
1399
+ app.commands.addKeyBinding({
1400
+ command: CommandIDs.executeConsole,
1401
+ keys: ['Shift Enter'],
1402
+ selector:
1403
+ '.jp-ConsolePanel.jp-DebugConsole .jp-DebugConsole-widget .jp-CodeConsole-promptCell'
1404
+ });
1405
+ }
1406
+ };
1407
+
1189
1408
  /**
1190
1409
  * Export the plugins as default.
1191
1410
  */
@@ -1199,7 +1418,9 @@ const plugins: JupyterFrontEndPlugin<any>[] = [
1199
1418
  main,
1200
1419
  sources,
1201
1420
  sourceViewer,
1202
- configuration
1421
+ configuration,
1422
+ debuggerCompletions,
1423
+ debugConsole
1203
1424
  ];
1204
1425
 
1205
1426
  export default plugins;
package/style/index.css CHANGED
@@ -9,9 +9,8 @@
9
9
  @import url('~@jupyterlab/rendermime/style/index.css');
10
10
  @import url('~@jupyterlab/docregistry/style/index.css');
11
11
  @import url('~@jupyterlab/application/style/index.css');
12
- @import url('~@jupyterlab/cells/style/index.css');
12
+ @import url('~@jupyterlab/completer/style/index.css');
13
13
  @import url('~@jupyterlab/console/style/index.css');
14
14
  @import url('~@jupyterlab/fileeditor/style/index.css');
15
15
  @import url('~@jupyterlab/notebook/style/index.css');
16
16
  @import url('~@jupyterlab/debugger/style/index.css');
17
- @import url('~@jupyterlab/logconsole/style/index.css');
package/style/index.js CHANGED
@@ -9,9 +9,8 @@ import '@jupyterlab/codeeditor/style/index.js';
9
9
  import '@jupyterlab/rendermime/style/index.js';
10
10
  import '@jupyterlab/docregistry/style/index.js';
11
11
  import '@jupyterlab/application/style/index.js';
12
- import '@jupyterlab/cells/style/index.js';
12
+ import '@jupyterlab/completer/style/index.js';
13
13
  import '@jupyterlab/console/style/index.js';
14
14
  import '@jupyterlab/fileeditor/style/index.js';
15
15
  import '@jupyterlab/notebook/style/index.js';
16
16
  import '@jupyterlab/debugger/style/index.js';
17
- import '@jupyterlab/logconsole/style/index.js';