@difizen/libro-language-client 0.2.0 → 0.2.2
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/es/common/codeConverter.d.ts +15 -1
- package/es/common/codeConverter.d.ts.map +1 -1
- package/es/common/codeConverter.js +122 -8
- package/es/common/protocolConverter.d.ts +3 -1
- package/es/common/protocolConverter.d.ts.map +1 -1
- package/es/common/protocolConverter.js +85 -2
- package/es/common/vscodeAdaptor/convertor.d.ts.map +1 -1
- package/es/common/vscodeAdaptor/convertor.js +5 -4
- package/es/common/vscodeAdaptor/libroWorkspace.d.ts +3 -2
- package/es/common/vscodeAdaptor/libroWorkspace.d.ts.map +1 -1
- package/es/common/vscodeAdaptor/libroWorkspace.js +21 -5
- package/es/common/vscodeAdaptor/monacoLanguages.d.ts +3 -0
- package/es/common/vscodeAdaptor/monacoLanguages.d.ts.map +1 -1
- package/es/common/vscodeAdaptor/monacoLanguages.js +256 -68
- package/es/index.d.ts +1 -0
- package/es/index.d.ts.map +1 -1
- package/es/index.js +2 -1
- package/es/libro-language-client-contribution.d.ts +4 -0
- package/es/libro-language-client-contribution.d.ts.map +1 -1
- package/es/libro-language-client-contribution.js +108 -30
- package/es/libro-language-client-manager.d.ts +4 -0
- package/es/libro-language-client-manager.d.ts.map +1 -1
- package/es/libro-language-client-manager.js +24 -11
- package/es/util.d.ts +9 -0
- package/es/util.d.ts.map +1 -0
- package/es/util.js +32 -0
- package/package.json +7 -6
- package/src/common/codeConverter.ts +133 -1
- package/src/common/protocolConverter.ts +66 -0
- package/src/common/vscodeAdaptor/convertor.ts +5 -4
- package/src/common/vscodeAdaptor/libroWorkspace.ts +16 -4
- package/src/common/vscodeAdaptor/monacoLanguages.ts +114 -6
- package/src/index.ts +1 -0
- package/src/libro-language-client-contribution.ts +88 -6
- package/src/libro-language-client-manager.ts +9 -1
- package/src/util.ts +43 -0
|
@@ -34,6 +34,8 @@ import type {
|
|
|
34
34
|
TextDocument,
|
|
35
35
|
MarkdownString as VMarkdownString,
|
|
36
36
|
SemanticTokens as VSemanticTokens,
|
|
37
|
+
SignatureHelpContext,
|
|
38
|
+
CodeActionContext,
|
|
37
39
|
} from 'vscode';
|
|
38
40
|
import { URI } from 'vscode-uri';
|
|
39
41
|
|
|
@@ -82,6 +84,8 @@ import {
|
|
|
82
84
|
MarkdownString,
|
|
83
85
|
SemanticTokens,
|
|
84
86
|
LinkedEditingRanges,
|
|
87
|
+
SignatureHelpTriggerKind,
|
|
88
|
+
CodeActionTriggerKind,
|
|
85
89
|
} from './vscodeAdaptor/vscodeAdaptor.js';
|
|
86
90
|
import {
|
|
87
91
|
DiagnosticRelatedInformation,
|
|
@@ -603,6 +607,14 @@ export interface Converter {
|
|
|
603
607
|
// new
|
|
604
608
|
|
|
605
609
|
asTextDcouemnt(value: ls.TextDocumentIdentifier): TextDocument;
|
|
610
|
+
asSignatureHelpContext(
|
|
611
|
+
context: ls.SignatureHelpContext,
|
|
612
|
+
): Promise<SignatureHelpContext>;
|
|
613
|
+
|
|
614
|
+
asCodeActionContext(
|
|
615
|
+
context: ls.CodeActionContext,
|
|
616
|
+
diagnostics: ls.Diagnostic[],
|
|
617
|
+
): Promise<CodeActionContext>;
|
|
606
618
|
}
|
|
607
619
|
|
|
608
620
|
export interface URIConverter {
|
|
@@ -2545,6 +2557,58 @@ export function createConverter(
|
|
|
2545
2557
|
} as TextDocument;
|
|
2546
2558
|
}
|
|
2547
2559
|
|
|
2560
|
+
function asSignatureHelpTriggerKind(
|
|
2561
|
+
triggerKind: ls.SignatureHelpTriggerKind,
|
|
2562
|
+
): SignatureHelpTriggerKind {
|
|
2563
|
+
switch (triggerKind) {
|
|
2564
|
+
case ls.SignatureHelpTriggerKind.ContentChange:
|
|
2565
|
+
return SignatureHelpTriggerKind.ContentChange;
|
|
2566
|
+
case ls.SignatureHelpTriggerKind.TriggerCharacter:
|
|
2567
|
+
return SignatureHelpTriggerKind.TriggerCharacter;
|
|
2568
|
+
default:
|
|
2569
|
+
return SignatureHelpTriggerKind.Invoke;
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2573
|
+
async function asSignatureHelpContext(
|
|
2574
|
+
context: ls.SignatureHelpContext,
|
|
2575
|
+
): Promise<SignatureHelpContext> {
|
|
2576
|
+
const active = await asSignatureHelp(context.activeSignatureHelp);
|
|
2577
|
+
return {
|
|
2578
|
+
triggerKind: asSignatureHelpTriggerKind(context.triggerKind),
|
|
2579
|
+
triggerCharacter: context.triggerCharacter,
|
|
2580
|
+
isRetrigger: context.isRetrigger,
|
|
2581
|
+
activeSignatureHelp: active,
|
|
2582
|
+
};
|
|
2583
|
+
}
|
|
2584
|
+
|
|
2585
|
+
function asCodeActionTriggerKind(
|
|
2586
|
+
trigger?: ls.CodeActionTriggerKind,
|
|
2587
|
+
): CodeActionTriggerKind {
|
|
2588
|
+
switch (trigger) {
|
|
2589
|
+
case ls.CodeActionTriggerKind.Automatic:
|
|
2590
|
+
return CodeActionTriggerKind.Automatic;
|
|
2591
|
+
case ls.CodeActionTriggerKind.Invoked:
|
|
2592
|
+
return CodeActionTriggerKind.Invoke;
|
|
2593
|
+
default:
|
|
2594
|
+
return CodeActionTriggerKind.Invoke;
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
|
|
2598
|
+
async function asCodeActionContext(
|
|
2599
|
+
context: ls.CodeActionContext,
|
|
2600
|
+
diagnostics: ls.Diagnostic[],
|
|
2601
|
+
): Promise<CodeActionContext> {
|
|
2602
|
+
if (context === void 0 || context === null) {
|
|
2603
|
+
return context;
|
|
2604
|
+
}
|
|
2605
|
+
return {
|
|
2606
|
+
diagnostics: await asDiagnostics(diagnostics),
|
|
2607
|
+
only: context.only?.[0] ? asCodeActionKind(context.only[0]) : undefined,
|
|
2608
|
+
triggerKind: asCodeActionTriggerKind(context.triggerKind),
|
|
2609
|
+
};
|
|
2610
|
+
}
|
|
2611
|
+
|
|
2548
2612
|
return {
|
|
2549
2613
|
asUri,
|
|
2550
2614
|
asDocumentSelector,
|
|
@@ -2623,5 +2687,7 @@ export function createConverter(
|
|
|
2623
2687
|
asInlineCompletionItem,
|
|
2624
2688
|
// new
|
|
2625
2689
|
asTextDcouemnt,
|
|
2690
|
+
asSignatureHelpContext,
|
|
2691
|
+
asCodeActionContext,
|
|
2626
2692
|
};
|
|
2627
2693
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CellView, LibroView } from '@difizen/libro-core';
|
|
2
|
+
import { ExecutableNotebookModel } from '@difizen/libro-kernel';
|
|
2
3
|
import type { NotebookCell, NotebookDocument, NotebookRange } from 'vscode';
|
|
3
4
|
|
|
4
5
|
import { NotebookDocumentSyncFeature } from '../notebook.js';
|
|
@@ -9,14 +10,14 @@ import { EndOfLine, NotebookCellKind, Uri } from './vscodeAdaptor.js';
|
|
|
9
10
|
export const l2c = {
|
|
10
11
|
asNotebookDocument(libroView: LibroView): NotebookDocument {
|
|
11
12
|
const model = libroView.model as any;
|
|
12
|
-
if (model
|
|
13
|
-
throw new Error('
|
|
13
|
+
if (!ExecutableNotebookModel.is(model)) {
|
|
14
|
+
throw new Error('invalid libro jupyter model');
|
|
14
15
|
}
|
|
15
16
|
const filePath = model.filePath as string;
|
|
16
17
|
return {
|
|
17
18
|
uri: Uri.parse(filePath),
|
|
18
19
|
notebookType: 'jupyter',
|
|
19
|
-
version:
|
|
20
|
+
version: libroView.model.version,
|
|
20
21
|
isDirty: libroView.model.dirty,
|
|
21
22
|
isUntitled: false,
|
|
22
23
|
isClosed: false,
|
|
@@ -49,7 +50,7 @@ export const l2c = {
|
|
|
49
50
|
fileName: filePath,
|
|
50
51
|
isUntitled: false,
|
|
51
52
|
languageId: 'python',
|
|
52
|
-
version:
|
|
53
|
+
version: cell.model.version,
|
|
53
54
|
isDirty: false,
|
|
54
55
|
isClosed: false,
|
|
55
56
|
save: unsupported,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { LibroView } from '@difizen/libro-core';
|
|
2
|
-
import { LibroService } from '@difizen/libro-core';
|
|
2
|
+
import { LibroService, ILibroWorkspaceService } from '@difizen/libro-core';
|
|
3
|
+
import { ExecutableNotebookModel } from '@difizen/libro-kernel';
|
|
3
4
|
import { inject, noop, singleton } from '@difizen/mana-app';
|
|
4
5
|
import type {
|
|
6
|
+
Uri,
|
|
5
7
|
NotebookDocument,
|
|
6
8
|
WorkspaceFolder,
|
|
7
9
|
Event,
|
|
@@ -22,10 +24,10 @@ import type {
|
|
|
22
24
|
FileWillCreateEvent,
|
|
23
25
|
GlobPattern,
|
|
24
26
|
FileSystemWatcher,
|
|
25
|
-
Uri,
|
|
26
27
|
TextDocument,
|
|
27
28
|
FileSystem,
|
|
28
29
|
} from 'vscode';
|
|
30
|
+
import { URI } from 'vscode-uri';
|
|
29
31
|
|
|
30
32
|
import { l2c } from './convertor.js';
|
|
31
33
|
import { Range } from './extHostTypes.js';
|
|
@@ -37,15 +39,25 @@ import { unsupported } from './util.js';
|
|
|
37
39
|
@singleton({ token: ILibroWorkspace })
|
|
38
40
|
export class LibroWorkspace implements ILibroWorkspace {
|
|
39
41
|
@inject(LibroService) private readonly libroService: LibroService;
|
|
42
|
+
@inject(ILibroWorkspaceService)
|
|
43
|
+
private readonly libroWorkspaceService: ILibroWorkspaceService;
|
|
40
44
|
|
|
41
45
|
isValidNotebook(view: LibroView): boolean {
|
|
42
|
-
if ((view.model
|
|
46
|
+
if (ExecutableNotebookModel.is(view.model)) {
|
|
43
47
|
return true;
|
|
44
48
|
}
|
|
45
49
|
return false;
|
|
46
50
|
}
|
|
47
51
|
|
|
48
|
-
workspaceFolders: WorkspaceFolder[] | undefined
|
|
52
|
+
get workspaceFolders(): WorkspaceFolder[] | undefined {
|
|
53
|
+
return [
|
|
54
|
+
{
|
|
55
|
+
index: 0,
|
|
56
|
+
uri: URI.parse(this.libroWorkspaceService.workspaceRoot.toString()),
|
|
57
|
+
name: '',
|
|
58
|
+
},
|
|
59
|
+
];
|
|
60
|
+
}
|
|
49
61
|
getWorkspaceFolder(uri: Uri): WorkspaceFolder | undefined {
|
|
50
62
|
return;
|
|
51
63
|
}
|
|
@@ -95,12 +95,62 @@ export class MonacoLanguages implements IMonacoLanguages {
|
|
|
95
95
|
provider: CodeActionProvider,
|
|
96
96
|
metadata?: CodeActionProviderMetadata,
|
|
97
97
|
): Disposable {
|
|
98
|
+
const codeActionProvider = this.createCodeActionProvider(provider);
|
|
99
|
+
return monaco.languages.registerCodeActionProvider(selector, codeActionProvider);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
protected createCodeActionProvider(
|
|
103
|
+
provider: CodeActionProvider,
|
|
104
|
+
): monaco.languages.CodeActionProvider {
|
|
98
105
|
return {
|
|
99
|
-
|
|
100
|
-
|
|
106
|
+
provideCodeActions: async (model, range, context, token) => {
|
|
107
|
+
/**
|
|
108
|
+
* This few lines of code are greatly inspired from https://github.com/microsoft/vscode/blob/e9393b096d90a5ac49b1528d1ec60483fc6b993e/src/vs/workbench/api/common/extHostLanguageFeatures.ts#L400
|
|
109
|
+
*/
|
|
110
|
+
// const allDiagnostics: Diagnostic[] = [];
|
|
111
|
+
// for (const diagnostic of this.extHostDiagnostics.getDiagnostics(
|
|
112
|
+
// model.uri.toString(),
|
|
113
|
+
// )) {
|
|
114
|
+
// if (range.intersectRanges(this.p2m.asRange(diagnostic.range))) {
|
|
115
|
+
// const newLen = allDiagnostics.push(diagnostic);
|
|
116
|
+
// if (newLen > MonacoLanguages._maxCodeActionsPerFile) {
|
|
117
|
+
// break;
|
|
118
|
+
// }
|
|
119
|
+
// }
|
|
120
|
+
// }
|
|
121
|
+
|
|
122
|
+
const params = this.m2p.asCodeActionParams(model, range, context, []);
|
|
123
|
+
const result = await provider.provideCodeActions(
|
|
124
|
+
this.p2c.asTextDcouemnt(params.textDocument),
|
|
125
|
+
this.p2c.asRange(params.range),
|
|
126
|
+
await this.p2c.asCodeActionContext(
|
|
127
|
+
this.m2p.asCodeActionContext(context, []),
|
|
128
|
+
[],
|
|
129
|
+
),
|
|
130
|
+
token,
|
|
131
|
+
);
|
|
132
|
+
return (
|
|
133
|
+
result && this.p2m.asCodeActionList(await this.c2p.asCodeActionList(result))
|
|
134
|
+
);
|
|
101
135
|
},
|
|
136
|
+
resolveCodeAction: provider.resolveCodeAction
|
|
137
|
+
? async (codeAction, token) => {
|
|
138
|
+
const params = await this.p2c.asCodeAction(
|
|
139
|
+
this.m2p.asCodeAction(codeAction),
|
|
140
|
+
);
|
|
141
|
+
const result = await provider.resolveCodeAction?.(params, token);
|
|
142
|
+
if (result) {
|
|
143
|
+
const resolvedCodeAction = this.p2m.asCodeAction(
|
|
144
|
+
await this.c2p.asCodeAction(result),
|
|
145
|
+
);
|
|
146
|
+
overrideWithResolvedValue(codeAction, resolvedCodeAction);
|
|
147
|
+
}
|
|
148
|
+
return codeAction;
|
|
149
|
+
}
|
|
150
|
+
: undefined,
|
|
102
151
|
};
|
|
103
152
|
}
|
|
153
|
+
|
|
104
154
|
registerCodeLensProvider(
|
|
105
155
|
selector: DocumentSelector,
|
|
106
156
|
provider: CodeLensProvider,
|
|
@@ -115,9 +165,25 @@ export class MonacoLanguages implements IMonacoLanguages {
|
|
|
115
165
|
selector: DocumentSelector,
|
|
116
166
|
provider: DefinitionProvider,
|
|
117
167
|
): Disposable {
|
|
168
|
+
return monaco.languages.registerDefinitionProvider(
|
|
169
|
+
selector,
|
|
170
|
+
this.createDefinitionProvider(provider),
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
protected createDefinitionProvider(
|
|
174
|
+
provider: DefinitionProvider,
|
|
175
|
+
): monaco.languages.DefinitionProvider {
|
|
118
176
|
return {
|
|
119
|
-
|
|
120
|
-
|
|
177
|
+
provideDefinition: async (model, position, token) => {
|
|
178
|
+
const params = this.m2p.asTextDocumentPositionParams(model, position);
|
|
179
|
+
const result = await provider.provideDefinition(
|
|
180
|
+
{ uri: model.uri } as any,
|
|
181
|
+
this.p2c.asPosition(params.position),
|
|
182
|
+
token,
|
|
183
|
+
);
|
|
184
|
+
return (
|
|
185
|
+
result && this.p2m.asDefinitionResult(this.c2p.asDefinitionResult(result))
|
|
186
|
+
);
|
|
121
187
|
},
|
|
122
188
|
};
|
|
123
189
|
}
|
|
@@ -332,12 +398,54 @@ export class MonacoLanguages implements IMonacoLanguages {
|
|
|
332
398
|
firstItem?: string | SignatureHelpProviderMetadata,
|
|
333
399
|
...remaining: string[]
|
|
334
400
|
): Disposable {
|
|
401
|
+
const signatureHelpProvider = this.createSignatureHelpProvider(
|
|
402
|
+
provider,
|
|
403
|
+
firstItem,
|
|
404
|
+
...remaining,
|
|
405
|
+
);
|
|
406
|
+
return monaco.languages.registerSignatureHelpProvider(
|
|
407
|
+
selector,
|
|
408
|
+
signatureHelpProvider,
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
protected createSignatureHelpProvider(
|
|
413
|
+
provider: SignatureHelpProvider,
|
|
414
|
+
firstItem?: string | SignatureHelpProviderMetadata,
|
|
415
|
+
...remaining: string[]
|
|
416
|
+
): monaco.languages.SignatureHelpProvider {
|
|
417
|
+
let triggerCharacters: string[] = [];
|
|
418
|
+
let retriggerCharacters: string[] = [];
|
|
419
|
+
if (typeof firstItem === 'string') {
|
|
420
|
+
triggerCharacters = [firstItem, ...remaining];
|
|
421
|
+
} else {
|
|
422
|
+
retriggerCharacters = [...(firstItem?.retriggerCharacters ?? [])];
|
|
423
|
+
triggerCharacters = [...(firstItem?.triggerCharacters ?? [])];
|
|
424
|
+
}
|
|
425
|
+
// const signatureHelpTriggerCharacters = [
|
|
426
|
+
// ...(provider.triggerCharacters || triggerCharacters || []),
|
|
427
|
+
// ];
|
|
335
428
|
return {
|
|
336
|
-
|
|
337
|
-
|
|
429
|
+
signatureHelpTriggerCharacters: triggerCharacters,
|
|
430
|
+
signatureHelpRetriggerCharacters: retriggerCharacters,
|
|
431
|
+
provideSignatureHelp: async (model, position, token, context) => {
|
|
432
|
+
const params = this.m2p.asTextDocumentPositionParams(model, position);
|
|
433
|
+
const signatureHelp = await provider.provideSignatureHelp(
|
|
434
|
+
this.p2c.asTextDcouemnt(params.textDocument),
|
|
435
|
+
this.p2c.asPosition(params.position),
|
|
436
|
+
token,
|
|
437
|
+
await this.p2c.asSignatureHelpContext(
|
|
438
|
+
this.m2p.asSignatureHelpContext(context),
|
|
439
|
+
),
|
|
440
|
+
);
|
|
441
|
+
return (
|
|
442
|
+
signatureHelp &&
|
|
443
|
+
this.p2m.asSignatureHelpResult(this.c2p.asSignatureHelpResult(signatureHelp))
|
|
444
|
+
);
|
|
338
445
|
},
|
|
339
446
|
};
|
|
340
447
|
}
|
|
448
|
+
|
|
341
449
|
registerCompletionItemProvider(
|
|
342
450
|
selector: DocumentSelector,
|
|
343
451
|
provider: CompletionItemProvider,
|
package/src/index.ts
CHANGED
|
@@ -1,24 +1,41 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EditorCellView,
|
|
3
|
+
ILibroWorkspaceService,
|
|
4
|
+
LibroService,
|
|
5
|
+
} from '@difizen/libro-core';
|
|
6
|
+
import { ExecutableNotebookModel } from '@difizen/libro-kernel';
|
|
1
7
|
import { ApplicationContribution, inject, singleton } from '@difizen/mana-app';
|
|
8
|
+
import * as monaco from '@difizen/monaco-editor-core';
|
|
9
|
+
import { URI } from 'vscode-uri';
|
|
2
10
|
|
|
3
11
|
import { CloseAction, ErrorAction } from './common/api.js';
|
|
4
12
|
import { LSPEnv } from './common/vscodeAdaptor/lspEnv.js';
|
|
5
13
|
import { workspace } from './common/vscodeAdaptor/vscodeAdaptor.js';
|
|
6
14
|
import { LibroLanguageClientManager } from './libro-language-client-manager.js';
|
|
15
|
+
import { getCellURI, toEditorRange, toMonacoPosition } from './util.js';
|
|
7
16
|
|
|
8
17
|
@singleton({ contrib: [ApplicationContribution] })
|
|
9
18
|
export class LibroLanguageClientContribution implements ApplicationContribution {
|
|
19
|
+
@inject(ILibroWorkspaceService)
|
|
20
|
+
protected readonly libroWorkspaceService: ILibroWorkspaceService;
|
|
10
21
|
@inject(LibroLanguageClientManager)
|
|
11
22
|
protected readonly libroLanguageClientManager: LibroLanguageClientManager;
|
|
12
23
|
|
|
13
24
|
@inject(LSPEnv)
|
|
14
25
|
protected readonly lspEnv: LSPEnv;
|
|
15
26
|
|
|
27
|
+
@inject(LibroService)
|
|
28
|
+
protected readonly libroService: LibroService;
|
|
29
|
+
|
|
16
30
|
async onViewStart() {
|
|
17
31
|
// not block
|
|
18
32
|
this.startLanguageClients();
|
|
33
|
+
this.setupEditorOpener();
|
|
19
34
|
}
|
|
20
35
|
|
|
21
36
|
async startLanguageClients() {
|
|
37
|
+
// wait for workspaceFolder
|
|
38
|
+
await this.libroWorkspaceService.ready;
|
|
22
39
|
await this.lspEnv.ready;
|
|
23
40
|
const serverIds = await this.libroLanguageClientManager.getServers();
|
|
24
41
|
|
|
@@ -33,17 +50,82 @@ export class LibroLanguageClientContribution implements ApplicationContribution
|
|
|
33
50
|
error: () => ({ action: ErrorAction.Continue }),
|
|
34
51
|
closed: () => ({ action: CloseAction.DoNotRestart }),
|
|
35
52
|
},
|
|
36
|
-
// pyright requires a workspace folder to be present, otherwise it will not work
|
|
37
|
-
// workspaceFolder: {
|
|
38
|
-
// index: 0,
|
|
39
|
-
// name: 'workspace',
|
|
40
|
-
// uri: URI.parse('/examples'), // abs path
|
|
41
|
-
// },
|
|
42
53
|
synchronize: {
|
|
43
54
|
fileEvents: [workspace.createFileSystemWatcher('**', false)],
|
|
44
55
|
},
|
|
45
56
|
},
|
|
46
57
|
});
|
|
47
58
|
}
|
|
59
|
+
|
|
60
|
+
this.libroLanguageClientManager
|
|
61
|
+
.getFeatureStatus('textDocument/formatting')
|
|
62
|
+
.then((status) => {
|
|
63
|
+
this.libroService.hasFormatter = status;
|
|
64
|
+
return;
|
|
65
|
+
})
|
|
66
|
+
.catch(() => {
|
|
67
|
+
return;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
setupEditorOpener() {
|
|
72
|
+
monaco.editor.registerEditorOpener({
|
|
73
|
+
openCodeEditor: (source, resource, selectionOrPosition) => {
|
|
74
|
+
// simulate openening a new browser tab for our own type (open definition of alert)
|
|
75
|
+
const model = monaco.editor.getModel(resource);
|
|
76
|
+
if (model?.id === source.getModel()?.id) {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
const libroView = Array.from(this.libroService.getViewCache().values()).find(
|
|
80
|
+
(item) => {
|
|
81
|
+
return (
|
|
82
|
+
ExecutableNotebookModel.is(item.model) &&
|
|
83
|
+
URI.parse(item.model.filePath).path === resource.path
|
|
84
|
+
);
|
|
85
|
+
},
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
if (!libroView) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const cell = libroView.model.cells.find((item) => {
|
|
93
|
+
return (
|
|
94
|
+
ExecutableNotebookModel.is(libroView.model) &&
|
|
95
|
+
getCellURI(libroView.model, item.model).toString() ===
|
|
96
|
+
decodeURIComponent(resource.toString())
|
|
97
|
+
);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
if (EditorCellView.is(cell)) {
|
|
101
|
+
libroView.selectCell(cell);
|
|
102
|
+
cell.editor?.focus();
|
|
103
|
+
let line = 0;
|
|
104
|
+
if (monaco.Range.isIRange(selectionOrPosition)) {
|
|
105
|
+
cell.editor?.revealSelection(toEditorRange(selectionOrPosition));
|
|
106
|
+
cell.editor?.setCursorPosition(toEditorRange(selectionOrPosition).start);
|
|
107
|
+
line = toEditorRange(selectionOrPosition).start.line;
|
|
108
|
+
} else {
|
|
109
|
+
cell.editor?.setCursorPosition(toMonacoPosition(selectionOrPosition));
|
|
110
|
+
line = toMonacoPosition(selectionOrPosition).line;
|
|
111
|
+
}
|
|
112
|
+
libroView.model.scrollToView(cell, (line ?? 0) * 20);
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// alternatively set model directly in the editor if you have your own tab/navigation implementation
|
|
117
|
+
// const model = monaco.editor.getModel(resource);
|
|
118
|
+
// editor.setModel(model);
|
|
119
|
+
// if (monaco.Range.isIRange(selectionOrPosition)) {
|
|
120
|
+
// editor.revealRangeInCenterIfOutsideViewport(selectionOrPosition);
|
|
121
|
+
// editor.setSelection(selectionOrPosition);
|
|
122
|
+
// } else {
|
|
123
|
+
// editor.revealPositionInCenterIfOutsideViewport(selectionOrPosition);
|
|
124
|
+
// editor.setPosition(selectionOrPosition);
|
|
125
|
+
// }
|
|
126
|
+
|
|
127
|
+
return false;
|
|
128
|
+
},
|
|
129
|
+
});
|
|
48
130
|
}
|
|
49
131
|
}
|
|
@@ -24,6 +24,11 @@ export class LibroLanguageClientManager {
|
|
|
24
24
|
|
|
25
25
|
protected clientMap = new Map<string, IConnectionData>();
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* lsp server that support notebook
|
|
29
|
+
*/
|
|
30
|
+
protected supportedLSPServer: string[] = ['libro-analyzer', 'ruff-lsp', 'pylance'];
|
|
31
|
+
|
|
27
32
|
@postConstruct()
|
|
28
33
|
init() {
|
|
29
34
|
this.languageServerManager = this.languageServerManagerFactory({});
|
|
@@ -39,7 +44,7 @@ export class LibroLanguageClientManager {
|
|
|
39
44
|
const serverIds = this.languageServerManager.getMatchingServers({
|
|
40
45
|
language,
|
|
41
46
|
});
|
|
42
|
-
return serverIds;
|
|
47
|
+
return serverIds.filter((item) => this.supportedLSPServer.includes(item));
|
|
43
48
|
}
|
|
44
49
|
|
|
45
50
|
async getServerSpecs(language = 'python') {
|
|
@@ -72,6 +77,9 @@ export class LibroLanguageClientManager {
|
|
|
72
77
|
languageServerId: string,
|
|
73
78
|
options: LibroLanguageClientOptions,
|
|
74
79
|
) {
|
|
80
|
+
if (!this.supportedLSPServer.includes(languageServerId)) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
75
83
|
if (this.clientMap.has(languageServerId)) {
|
|
76
84
|
return this.clientMap.get(languageServerId);
|
|
77
85
|
}
|
package/src/util.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { IPosition, IRange } from '@difizen/libro-code-editor';
|
|
2
|
+
import type { CellModel } from '@difizen/libro-core';
|
|
3
|
+
import type { ExecutableNotebookModel } from '@difizen/libro-kernel';
|
|
4
|
+
import { URI } from '@difizen/mana-app';
|
|
5
|
+
import type * as monaco from '@difizen/monaco-editor-core';
|
|
6
|
+
|
|
7
|
+
import { LibroCellURIScheme } from './constants.js';
|
|
8
|
+
|
|
9
|
+
export const getCellURI = (
|
|
10
|
+
libroModel: ExecutableNotebookModel,
|
|
11
|
+
cellModel: CellModel,
|
|
12
|
+
): URI => {
|
|
13
|
+
let uri = new URI(libroModel.filePath);
|
|
14
|
+
uri = URI.withScheme(uri, LibroCellURIScheme);
|
|
15
|
+
uri = URI.withQuery(uri, `cellid=${cellModel.id}`);
|
|
16
|
+
return uri;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const toEditorRange = (range: monaco.IRange): IRange => {
|
|
20
|
+
return {
|
|
21
|
+
start: {
|
|
22
|
+
line: range.startLineNumber - 1,
|
|
23
|
+
column: range.startColumn - 1,
|
|
24
|
+
},
|
|
25
|
+
end: {
|
|
26
|
+
line: range.endLineNumber - 1,
|
|
27
|
+
column: range.endColumn - 1,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const toMonacoPosition = (position: monaco.IPosition | undefined): IPosition => {
|
|
33
|
+
if (!position) {
|
|
34
|
+
return {
|
|
35
|
+
column: 0,
|
|
36
|
+
line: 0,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
column: position?.column - 1,
|
|
41
|
+
line: position?.lineNumber - 1,
|
|
42
|
+
};
|
|
43
|
+
};
|