diff --git a/developer/src/kmc/src/util/NodeCompilerCallbacks.ts b/developer/src/kmc/src/util/NodeCompilerCallbacks.ts index fd5f29d2122..de80ba62f27 100644 --- a/developer/src/kmc/src/util/NodeCompilerCallbacks.ts +++ b/developer/src/kmc/src/util/NodeCompilerCallbacks.ts @@ -193,6 +193,11 @@ export class NodeCompilerCallbacks implements CompilerCallbacks { this.printMessage(event); } + /** Bottleneck for output */ + protected writeString(str: string) { + process.stdout.write(str); + } + private printMessage(event: CompilerEvent) { if(this.options.logFormat == 'tsv') { this.printTsvMessage(event); @@ -202,7 +207,7 @@ export class NodeCompilerCallbacks implements CompilerCallbacks { } private printTsvMessage(event: CompilerEvent) { - process.stdout.write([ + this.writeString([ CompilerError.formatFilename(event.filename, {fullPath:true, forwardSlashes:false}), CompilerError.formatLine(event.line), CompilerError.formatSeverity(event.code), @@ -214,7 +219,7 @@ export class NodeCompilerCallbacks implements CompilerCallbacks { private printFormattedMessage(event: CompilerEvent) { const severityColor = severityColors[CompilerError.severity(event.code)] ?? color.reset; const messageColor = this.messageSpecialColor(event) ?? color.reset; - process.stdout.write( + this.writeString( ( event.filename ? color.cyan(CompilerError.formatFilename(event.filename)) + @@ -228,7 +233,7 @@ export class NodeCompilerCallbacks implements CompilerCallbacks { if(event.code == InfrastructureMessages.INFO_ProjectBuiltSuccessfully) { // Special case: we'll add a blank line after project builds - process.stdout.write('\n'); + this.writeString('\n'); } } diff --git a/developer/src/vscode-plugin/app/App.tsx b/developer/src/vscode-plugin/app/App.tsx index f109b9973be..db87a86beb5 100644 --- a/developer/src/vscode-plugin/app/App.tsx +++ b/developer/src/vscode-plugin/app/App.tsx @@ -7,6 +7,20 @@ function count() : number { return (++a); } +let kmxplus = null; +let text = null; + +window.addEventListener('message', event => { + const message = event.data; + switch (message.command) { + case 'update': + kmxplus = message.kmxplus; + text = message.text; + break; + } +}); + + function App() { return (
diff --git a/developer/src/vscode-plugin/src/extensionCallbacks.mts b/developer/src/vscode-plugin/src/extensionCallbacks.mts new file mode 100644 index 00000000000..e0c0fa7c6b9 --- /dev/null +++ b/developer/src/vscode-plugin/src/extensionCallbacks.mts @@ -0,0 +1,25 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + */ + +import * as process from 'node:process'; +import { CompilerCallbackOptions } from "@keymanapp/developer-utils"; +import { NodeCompilerCallbacks } from "@keymanapp/kmc/build/src/util/NodeCompilerCallbacks.js"; + +export class ExtensionCallbacks extends NodeCompilerCallbacks { + /** + * @param options options to pass to NodeCompilerCallbacks + * @param msg callback to write to the console + */ + constructor(options: CompilerCallbackOptions, private msg?: (m: string)=>void) { + super(options); + } + + protected writeString(str: string) { + if (this.msg) { + this.msg(str); + } else { + process.stdout.write(str); + } + } +} diff --git a/developer/src/vscode-plugin/src/kmcLdmlCompilerManager.mts b/developer/src/vscode-plugin/src/kmcLdmlCompilerManager.mts index 0fc0c813199..7ffd930d926 100644 --- a/developer/src/vscode-plugin/src/kmcLdmlCompilerManager.mts +++ b/developer/src/vscode-plugin/src/kmcLdmlCompilerManager.mts @@ -2,19 +2,59 @@ * Keyman is copyright (C) SIL Global. MIT License. */ -// import { NodeCompilerCallbacks } from "@keymanapp/kmc"; import { LDMLCompilerManager } from "./ldmlCompilerManager.js"; - +import { CompilerCallbackOptions, CompilerCallbacks, defaultCompilerOptions } from "@keymanapp/developer-utils"; +import { LdmlCompilerOptions, LdmlKeyboardCompiler } from "@keymanapp/kmc-ldml"; +import { ExtensionCallbacks } from "./extensionCallbacks.mjs"; +import { KMXPlus } from "@keymanapp/common-types"; /** * TODO-LDML-EDITOR: should use vscode.workspace.fs.readFile which can read from remote workspaces. + * + * TODO-LDML-EDITOR: naming can be improved. */ export class KmcLdmlManager implements LDMLCompilerManager { + calloptions?: CompilerCallbackOptions; + callbacks?: CompilerCallbacks; + compoptions?: LdmlCompilerOptions; + async init(): Promise { + if (this.callbacks) { + return; // already initted + } console.log("Initting KmcLdmlManager…"); - // new NodeCompilerCallbacks({ - // }); + this.calloptions = { + logLevel: "debug" + }; + this.callbacks = new ExtensionCallbacks(this.calloptions); // TODO-EPIC-LDML: capture output console.log("KmcLdmlManager okay!"); + console.log('Initted'); + } + + async compile(filename: string): Promise { + if (!this.callbacks) { + throw Error(`Must call init() first.`); + } + const k = new LdmlKeyboardCompiler(); + this.compoptions = { + ...defaultCompilerOptions, + readerOptions: { + // TODO-EPIC-LDML: need to use global path + importsPath: "/Users/srl295/src/cldr/keyboards/import/", + } + }; + await k.init(this.callbacks, this.compoptions); + const source = await k.load(filename); + console.log(`loaded ${filename}`); + if (!source) { + throw Error(`Could not load ${filename}`); + } + const compiled = await k.compile(source); + if (!compiled) { + throw Error(`Could not compile ${filename}`); + } + console.log(`compiled ${filename}`); + return compiled; } }; diff --git a/developer/src/vscode-plugin/src/ldmlCompilerManager.ts b/developer/src/vscode-plugin/src/ldmlCompilerManager.ts index 05a0dfb070a..2cc81a44159 100644 --- a/developer/src/vscode-plugin/src/ldmlCompilerManager.ts +++ b/developer/src/vscode-plugin/src/ldmlCompilerManager.ts @@ -7,8 +7,10 @@ * This is abstract because the ES module needs to be loaded asynchronously. */ export interface LDMLCompilerManager { - /** validate that everything loaded properly */ + /** validate that everything loaded properly. idempotent */ init() : Promise; + /** Compile a file. Returns KMXPlus file. */ + compile(filename: string) : Promise; }; /** load concrete instance from module */ diff --git a/developer/src/vscode-plugin/src/ldmleditor.ts b/developer/src/vscode-plugin/src/ldmleditor.ts index 11fc4b58db1..8d3d7bff686 100644 --- a/developer/src/vscode-plugin/src/ldmleditor.ts +++ b/developer/src/vscode-plugin/src/ldmleditor.ts @@ -6,7 +6,7 @@ import * as vscode from 'vscode'; import * as crypto from 'crypto'; -import { getLDMLCompilerManager } from './ldmlCompilerManager'; +import { getLDMLCompilerManager, LDMLCompilerManager } from './ldmlCompilerManager'; interface LdmlDocumentDelegate { getFileData(): Promise; @@ -41,8 +41,17 @@ class LdmlDocument implements vscode.CustomDocument { } export class LdmlEditorProvider implements vscode.CustomTextEditorProvider { + private compiler? : LDMLCompilerManager; private static readonly viewType = 'keyman.ldml'; // sync w/ package.json + private async getCompiler() : Promise { + if (!this.compiler) { + this.compiler = await getLDMLCompilerManager(); + } + await this.compiler.init(); + return this.compiler; + } + constructor(private readonly context: vscode.ExtensionContext) { } static register(context: vscode.ExtensionContext): vscode.Disposable { const provider = new LdmlEditorProvider(context); @@ -96,8 +105,10 @@ export class LdmlEditorProvider implements vscode.CustomTextEditorProvider { } async resolveCustomTextEditor(document: vscode.TextDocument, webviewPanel: vscode.WebviewPanel, token: vscode.CancellationToken): Promise { + // make sure we have a compiler + const compiler = await this.getCompiler(); // temporary - testing linkage - await (await getLDMLCompilerManager()).init(); + const kmxPlus = await compiler.compile(document.fileName); webviewPanel.webview.options = { enableScripts: true, @@ -142,6 +153,7 @@ export class LdmlEditorProvider implements vscode.CustomTextEditorProvider { webviewPanel.webview.postMessage({ type: 'update', text: document.getText(), + kmxPlus, }); }