@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/lib/debug-console-executor.d.ts +42 -0
- package/lib/debug-console-executor.js +63 -0
- package/lib/debug-console-executor.js.map +1 -0
- package/lib/debugger-completion-provider.d.ts +30 -0
- package/lib/debugger-completion-provider.js +146 -0
- package/lib/debugger-completion-provider.js.map +1 -0
- package/lib/index.js +239 -65
- package/lib/index.js.map +1 -1
- package/package.json +17 -17
- package/src/debug-console-executor.ts +119 -0
- package/src/debugger-completion-provider.ts +195 -0
- package/src/index.ts +290 -69
- package/style/index.css +1 -2
- package/style/index.js +1 -2
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { IConsoleCellExecutor } from '@jupyterlab/console';
|
|
2
|
+
import { IDebugger } from '@jupyterlab/debugger';
|
|
3
|
+
import { ExecutionCount, IDisplayData } from '@jupyterlab/nbformat';
|
|
4
|
+
import { TranslationBundle } from '@jupyterlab/translation';
|
|
5
|
+
/**
|
|
6
|
+
* Custom console cell executor that uses debugger evaluation.
|
|
7
|
+
*/
|
|
8
|
+
export declare class DebugConsoleCellExecutor implements IConsoleCellExecutor {
|
|
9
|
+
constructor(options: DebugConsoleCellExecutor.IOptions);
|
|
10
|
+
/**
|
|
11
|
+
* Create an IDisplayData object with the given text content.
|
|
12
|
+
*/
|
|
13
|
+
private createDisplayData;
|
|
14
|
+
evaluateWithDebugger(options: {
|
|
15
|
+
code: string;
|
|
16
|
+
executionCount: ExecutionCount;
|
|
17
|
+
}): Promise<IDisplayData | null>;
|
|
18
|
+
/**
|
|
19
|
+
* Execute a cell using debugger evaluation.
|
|
20
|
+
*/
|
|
21
|
+
runCell(options: IConsoleCellExecutor.IRunCellOptions): Promise<boolean>;
|
|
22
|
+
private _debuggerService;
|
|
23
|
+
private _trans;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* A namespace for DebugConsoleCellExecutor statics.
|
|
27
|
+
*/
|
|
28
|
+
export declare namespace DebugConsoleCellExecutor {
|
|
29
|
+
/**
|
|
30
|
+
* The instantiation options for a DebugConsoleCellExecutor.
|
|
31
|
+
*/
|
|
32
|
+
interface IOptions {
|
|
33
|
+
/**
|
|
34
|
+
* The debugger service for evaluating expressions in debug context.
|
|
35
|
+
*/
|
|
36
|
+
debuggerService: IDebugger;
|
|
37
|
+
/**
|
|
38
|
+
* The translation bundle for internationalization.
|
|
39
|
+
*/
|
|
40
|
+
trans: TranslationBundle;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom console cell executor that uses debugger evaluation.
|
|
3
|
+
*/
|
|
4
|
+
export class DebugConsoleCellExecutor {
|
|
5
|
+
constructor(options) {
|
|
6
|
+
this._debuggerService = options.debuggerService;
|
|
7
|
+
this._trans = options.trans;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Create an IDisplayData object with the given text content.
|
|
11
|
+
*/
|
|
12
|
+
createDisplayData(text, executionCount) {
|
|
13
|
+
return {
|
|
14
|
+
output_type: 'display_data',
|
|
15
|
+
data: {
|
|
16
|
+
'text/plain': text
|
|
17
|
+
},
|
|
18
|
+
metadata: {
|
|
19
|
+
execution_count: executionCount
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
async evaluateWithDebugger(options) {
|
|
24
|
+
const { code, executionCount } = options;
|
|
25
|
+
try {
|
|
26
|
+
// Check if debugger has stopped threads (required for evaluation)
|
|
27
|
+
if (!this._debuggerService.hasStoppedThreads()) {
|
|
28
|
+
return this.createDisplayData(this._trans.__('Debugger does not have stopped threads - cannot evaluate'), executionCount);
|
|
29
|
+
}
|
|
30
|
+
// Evaluate the code using the debugger service
|
|
31
|
+
const reply = await this._debuggerService.evaluate(code);
|
|
32
|
+
if (!reply) {
|
|
33
|
+
return this.createDisplayData(this._trans.__('Evaluation resulted in an error'), executionCount);
|
|
34
|
+
}
|
|
35
|
+
// Convert reply to IDisplayData format
|
|
36
|
+
return this.createDisplayData(reply.result, executionCount);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error('Error evaluating code with debugger:', error);
|
|
40
|
+
return this.createDisplayData(`Error: ${error}`, executionCount);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Execute a cell using debugger evaluation.
|
|
45
|
+
*/
|
|
46
|
+
async runCell(options) {
|
|
47
|
+
const { cell } = options;
|
|
48
|
+
const code = cell.model.sharedModel.getSource();
|
|
49
|
+
const executionCount = cell.model.sharedModel.execution_count;
|
|
50
|
+
const outputDisplayData = await this.evaluateWithDebugger({
|
|
51
|
+
code,
|
|
52
|
+
executionCount
|
|
53
|
+
});
|
|
54
|
+
if (!outputDisplayData) {
|
|
55
|
+
const errorOutputData = this.createDisplayData(this._trans.__('Could not display output data'), executionCount);
|
|
56
|
+
cell.model.outputs.add(errorOutputData);
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
cell.model.outputs.add(outputDisplayData);
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=debug-console-executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug-console-executor.js","sourceRoot":"","sources":["../src/debug-console-executor.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,OAAO,wBAAwB;IACnC,YAAY,OAA0C;QACpD,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;QAChD,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAC9B,CAAC;IAED;;OAEG;IACK,iBAAiB,CACvB,IAAY,EACZ,cAA8B;QAE9B,OAAO;YACL,WAAW,EAAE,cAAc;YAC3B,IAAI,EAAE;gBACJ,YAAY,EAAE,IAAI;aACnB;YACD,QAAQ,EAAE;gBACR,eAAe,EAAE,cAAc;aAChC;SACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,OAG1B;QACC,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;QAEzC,IAAI,CAAC;YACH,kEAAkE;YAClE,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,iBAAiB,EAAE,EAAE,CAAC;gBAC/C,OAAO,IAAI,CAAC,iBAAiB,CAC3B,IAAI,CAAC,MAAM,CAAC,EAAE,CACZ,0DAA0D,CAC3D,EACD,cAAc,CACf,CAAC;YACJ,CAAC;YAED,+CAA+C;YAC/C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAEzD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,IAAI,CAAC,iBAAiB,CAC3B,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,iCAAiC,CAAC,EACjD,cAAc,CACf,CAAC;YACJ,CAAC;YAED,uCAAuC;YACvC,OAAO,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;QAC9D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,KAAK,CAAC,CAAC;YAC7D,OAAO,IAAI,CAAC,iBAAiB,CAAC,UAAU,KAAK,EAAE,EAAE,cAAc,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CACX,OAA6C;QAE7C,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;QAEzB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;QAChD,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,eAAe,CAAC;QAC9D,MAAM,iBAAiB,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC;YACxD,IAAI;YACJ,cAAc;SACf,CAAC,CAAC;QAEH,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,MAAM,eAAe,GAAG,IAAI,CAAC,iBAAiB,CAC5C,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,+BAA+B,CAAC,EAC/C,cAAc,CACf,CAAC;YACF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;YACxC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC;IACd,CAAC;CAIF"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { CompletionTriggerKind, ICompletionContext, ICompletionProvider } from '@jupyterlab/completer';
|
|
2
|
+
import type { CompletionHandler } from '@jupyterlab/completer';
|
|
3
|
+
import { IDebugger } from '@jupyterlab/debugger';
|
|
4
|
+
import { ITranslator } from '@jupyterlab/translation';
|
|
5
|
+
/**
|
|
6
|
+
* Completion provider that uses debugger evaluation for suggestions.
|
|
7
|
+
*/
|
|
8
|
+
export declare class DebuggerCompletionProvider implements ICompletionProvider {
|
|
9
|
+
protected options: DebuggerCompletionProvider.IOptions;
|
|
10
|
+
readonly identifier = "DebuggerCompletionProvider";
|
|
11
|
+
readonly name: string;
|
|
12
|
+
readonly rank = 1000;
|
|
13
|
+
constructor(options: DebuggerCompletionProvider.IOptions);
|
|
14
|
+
/**
|
|
15
|
+
* Check if this completion provider is applicable to the given context.
|
|
16
|
+
*/
|
|
17
|
+
isApplicable(context: ICompletionContext): Promise<boolean>;
|
|
18
|
+
/**
|
|
19
|
+
* Fetch completion suggestions using debugger evaluation.
|
|
20
|
+
*/
|
|
21
|
+
fetch(request: CompletionHandler.IRequest, context: ICompletionContext, trigger?: CompletionTriggerKind): Promise<CompletionHandler.ICompletionItemsReply>;
|
|
22
|
+
private _trans;
|
|
23
|
+
private _debuggerService;
|
|
24
|
+
}
|
|
25
|
+
export declare namespace DebuggerCompletionProvider {
|
|
26
|
+
interface IOptions {
|
|
27
|
+
debuggerService: IDebugger;
|
|
28
|
+
translator?: ITranslator;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// Copyright (c) Jupyter Development Team.
|
|
2
|
+
// Distributed under the terms of the Modified BSD License.
|
|
3
|
+
import { nullTranslator } from '@jupyterlab/translation';
|
|
4
|
+
/**
|
|
5
|
+
* Completion provider that uses debugger evaluation for suggestions.
|
|
6
|
+
*/
|
|
7
|
+
export class DebuggerCompletionProvider {
|
|
8
|
+
constructor(options) {
|
|
9
|
+
this.options = options;
|
|
10
|
+
this.identifier = 'DebuggerCompletionProvider';
|
|
11
|
+
this.rank = 1000;
|
|
12
|
+
const translator = options.translator || nullTranslator;
|
|
13
|
+
this._trans = translator.load('jupyterlab');
|
|
14
|
+
this.name = this._trans.__('Debugger');
|
|
15
|
+
this._debuggerService = options.debuggerService;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Check if this completion provider is applicable to the given context.
|
|
19
|
+
*/
|
|
20
|
+
async isApplicable(context) {
|
|
21
|
+
var _a, _b, _c;
|
|
22
|
+
try {
|
|
23
|
+
const spec = await ((_c = (_b = (_a = this._debuggerService.session) === null || _a === void 0 ? void 0 : _a.connection) === null || _b === void 0 ? void 0 : _b.kernel) === null || _c === void 0 ? void 0 : _c.spec);
|
|
24
|
+
return (spec === null || spec === void 0 ? void 0 : spec.language) === 'python';
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Fetch completion suggestions using debugger evaluation.
|
|
32
|
+
*/
|
|
33
|
+
async fetch(request, context, trigger) {
|
|
34
|
+
var _a, _b;
|
|
35
|
+
let items = [];
|
|
36
|
+
let parsedResult;
|
|
37
|
+
try {
|
|
38
|
+
const { text, offset } = request;
|
|
39
|
+
const pyCode = `
|
|
40
|
+
from IPython.core.completer import provisionalcompleter as _provisionalcompleter
|
|
41
|
+
from IPython.core.completer import rectify_completions as _rectify_completions
|
|
42
|
+
from IPython.core.completer import IPCompleter
|
|
43
|
+
_EXPERIMENTAL_KEY_NAME = "_jupyter_types_experimental"
|
|
44
|
+
|
|
45
|
+
def getCompletionsForDebugger(code, cursor_pos):
|
|
46
|
+
ip = get_ipython()
|
|
47
|
+
|
|
48
|
+
# Access the current debugger frame
|
|
49
|
+
import inspect
|
|
50
|
+
current_frame = inspect.currentframe()
|
|
51
|
+
|
|
52
|
+
# Get the frame that called this function (the debugger's target frame)
|
|
53
|
+
caller_frame = current_frame.f_back if current_frame else None
|
|
54
|
+
|
|
55
|
+
# Get the debugger's frame variables
|
|
56
|
+
if caller_frame:
|
|
57
|
+
frame_locals = caller_frame.f_locals
|
|
58
|
+
frame_globals = caller_frame.f_globals
|
|
59
|
+
else:
|
|
60
|
+
frame_locals = locals()
|
|
61
|
+
frame_globals = globals()
|
|
62
|
+
|
|
63
|
+
local_completer = IPCompleter(shell=ip, namespace=frame_locals, global_namespace=frame_globals, parent=ip)
|
|
64
|
+
|
|
65
|
+
with _provisionalcompleter():
|
|
66
|
+
raw_completions = local_completer.completions(code, cursor_pos)
|
|
67
|
+
completions = list(_rectify_completions(code, raw_completions))
|
|
68
|
+
|
|
69
|
+
comps = []
|
|
70
|
+
for comp in completions:
|
|
71
|
+
comps.append(
|
|
72
|
+
dict(
|
|
73
|
+
start=comp.start,
|
|
74
|
+
end=comp.end,
|
|
75
|
+
text=comp.text,
|
|
76
|
+
type=comp.type,
|
|
77
|
+
signature=comp.signature,
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
if completions:
|
|
82
|
+
s = completions[0].start
|
|
83
|
+
e = completions[0].end
|
|
84
|
+
matches = [c.text for c in completions]
|
|
85
|
+
types = [c.type for c in completions]
|
|
86
|
+
else:
|
|
87
|
+
s = cursor_pos
|
|
88
|
+
e = cursor_pos
|
|
89
|
+
matches = []
|
|
90
|
+
types = []
|
|
91
|
+
|
|
92
|
+
result = {
|
|
93
|
+
"matches": matches,
|
|
94
|
+
"types": types,
|
|
95
|
+
"cursor_end": e,
|
|
96
|
+
"cursor_start": s,
|
|
97
|
+
"status": "ok",
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return result
|
|
101
|
+
`;
|
|
102
|
+
// create method
|
|
103
|
+
await this._debuggerService.evaluate(pyCode);
|
|
104
|
+
const debuggerCompletions = `getCompletionsForDebugger(${JSON.stringify(text)}, ${offset})`;
|
|
105
|
+
const evalReply = await this._debuggerService.evaluate(debuggerCompletions);
|
|
106
|
+
if (!evalReply) {
|
|
107
|
+
return { start: 0, end: 0, items: [] };
|
|
108
|
+
}
|
|
109
|
+
const matches = evalReply.result;
|
|
110
|
+
// Replace single quotes with double quotes in matches string for JSON parsing
|
|
111
|
+
let correctedMatches = matches.replace(/'/g, '"');
|
|
112
|
+
// TODO - Investigate truncation
|
|
113
|
+
// The eval reply from kernel truncates the result string (a string representation
|
|
114
|
+
// of an array containing completion results). Anything after a certain number of
|
|
115
|
+
// matches (19 for ipykernel) is replaced by ellipses, which needs to be removed to parse into JSON.
|
|
116
|
+
correctedMatches = correctedMatches.replace(/, \.\.\./g, '');
|
|
117
|
+
try {
|
|
118
|
+
parsedResult = JSON.parse(correctedMatches);
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
console.error('Failed to parse corrected matches:', error);
|
|
122
|
+
return { start: 0, end: 0, items: [] };
|
|
123
|
+
}
|
|
124
|
+
// Parse completions into completion items
|
|
125
|
+
const parsedCompletions = parsedResult.matches.map((match, index) => {
|
|
126
|
+
var _a;
|
|
127
|
+
return ({
|
|
128
|
+
label: match,
|
|
129
|
+
insertText: match,
|
|
130
|
+
type: ((_a = parsedResult.types) === null || _a === void 0 ? void 0 : _a[index]) || undefined
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
items = [...parsedCompletions];
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
console.warn('Error fetching debugger completions:', error);
|
|
137
|
+
// Return empty items on error
|
|
138
|
+
return { start: 0, end: 0, items: [] };
|
|
139
|
+
}
|
|
140
|
+
// Extract cursor positions from the parsed result if available
|
|
141
|
+
const start = (_a = parsedResult.cursor_start) !== null && _a !== void 0 ? _a : 0;
|
|
142
|
+
const end = (_b = parsedResult.cursor_end) !== null && _b !== void 0 ? _b : 0;
|
|
143
|
+
return { start, end, items };
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=debugger-completion-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debugger-completion-provider.js","sourceRoot":"","sources":["../src/debugger-completion-provider.ts"],"names":[],"mappings":"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"}
|
package/lib/index.js
CHANGED
|
@@ -5,19 +5,21 @@
|
|
|
5
5
|
* @module debugger-extension
|
|
6
6
|
*/
|
|
7
7
|
import { ILabShell, ILayoutRestorer } from '@jupyterlab/application';
|
|
8
|
-
import { Clipboard, Dialog, ICommandPalette, InputDialog, ISessionContextDialogs, IThemeManager, MainAreaWidget, SessionContextDialogs, showDialog
|
|
9
|
-
import { CodeCell } from '@jupyterlab/cells';
|
|
8
|
+
import { Clipboard, Dialog, ICommandPalette, InputDialog, ISanitizer, ISessionContextDialogs, IThemeManager, MainAreaWidget, SessionContextDialogs, showDialog } from '@jupyterlab/apputils';
|
|
10
9
|
import { IEditorServices } from '@jupyterlab/codeeditor';
|
|
11
10
|
import { ConsolePanel, IConsoleTracker } from '@jupyterlab/console';
|
|
12
11
|
import { PageConfig, PathExt } from '@jupyterlab/coreutils';
|
|
13
12
|
import { Debugger, IDebugger, IDebuggerConfig, IDebuggerHandler, IDebuggerSidebar, IDebuggerSources, IDebuggerSourceViewer } from '@jupyterlab/debugger';
|
|
14
13
|
import { DocumentWidget } from '@jupyterlab/docregistry';
|
|
15
14
|
import { FileEditor, IEditorTracker } from '@jupyterlab/fileeditor';
|
|
16
|
-
import { ILoggerRegistry } from '@jupyterlab/logconsole';
|
|
17
15
|
import { INotebookTracker, NotebookActions, NotebookPanel } from '@jupyterlab/notebook';
|
|
18
16
|
import { standardRendererFactories as initialFactories, IRenderMimeRegistry, RenderMimeRegistry } from '@jupyterlab/rendermime';
|
|
19
17
|
import { ISettingRegistry } from '@jupyterlab/settingregistry';
|
|
20
18
|
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
|
|
19
|
+
import { ICompletionProviderManager } from '@jupyterlab/completer';
|
|
20
|
+
import { WidgetTracker } from '@jupyterlab/apputils';
|
|
21
|
+
import { DebugConsoleCellExecutor } from './debug-console-executor';
|
|
22
|
+
import { DebuggerCompletionProvider } from './debugger-completion-provider';
|
|
21
23
|
function notifyCommands(commands) {
|
|
22
24
|
Object.values(Debugger.CommandIDs).forEach(command => {
|
|
23
25
|
if (commands.hasCommand(command)) {
|
|
@@ -261,7 +263,7 @@ const sources = {
|
|
|
261
263
|
});
|
|
262
264
|
}
|
|
263
265
|
};
|
|
264
|
-
|
|
266
|
+
/**
|
|
265
267
|
* A plugin to open detailed views for variables.
|
|
266
268
|
*/
|
|
267
269
|
const variables = {
|
|
@@ -661,17 +663,23 @@ const sourceViewer = {
|
|
|
661
663
|
const main = {
|
|
662
664
|
id: '@jupyterlab/debugger-extension:main',
|
|
663
665
|
description: 'Initialize the debugger user interface.',
|
|
664
|
-
requires: [
|
|
666
|
+
requires: [
|
|
667
|
+
IDebugger,
|
|
668
|
+
IDebuggerSidebar,
|
|
669
|
+
IEditorServices,
|
|
670
|
+
ITranslator,
|
|
671
|
+
ConsolePanel.IContentFactory,
|
|
672
|
+
IConsoleTracker
|
|
673
|
+
],
|
|
665
674
|
optional: [
|
|
666
675
|
ICommandPalette,
|
|
667
676
|
IDebuggerSourceViewer,
|
|
668
677
|
ILabShell,
|
|
669
678
|
ILayoutRestorer,
|
|
670
|
-
ILoggerRegistry,
|
|
671
679
|
ISettingRegistry
|
|
672
680
|
],
|
|
673
681
|
autoStart: true,
|
|
674
|
-
activate: async (app, service, sidebar, editorServices, translator, palette, sourceViewer, labShell, restorer,
|
|
682
|
+
activate: async (app, service, sidebar, editorServices, translator, consolePanelContentFactory, consoleTracker, palette, sourceViewer, labShell, restorer, settingRegistry) => {
|
|
675
683
|
var _a;
|
|
676
684
|
const trans = translator.load('jupyterlab');
|
|
677
685
|
const { commands, shell, serviceManager } = app;
|
|
@@ -692,63 +700,6 @@ const main = {
|
|
|
692
700
|
return;
|
|
693
701
|
}
|
|
694
702
|
}
|
|
695
|
-
// get the mime type of the kernel language for the current debug session
|
|
696
|
-
const getMimeType = async () => {
|
|
697
|
-
var _a, _b, _c;
|
|
698
|
-
const kernel = (_b = (_a = service.session) === null || _a === void 0 ? void 0 : _a.connection) === null || _b === void 0 ? void 0 : _b.kernel;
|
|
699
|
-
if (!kernel) {
|
|
700
|
-
return '';
|
|
701
|
-
}
|
|
702
|
-
const info = (await kernel.info).language_info;
|
|
703
|
-
const name = info.name;
|
|
704
|
-
const mimeType = (_c = editorServices.mimeTypeService.getMimeTypeByLanguage({ name })) !== null && _c !== void 0 ? _c : '';
|
|
705
|
-
return mimeType;
|
|
706
|
-
};
|
|
707
|
-
const rendermime = new RenderMimeRegistry({ initialFactories });
|
|
708
|
-
commands.addCommand(CommandIDs.evaluate, {
|
|
709
|
-
label: trans.__('Evaluate Code'),
|
|
710
|
-
caption: trans.__('Evaluate Code'),
|
|
711
|
-
icon: Debugger.Icons.evaluateIcon,
|
|
712
|
-
isEnabled: () => service.hasStoppedThreads(),
|
|
713
|
-
execute: async () => {
|
|
714
|
-
var _a, _b, _c;
|
|
715
|
-
const mimeType = await getMimeType();
|
|
716
|
-
const result = await Debugger.Dialogs.getCode({
|
|
717
|
-
title: trans.__('Evaluate Code'),
|
|
718
|
-
okLabel: trans.__('Evaluate'),
|
|
719
|
-
cancelLabel: trans.__('Cancel'),
|
|
720
|
-
mimeType,
|
|
721
|
-
contentFactory: new CodeCell.ContentFactory({
|
|
722
|
-
editorFactory: options => editorServices.factoryService.newInlineEditor(options)
|
|
723
|
-
}),
|
|
724
|
-
rendermime
|
|
725
|
-
});
|
|
726
|
-
const code = result.value;
|
|
727
|
-
if (!result.button.accept || !code) {
|
|
728
|
-
return;
|
|
729
|
-
}
|
|
730
|
-
const reply = await service.evaluate(code);
|
|
731
|
-
if (reply) {
|
|
732
|
-
const data = reply.result;
|
|
733
|
-
const path = (_b = (_a = service === null || service === void 0 ? void 0 : service.session) === null || _a === void 0 ? void 0 : _a.connection) === null || _b === void 0 ? void 0 : _b.path;
|
|
734
|
-
const logger = path ? (_c = loggerRegistry === null || loggerRegistry === void 0 ? void 0 : loggerRegistry.getLogger) === null || _c === void 0 ? void 0 : _c.call(loggerRegistry, path) : undefined;
|
|
735
|
-
if (logger) {
|
|
736
|
-
// print to log console of the notebook currently being debugged
|
|
737
|
-
logger.log({ type: 'text', data, level: logger.level });
|
|
738
|
-
}
|
|
739
|
-
else {
|
|
740
|
-
// fallback to printing to devtools console
|
|
741
|
-
console.debug(data);
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
},
|
|
745
|
-
describedBy: {
|
|
746
|
-
args: {
|
|
747
|
-
type: 'object',
|
|
748
|
-
properties: {}
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
});
|
|
752
703
|
commands.addCommand(CommandIDs.debugContinue, {
|
|
753
704
|
label: () => {
|
|
754
705
|
return service.hasStoppedThreads()
|
|
@@ -968,6 +919,227 @@ const main = {
|
|
|
968
919
|
}
|
|
969
920
|
}
|
|
970
921
|
};
|
|
922
|
+
/**
|
|
923
|
+
* A plugin that provides debugger-based completions.
|
|
924
|
+
*/
|
|
925
|
+
const debuggerCompletions = {
|
|
926
|
+
id: '@jupyterlab/debugger-extension:completions',
|
|
927
|
+
description: 'Provides debugger-based completions.',
|
|
928
|
+
autoStart: true,
|
|
929
|
+
requires: [IDebugger, ICompletionProviderManager],
|
|
930
|
+
optional: [ITranslator],
|
|
931
|
+
activate: (app, debuggerService, completionManager, translator) => {
|
|
932
|
+
// Create and register the debugger completion provider
|
|
933
|
+
const provider = new DebuggerCompletionProvider({
|
|
934
|
+
debuggerService: debuggerService,
|
|
935
|
+
translator: translator || nullTranslator
|
|
936
|
+
});
|
|
937
|
+
// Register the provider with the completion manager
|
|
938
|
+
completionManager.registerProvider(provider);
|
|
939
|
+
}
|
|
940
|
+
};
|
|
941
|
+
/**
|
|
942
|
+
* A plugin that provides the debug console functionality.
|
|
943
|
+
*/
|
|
944
|
+
const debugConsole = {
|
|
945
|
+
id: '@jupyterlab/debugger-extension:debug-console',
|
|
946
|
+
description: 'Debugger console to enable evaluation in debugger context.',
|
|
947
|
+
autoStart: true,
|
|
948
|
+
requires: [
|
|
949
|
+
IDebugger,
|
|
950
|
+
ConsolePanel.IContentFactory,
|
|
951
|
+
IEditorServices,
|
|
952
|
+
ICompletionProviderManager,
|
|
953
|
+
ISanitizer,
|
|
954
|
+
ITranslator
|
|
955
|
+
],
|
|
956
|
+
optional: [ILabShell],
|
|
957
|
+
activate: (app, service, consolePanelContentFactory, editorServices, manager, sanitizer, translator, labShell) => {
|
|
958
|
+
const CommandIDs = Debugger.CommandIDs;
|
|
959
|
+
const trans = translator.load('jupyterlab');
|
|
960
|
+
// Create our own tracker for debug consoles
|
|
961
|
+
const debugConsoleTracker = new WidgetTracker({
|
|
962
|
+
namespace: 'debugger-debug-console'
|
|
963
|
+
});
|
|
964
|
+
// Global debug console widget variable for toggling
|
|
965
|
+
let debugConsoleWidget = null;
|
|
966
|
+
// Create the console
|
|
967
|
+
const createDebugConsole = async () => {
|
|
968
|
+
const rendermime = new RenderMimeRegistry({ initialFactories });
|
|
969
|
+
const debugExecutor = new DebugConsoleCellExecutor({
|
|
970
|
+
debuggerService: service,
|
|
971
|
+
trans
|
|
972
|
+
});
|
|
973
|
+
debugConsoleWidget = new ConsolePanel({
|
|
974
|
+
manager: app.serviceManager,
|
|
975
|
+
name: trans.__('Debug Console'),
|
|
976
|
+
contentFactory: consolePanelContentFactory,
|
|
977
|
+
rendermime,
|
|
978
|
+
executor: debugExecutor,
|
|
979
|
+
mimeTypeService: editorServices.mimeTypeService,
|
|
980
|
+
kernelPreference: { shouldStart: false, canStart: false }
|
|
981
|
+
});
|
|
982
|
+
debugConsoleWidget.title.label = trans.__('Debug Console');
|
|
983
|
+
debugConsoleWidget.title.icon = Debugger.Icons.evaluateIcon;
|
|
984
|
+
// Add a specific class to distinguish debug console from regular consoles
|
|
985
|
+
debugConsoleWidget.addClass('jp-DebugConsole');
|
|
986
|
+
debugConsoleWidget.console.addClass('jp-DebugConsole-widget');
|
|
987
|
+
// Close console when debugger is terminated
|
|
988
|
+
service.eventMessage.connect((_, event) => {
|
|
989
|
+
if (labShell && event.event === 'terminated') {
|
|
990
|
+
debugConsoleWidget === null || debugConsoleWidget === void 0 ? void 0 : debugConsoleWidget.dispose();
|
|
991
|
+
}
|
|
992
|
+
});
|
|
993
|
+
const notifyCommands = () => {
|
|
994
|
+
app.commands.notifyCommandChanged(CommandIDs.evaluate);
|
|
995
|
+
app.commands.notifyCommandChanged(CommandIDs.executeConsole);
|
|
996
|
+
app.commands.notifyCommandChanged(CommandIDs.invokeConsole);
|
|
997
|
+
app.commands.notifyCommandChanged(CommandIDs.selectConsole);
|
|
998
|
+
};
|
|
999
|
+
debugConsoleWidget.disposed.connect(() => {
|
|
1000
|
+
debugConsoleWidget = null;
|
|
1001
|
+
});
|
|
1002
|
+
app.shell.add(debugConsoleWidget, 'main', {
|
|
1003
|
+
mode: 'split-bottom',
|
|
1004
|
+
activate: true,
|
|
1005
|
+
type: 'Debugger console'
|
|
1006
|
+
});
|
|
1007
|
+
void debugConsoleTracker.add(debugConsoleWidget);
|
|
1008
|
+
app.shell.activateById(debugConsoleWidget.id);
|
|
1009
|
+
await updateCompleter(undefined, debugConsoleWidget);
|
|
1010
|
+
debugConsoleWidget === null || debugConsoleWidget === void 0 ? void 0 : debugConsoleWidget.update();
|
|
1011
|
+
notifyCommands();
|
|
1012
|
+
};
|
|
1013
|
+
// Set up completer
|
|
1014
|
+
const updateCompleter = async (_, consolePanel) => {
|
|
1015
|
+
var _a, _b;
|
|
1016
|
+
const completerContext = {
|
|
1017
|
+
editor: (_b = (_a = consolePanel.console.promptCell) === null || _a === void 0 ? void 0 : _a.editor) !== null && _b !== void 0 ? _b : null,
|
|
1018
|
+
session: consolePanel.console.sessionContext.session,
|
|
1019
|
+
widget: consolePanel
|
|
1020
|
+
};
|
|
1021
|
+
await manager.updateCompleter(completerContext);
|
|
1022
|
+
consolePanel.console.promptCellCreated.connect((codeConsole, cell) => {
|
|
1023
|
+
const newContext = {
|
|
1024
|
+
editor: cell.editor,
|
|
1025
|
+
session: codeConsole.sessionContext.session,
|
|
1026
|
+
widget: consolePanel,
|
|
1027
|
+
sanitizer: sanitizer
|
|
1028
|
+
};
|
|
1029
|
+
manager.updateCompleter(newContext).catch(console.error);
|
|
1030
|
+
});
|
|
1031
|
+
consolePanel.console.sessionContext.sessionChanged.connect(() => {
|
|
1032
|
+
var _a, _b;
|
|
1033
|
+
const newContext = {
|
|
1034
|
+
editor: (_b = (_a = consolePanel.console.promptCell) === null || _a === void 0 ? void 0 : _a.editor) !== null && _b !== void 0 ? _b : null,
|
|
1035
|
+
session: consolePanel.console.sessionContext.session,
|
|
1036
|
+
widget: consolePanel,
|
|
1037
|
+
sanitizer: sanitizer
|
|
1038
|
+
};
|
|
1039
|
+
manager.updateCompleter(newContext).catch(console.error);
|
|
1040
|
+
});
|
|
1041
|
+
};
|
|
1042
|
+
debugConsoleTracker.widgetAdded.connect(updateCompleter);
|
|
1043
|
+
manager.activeProvidersChanged.connect(() => {
|
|
1044
|
+
debugConsoleTracker.forEach(consoleWidget => {
|
|
1045
|
+
updateCompleter(undefined, consoleWidget).catch(e => console.error(e));
|
|
1046
|
+
});
|
|
1047
|
+
});
|
|
1048
|
+
// Add commands
|
|
1049
|
+
app.commands.addCommand(CommandIDs.invokeConsole, {
|
|
1050
|
+
label: trans.__('Display the tab completion widget.'),
|
|
1051
|
+
execute: () => {
|
|
1052
|
+
const id = debugConsoleTracker.currentWidget &&
|
|
1053
|
+
debugConsoleTracker.currentWidget.id;
|
|
1054
|
+
if (id) {
|
|
1055
|
+
return manager.invoke(id);
|
|
1056
|
+
}
|
|
1057
|
+
},
|
|
1058
|
+
describedBy: {
|
|
1059
|
+
args: {
|
|
1060
|
+
type: 'object',
|
|
1061
|
+
properties: {}
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
});
|
|
1065
|
+
app.commands.addCommand(CommandIDs.selectConsole, {
|
|
1066
|
+
label: trans.__('Select the completion suggestion.'),
|
|
1067
|
+
execute: () => {
|
|
1068
|
+
const id = debugConsoleTracker.currentWidget &&
|
|
1069
|
+
debugConsoleTracker.currentWidget.id;
|
|
1070
|
+
if (id) {
|
|
1071
|
+
return manager.select(id);
|
|
1072
|
+
}
|
|
1073
|
+
},
|
|
1074
|
+
describedBy: {
|
|
1075
|
+
args: {
|
|
1076
|
+
type: 'object',
|
|
1077
|
+
properties: {}
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
});
|
|
1081
|
+
// Add the debugger console execute command
|
|
1082
|
+
app.commands.addCommand(CommandIDs.executeConsole, {
|
|
1083
|
+
label: trans.__('Execute the current line in debug console.'),
|
|
1084
|
+
execute: async () => {
|
|
1085
|
+
const currentWidget = debugConsoleTracker.currentWidget;
|
|
1086
|
+
if (currentWidget && currentWidget.console) {
|
|
1087
|
+
await currentWidget.console.execute(true);
|
|
1088
|
+
// Ensure focus stays on the console prompt after execution
|
|
1089
|
+
const promptCell = currentWidget.console.promptCell;
|
|
1090
|
+
if (promptCell && promptCell.editor) {
|
|
1091
|
+
promptCell.editor.focus();
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
},
|
|
1095
|
+
describedBy: {
|
|
1096
|
+
args: {
|
|
1097
|
+
type: 'object',
|
|
1098
|
+
properties: {}
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
});
|
|
1102
|
+
app.commands.addCommand(CommandIDs.evaluate, {
|
|
1103
|
+
label: trans.__('Evaluate Code'),
|
|
1104
|
+
caption: trans.__('Evaluate Code'),
|
|
1105
|
+
icon: Debugger.Icons.evaluateIcon,
|
|
1106
|
+
isEnabled: () => { var _a; return !!((_a = service.session) === null || _a === void 0 ? void 0 : _a.isStarted); },
|
|
1107
|
+
execute: async () => {
|
|
1108
|
+
if (debugConsoleWidget) {
|
|
1109
|
+
debugConsoleWidget.dispose();
|
|
1110
|
+
}
|
|
1111
|
+
else {
|
|
1112
|
+
void createDebugConsole();
|
|
1113
|
+
}
|
|
1114
|
+
},
|
|
1115
|
+
isToggled: () => {
|
|
1116
|
+
return debugConsoleWidget !== null;
|
|
1117
|
+
},
|
|
1118
|
+
describedBy: {
|
|
1119
|
+
args: {
|
|
1120
|
+
type: 'object',
|
|
1121
|
+
properties: {}
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
});
|
|
1125
|
+
// Add the keybindings
|
|
1126
|
+
app.commands.addKeyBinding({
|
|
1127
|
+
command: CommandIDs.selectConsole,
|
|
1128
|
+
keys: ['Enter'],
|
|
1129
|
+
selector: '.jp-ConsolePanel.jp-DebugConsole .jp-DebugConsole-widget .jp-mod-completer-active'
|
|
1130
|
+
});
|
|
1131
|
+
app.commands.addKeyBinding({
|
|
1132
|
+
command: CommandIDs.invokeConsole,
|
|
1133
|
+
keys: ['Tab'],
|
|
1134
|
+
selector: '.jp-ConsolePanel.jp-DebugConsole .jp-DebugConsole-widget .jp-CodeConsole-promptCell .jp-mod-completer-enabled:not(.jp-mod-at-line-beginning)'
|
|
1135
|
+
});
|
|
1136
|
+
app.commands.addKeyBinding({
|
|
1137
|
+
command: CommandIDs.executeConsole,
|
|
1138
|
+
keys: ['Shift Enter'],
|
|
1139
|
+
selector: '.jp-ConsolePanel.jp-DebugConsole .jp-DebugConsole-widget .jp-CodeConsole-promptCell'
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
};
|
|
971
1143
|
/**
|
|
972
1144
|
* Export the plugins as default.
|
|
973
1145
|
*/
|
|
@@ -981,7 +1153,9 @@ const plugins = [
|
|
|
981
1153
|
main,
|
|
982
1154
|
sources,
|
|
983
1155
|
sourceViewer,
|
|
984
|
-
configuration
|
|
1156
|
+
configuration,
|
|
1157
|
+
debuggerCompletions,
|
|
1158
|
+
debugConsole
|
|
985
1159
|
];
|
|
986
1160
|
export default plugins;
|
|
987
1161
|
//# sourceMappingURL=index.js.map
|