VS Code: decoration-based matching, Ctrl+K bindings, README overhaul (from dev f8451715e657)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-27 17:02:41 +02:00
parent 2eb16791d2
commit 6abb0fd3dd
10 changed files with 255 additions and 39 deletions

View File

@@ -167,6 +167,11 @@ function activate(context) {
}
const python = vscode.workspace.getConfiguration('klammertext').get('pythonPath') || 'python3';
client = new LspClient(python, [serverPath], log);
client.proc.on('error', (err) => {
vscode.window.showWarningMessage(
'Klammertext: could not start the language server (' + err.message +
') — check the klammertext.pythonPath setting.');
});
const diagnostics = vscode.languages.createDiagnosticCollection('klammertext');
context.subscriptions.push(diagnostics, output);
@@ -271,6 +276,58 @@ function activate(context) {
},
}));
// -- live match/mismatch decorations --
// Drawn on every cursor move from the server's klammertext/matchInfo.
// Deliberately NOT left to occurrence highlighting: VS Code only asks
// documentHighlight providers when the cursor is on a word, so a bare @
// close would never light up — and a mismatch could not show in red.
const matchDecoration = vscode.window.createTextEditorDecorationType({
border: '1px solid',
borderColor: new vscode.ThemeColor('editorBracketMatch.border'),
backgroundColor: new vscode.ThemeColor('editorBracketMatch.background'),
});
const mismatchDecoration = vscode.window.createTextEditorDecorationType({
border: '1px solid #ff5555',
fontWeight: 'bold',
});
context.subscriptions.push(matchDecoration, mismatchDecoration);
const updateMatchDecorations = (editor) => {
if (!editor || !isKt(editor.document)) return;
client.request('klammertext/matchInfo',
Object.assign(docParams(editor.document),
{ position: fromVsPosition(editor.selection.active) }))
.then((info) => {
if (!info) {
editor.setDecorations(matchDecoration, []);
editor.setDecorations(mismatchDecoration, []);
return;
}
const ranges = [toVsRange(info.token)];
if (info.matchToken) ranges.push(toVsRange(info.matchToken));
if (info.mismatch) {
editor.setDecorations(matchDecoration, []);
editor.setDecorations(mismatchDecoration, ranges);
if (info.message) {
vscode.window.setStatusBarMessage(
'Klammertext: ' + info.message, 5000);
}
} else {
editor.setDecorations(mismatchDecoration, []);
editor.setDecorations(matchDecoration, ranges);
}
}, () => { /* server gone: leave decorations as they are */ });
};
let matchTimer = null;
context.subscriptions.push(
vscode.window.onDidChangeTextEditorSelection((event) => {
if (matchTimer) clearTimeout(matchTimer);
matchTimer = setTimeout(
() => updateMatchDecorations(event.textEditor), 50);
}),
vscode.window.onDidChangeActiveTextEditor(
(editor) => updateMatchDecorations(editor)));
// -- commands --
context.subscriptions.push(
vscode.commands.registerCommand('klammertext.jumpToMatch', () => {