From 1cdd59478f23c814750ce5d8074151edce84c696 Mon Sep 17 00:00:00 2001 From: David de Hilster Date: Thu, 15 Oct 2026 08:31:39 -0400 Subject: [PATCH] Rule Fired on a dictionary node opens its .dict entry (-DICTSOURCE, #475) On DEV runs with engine 4.2.33 or later the extension passes -DICTSOURCE, so nodes built from .dict entries carry dictfile and dictline. Rule Fired on such a node opens that file at that line; without them it falls back to searching the dictionaries as before. New setting analyzer.dictSource (on by default) turns the switch off. Co-Authored-By: Claude Opus 5.5 --- package.json | 6 ++++++ src/nlp.ts | 12 ++++++++++++ src/treeFile.ts | 24 +++++++++++++++++++++++- 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index ca6dc735..8b329bb2 100644 --- a/package.json +++ b/package.json @@ -3509,6 +3509,12 @@ "default": "interpreted", "markdownDescription": "How the analyzer runs. Set from the run-mode button in the status bar and remembered per workspace folder." }, + "analyzer.dictSource": { + "type": "boolean", + "scope": "resource", + "default": true, + "description": "On DEV runs, have the engine (4.2.33 or later) record which dictionary file and line built each node, so Rule Fired on a parse tree node opens that dictionary entry." + }, "analyzer.regressionTerminal": { "type": "boolean", "scope": "resource", diff --git a/src/nlp.ts b/src/nlp.ts index e27c3c1c..92a43235 100644 --- a/src/nlp.ts +++ b/src/nlp.ts @@ -17,6 +17,9 @@ import * as telemetry from './telemetry/telemetry'; import { analyzerOutputLines, lastTreePass } from './output/analyzerOutput'; import { generatorChanged, kbOutputsOf } from './session/kbGen'; +// First engine with -DICTSOURCE (nlp-engine#432). +const DICT_SOURCE_ENGINE = '4.2.33'; + let analyzerOutputChannel: vscode.OutputChannel | undefined; /** Show what the analyzer printed with cout() in the "NLP++ Analyzer Output" panel. */ @@ -160,6 +163,15 @@ export class NLPFile extends TextFile { args.push('-COMPILED'); } args.push('"' + filestr + '"', devFlagStr); + // Nodes built from .dict entries then name the entry's file and line, + // so Rule Fired on the tree opens it (#475). Engines before 4.2.33 + // reject the switch and exit, so it goes only to newer ones. + if (mode == DevMode.DEV + && vscode.workspace.getConfiguration('analyzer').get('dictSource', true) + && visualText.engineVersion + && visualText.versionCompare(visualText.engineVersion, DICT_SOURCE_ENGINE) >= 0) { + args.push('-DICTSOURCE'); + } visualText.nlp.setAnalyzerStatus(filepath, analyzerStatus.ANALYZING); diff --git a/src/treeFile.ts b/src/treeFile.ts index a72e1c9a..b1bc0943 100644 --- a/src/treeFile.ts +++ b/src/treeFile.ts @@ -86,12 +86,34 @@ export class TreeFile extends TextFile { // If 0,0, then search inside dictionary files } else if (tline.ruleLine == 0) { - this.searchInDictionaries(tline.node); + if (!this.openDictSource()) + this.searchInDictionaries(tline.node); } } } } + // A run with -DICTSOURCE (engine 4.2.33+) puts the entry that built a + // dictionary node on it: ("dictfile" "words.dict") ("dictline" 14). + // Open that line rather than searching every dictionary (#475). + openDictSource(): boolean { + const line = this.getLines()[this.selStartLine] ?? ''; + const file = /\("dictfile" "([^"]+)"\)/.exec(line); + if (!file) return false; + const dictPath = path.join(visualText.analyzer.getKBDirectory().fsPath, file[1]); + if (!fs.existsSync(dictPath)) return false; + const num = /\("dictline" (\d+)\)/.exec(line); + const lineNum = num ? parseInt(num[1], 10) : 0; + vscode.window.showTextDocument(vscode.Uri.file(dictPath), { viewColumn: vscode.ViewColumn.Beside }).then(edit => { + if (lineNum > 0 && lineNum <= edit.document.lineCount) { + const entry = edit.document.lineAt(lineNum - 1).range; + edit.selections = [new vscode.Selection(entry.start, entry.end)]; + edit.revealRange(entry, vscode.TextEditorRevealType.InCenter); + } + }); + return true; + } + searchInDictionaries(word: string) { const finalMatches: FindItem[] = []; let searchWord = word.toLowerCase();