cefff5b891
Implements a Language Server Protocol server for El files over stdin/stdout JSON-RPC. Provides completions (builtins + keywords + document functions), hover documentation, go-to-definition, and full document sync. Also adds a VSCode extension that launches the binary as a child process and a TextMate grammar for .el syntax highlighting. NOTE: el-lsp.el calls __read_n(n: Int) -> String, a seed primitive not yet in el_runtime.c. Build.sh documents the required C implementation; the seed agent must add it before the binary will link.
98 lines
3.0 KiB
JavaScript
98 lines
3.0 KiB
JavaScript
// tools/lsp/vscode-extension/extension.js — El Language VSCode extension
|
|
//
|
|
// Launches el-lsp as a child process (stdin/stdout Language Server Protocol)
|
|
// and connects VSCode's language client to it.
|
|
//
|
|
// Prerequisites:
|
|
// - el-lsp binary built at ../dist/el-lsp (run tools/lsp/build.sh first)
|
|
// - npm install (installs vscode-languageclient)
|
|
//
|
|
// Install for development:
|
|
// 1. Open the vscode-extension/ folder in VSCode
|
|
// 2. Press F5 — Extension Development Host launches
|
|
// 3. Open any .el file — the LSP activates
|
|
//
|
|
// To package as a .vsix:
|
|
// npm install -g @vscode/vsce
|
|
// cd tools/lsp/vscode-extension && vsce package
|
|
|
|
'use strict';
|
|
|
|
const path = require('path');
|
|
const { workspace, window, ExtensionContext } = require('vscode');
|
|
const {
|
|
LanguageClient,
|
|
TransportKind,
|
|
} = require('vscode-languageclient/node');
|
|
|
|
let client;
|
|
|
|
/**
|
|
* activate — called when a .el file is first opened.
|
|
* Resolves the el-lsp binary path and starts the language client.
|
|
*
|
|
* @param {ExtensionContext} context
|
|
*/
|
|
function activate(context) {
|
|
// Resolve el-lsp binary path.
|
|
// Default: ../dist/el-lsp relative to this extension root.
|
|
// Override with the "el.lspPath" workspace setting.
|
|
const config = workspace.getConfiguration('el');
|
|
const defaultLspPath = path.join(context.extensionPath, '..', 'dist', 'el-lsp');
|
|
const serverPath = config.get('lspPath', defaultLspPath);
|
|
|
|
// ServerOptions: run el-lsp as a child process over stdin/stdout.
|
|
const serverOptions = {
|
|
run: {
|
|
command: serverPath,
|
|
transport: TransportKind.stdio,
|
|
},
|
|
debug: {
|
|
command: serverPath,
|
|
transport: TransportKind.stdio,
|
|
// In debug mode you could add --verbose or redirect stderr to a
|
|
// log file for inspection. For now debug == run.
|
|
},
|
|
};
|
|
|
|
// ClientOptions: handle all files with language id "el".
|
|
const clientOptions = {
|
|
documentSelector: [
|
|
{ scheme: 'file', language: 'el' },
|
|
{ scheme: 'untitled', language: 'el' },
|
|
],
|
|
synchronize: {
|
|
// Re-send full document on save (matches textDocumentSync: 1).
|
|
fileEvents: workspace.createFileSystemWatcher('**/*.el'),
|
|
},
|
|
// Output channel for LSP messages (visible in Output → El Language Server).
|
|
outputChannelName: 'El Language Server',
|
|
};
|
|
|
|
client = new LanguageClient(
|
|
'el-language-server',
|
|
'El Language Server',
|
|
serverOptions,
|
|
clientOptions
|
|
);
|
|
|
|
// Start the client (and the server as its child process).
|
|
client.start();
|
|
|
|
// Notify user on activation.
|
|
window.showInformationMessage('El Language Server started.');
|
|
}
|
|
|
|
/**
|
|
* deactivate — called when the extension is unloaded.
|
|
* Stops the language client (sends LSP shutdown + exit).
|
|
*/
|
|
function deactivate() {
|
|
if (!client) {
|
|
return undefined;
|
|
}
|
|
return client.stop();
|
|
}
|
|
|
|
module.exports = { activate, deactivate };
|