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:
@@ -211,6 +211,33 @@ def main():
|
||||
'position': {'line': 0, 'character': 4}})
|
||||
check('documentHighlight off-delimiter is null', off is None, repr(off))
|
||||
|
||||
# -- the custom matchInfo request (drives the VS Code decorations) --
|
||||
hl2 = client.request('textDocument/documentHighlight',
|
||||
{'textDocument': {'uri': uri},
|
||||
'position': {'line': 0, 'character': 7}})
|
||||
check('documentHighlight from the bare close',
|
||||
hl2 is not None and len(hl2) == 2, repr(hl2))
|
||||
mi = client.request('klammertext/matchInfo',
|
||||
{'textDocument': {'uri': uri},
|
||||
'position': {'line': 0, 'character': 7}})
|
||||
check('matchInfo from the bare close',
|
||||
mi is not None and not mi['mismatch']
|
||||
and mi['matchToken']['start']['character'] == 0, repr(mi))
|
||||
client.notify('textDocument/didChange',
|
||||
{'textDocument': {'uri': uri, 'version': 6},
|
||||
'contentChanges': [{'text': '@ol x ul@\n'}]})
|
||||
client.wait_notification('textDocument/publishDiagnostics')
|
||||
mi = client.request('klammertext/matchInfo',
|
||||
{'textDocument': {'uri': uri},
|
||||
'position': {'line': 0, 'character': 0}})
|
||||
check('matchInfo reports a mismatch',
|
||||
mi is not None and mi['mismatch'] and 'ul@' in (mi['message'] or ''),
|
||||
repr(mi))
|
||||
mi = client.request('klammertext/matchInfo',
|
||||
{'textDocument': {'uri': uri},
|
||||
'position': {'line': 0, 'character': 4}})
|
||||
check('matchInfo off-delimiter is null', mi is None, repr(mi))
|
||||
|
||||
# -- alignTable via executeCommand -> applyEdit, on every align fixture --
|
||||
align_fixtures = ['align_mixed', 'align_empty_cells', 'align_boundary',
|
||||
'align_colspan', 'align_escapes']
|
||||
|
||||
@@ -59,7 +59,8 @@ class WorkspaceEdit {
|
||||
replace(uri, range, newText) { this.edits.push({ uri, range, newText }); }
|
||||
}
|
||||
|
||||
const listeners = { open: [], change: [], close: [] };
|
||||
const listeners = { open: [], change: [], close: [], selection: [] };
|
||||
const decorationTypes = []; // in creation order: match, mismatch
|
||||
const providers = {};
|
||||
const commands = {};
|
||||
const collections = {};
|
||||
@@ -87,10 +88,20 @@ const vscodeStub = {
|
||||
onDidCloseTextDocument: (fn) => { listeners.close.push(fn); return { dispose() {} }; },
|
||||
applyEdit: (we) => { appliedEdits.push(we); return Promise.resolve(true); },
|
||||
},
|
||||
ThemeColor: class ThemeColor {
|
||||
constructor(id) { this.id = id; }
|
||||
},
|
||||
window: {
|
||||
createOutputChannel: () => ({ append() {}, dispose() {} }),
|
||||
showWarningMessage: (m) => { statusMessages.push(m); },
|
||||
setStatusBarMessage: (m) => { statusMessages.push(m); },
|
||||
createTextEditorDecorationType: (opts) => {
|
||||
const t = { opts, dispose() {} };
|
||||
decorationTypes.push(t);
|
||||
return t;
|
||||
},
|
||||
onDidChangeTextEditorSelection: (fn) => { listeners.selection.push(fn); return { dispose() {} }; },
|
||||
onDidChangeActiveTextEditor: () => ({ dispose() {} }),
|
||||
activeTextEditor: null,
|
||||
},
|
||||
languages: {
|
||||
@@ -199,6 +210,27 @@ async function main() {
|
||||
check('jumpToMatch cursor at close', sel.active.character === 7,
|
||||
JSON.stringify(sel));
|
||||
|
||||
// live decorations: a bare close highlights its pair from any position.
|
||||
const [matchType, mismatchType] = decorationTypes;
|
||||
const editor = vscodeStub.window.activeTextEditor;
|
||||
editor.decorations = new Map();
|
||||
editor.setDecorations = (type, ranges) => editor.decorations.set(type, ranges);
|
||||
editor.selection = new Selection(new Position(0, 7), new Position(0, 7));
|
||||
listeners.selection.forEach((fn) => fn({ textEditor: editor }));
|
||||
await waitFor(() => (editor.decorations.get(matchType) || []).length === 2,
|
||||
'match decorations');
|
||||
check('decorations: bare close boxes the pair', true);
|
||||
|
||||
// mismatch: red decoration type, match type cleared
|
||||
setDocText('@ol x ul@\n');
|
||||
editor.selection = new Selection(new Position(0, 0), new Position(0, 0));
|
||||
listeners.selection.forEach((fn) => fn({ textEditor: editor }));
|
||||
await waitFor(() => (editor.decorations.get(mismatchType) || []).length === 2,
|
||||
'mismatch decorations');
|
||||
check('decorations: mismatch in the red type',
|
||||
(editor.decorations.get(matchType) || []).length === 0,
|
||||
JSON.stringify([...editor.decorations.values()]));
|
||||
|
||||
// alignTable round-trips through workspace/applyEdit.
|
||||
const src = fs.readFileSync(path.join(fixDir, 'align_mixed.kt'), 'utf8');
|
||||
const exp = fs.readFileSync(path.join(fixDir, 'align_mixed_expected.kt'), 'utf8');
|
||||
|
||||
Reference in New Issue
Block a user