98 lines
3.0 KiB
TypeScript
98 lines
3.0 KiB
TypeScript
import * as vscode from "vscode";
|
|
import { ABBREV } from "./abbrev";
|
|
import {
|
|
LanguageClient,
|
|
LanguageClientOptions,
|
|
ServerOptions,
|
|
TransportKind
|
|
} from 'vscode-languageclient/node';
|
|
|
|
function getIndent(text: string) {
|
|
return text.match(/\S/)?.index ?? 0
|
|
}
|
|
|
|
// They put this at module level for deactivate below.
|
|
let client: LanguageClient
|
|
|
|
export function activate(context: vscode.ExtensionContext) {
|
|
const serverModule = context.asAbsolutePath('./dist/lsp.js')
|
|
console.log('*** servervModule', serverModule)
|
|
const config = vscode.workspace.getConfiguration("newt");
|
|
const cmd = config.get<string | null>("lspPath");
|
|
|
|
let serverOptions: ServerOptions
|
|
if (cmd) {
|
|
serverOptions = {
|
|
run: { command: "node", args: [cmd], transport: TransportKind.pipe },
|
|
debug: { command: "node", args: [cmd], transport: TransportKind.pipe },
|
|
}
|
|
} else {
|
|
serverOptions = {
|
|
run: { module: serverModule, transport: TransportKind.ipc },
|
|
debug: { module: serverModule, transport: TransportKind.ipc },
|
|
}
|
|
}
|
|
|
|
const clientOptions: LanguageClientOptions = {
|
|
documentSelector: [{ scheme: 'file', language: 'newt' }],
|
|
synchronize: {
|
|
fileEvents: vscode.workspace.createFileSystemWatcher('*.newt')
|
|
}
|
|
}
|
|
|
|
client = new LanguageClient(
|
|
'NewtLanguageServer',
|
|
'Newt Language Server',
|
|
serverOptions,
|
|
clientOptions
|
|
)
|
|
|
|
client.start();
|
|
console.log('CLIENT started')
|
|
|
|
vscode.workspace.onDidChangeTextDocument((event) => {
|
|
const editor = vscode.window.activeTextEditor;
|
|
if (!editor || event.document !== editor.document) return;
|
|
|
|
const changes = event.contentChanges;
|
|
if (changes.length === 0) return;
|
|
|
|
// TODO - agda input mode does the replacement as soon as possible
|
|
// but if the sequence is a prefix, it will change for subsequent characters
|
|
// The latter would require keeping state, but if we don't allow sequences to prefix
|
|
// each other, we could activate quicker.
|
|
const lastChange = changes[changes.length - 1];
|
|
const text = lastChange.text;
|
|
// Check if the last change is a potential shortcut trigger
|
|
if (!text || !(" ')\\_".includes(text) || text.startsWith('\n'))) return;
|
|
|
|
const document = editor.document;
|
|
const position = lastChange.range.end;
|
|
const lineText = document.lineAt(position.line).text;
|
|
const start = Math.max(0, position.character - 10);
|
|
const snippet = lineText.slice(start, position.character);
|
|
const m = snippet.match(/(\\[^ ]+)$/);
|
|
if (m) {
|
|
const cand = m[0];
|
|
console.log("cand", cand);
|
|
const replacement = ABBREV[cand];
|
|
console.log("repl", replacement);
|
|
if (replacement) {
|
|
const range = new vscode.Range(
|
|
position.line,
|
|
position.character - cand.length,
|
|
position.line,
|
|
position.character
|
|
);
|
|
editor.edit((editBuilder) => {
|
|
editBuilder.replace(range, replacement);
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
export function deactivate() {
|
|
if (client) client.stop();
|
|
}
|