Skip to content

Commit a53403d

Browse files
committed
Add opm-flow.additionalFileExtensions setting
Lets users open project-specific include-file extensions as opm-flow without modifying the built-in extension list. Accepts entries with or without a leading '.', matched case-insensitively, and is resource-scoped so a workspace can pin its own list: "opm-flow.additionalFileExtensions": [".myinc", "wellconv"] Activation is moved to onStartupFinished so the extension can retag files on first open. Already-open files are retagged on activate; onDidOpenTextDocument handles new opens; onDidChangeConfiguration re-evaluates on setting changes. The VS Code-native `files.associations` setting still works for one-off cases.
1 parent 7f51ea6 commit a53403d

2 files changed

Lines changed: 78 additions & 1 deletion

File tree

vscode-extension/package.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
],
3232
"activationEvents": [
3333
"onLanguage:opm-flow",
34-
"onView:opm-flow.docsView"
34+
"onView:opm-flow.docsView",
35+
"onStartupFinished"
3536
],
3637
"main": "./out/extension",
3738
"contributes": {
@@ -195,6 +196,15 @@
195196
],
196197
"description": "Keywords to skip when computing diagnostics (no squiggles for unknown-keyword, wrong-section, arity, or missing-'/' checks). Names are matched case-insensitively after upper-casing — OPM Flow keywords are conventionally uppercase. Use this for keywords whose record bodies don't fit the generic record model and produce noisy false positives.",
197198
"scope": "resource"
199+
},
200+
"opm-flow.additionalFileExtensions": {
201+
"type": "array",
202+
"items": {
203+
"type": "string"
204+
},
205+
"default": [],
206+
"description": "Extra file extensions (with or without a leading '.') that should open as OPM Flow. Useful for project-specific include-file conventions not covered by the built-in extension list. Matched case-insensitively. Example: [\".myinc\", \"props2\"]. For one-off cases the VS Code-native `files.associations` setting still works too.",
207+
"scope": "resource"
198208
}
199209
}
200210
}

vscode-extension/src/extension.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,10 +776,77 @@ function debounce<T extends unknown[]>(fn: (...args: T) => void, ms: number): (.
776776
};
777777
}
778778

779+
// ---------------------------------------------------------------------------
780+
// Additional file extensions — `opm-flow.additionalFileExtensions`
781+
// ---------------------------------------------------------------------------
782+
783+
/** Read and normalise the user's extra-extensions setting. Accepts entries
784+
* with or without a leading '.'; matches case-insensitively. */
785+
function getAdditionalFileExtensions(resource?: vscode.Uri): Set<string> {
786+
const raw = vscode.workspace
787+
.getConfiguration('opm-flow', resource ?? null)
788+
.get<string[]>('additionalFileExtensions', []);
789+
const out = new Set<string>();
790+
for (const entry of raw) {
791+
if (typeof entry !== 'string') continue;
792+
let s = entry.trim();
793+
if (!s) continue;
794+
if (s.startsWith('.')) s = s.slice(1);
795+
if (s) out.add(s.toLowerCase());
796+
}
797+
return out;
798+
}
799+
800+
/** If the document's extension matches one of the user-configured extras
801+
* and the document isn't already opm-flow, retag it. Failures (closed
802+
* document, virtual scheme, etc.) are silently ignored. */
803+
async function retagDocumentIfMatches(
804+
doc: vscode.TextDocument,
805+
extensions: Set<string>,
806+
): Promise<void> {
807+
if (extensions.size === 0) return;
808+
if (doc.languageId === 'opm-flow') return;
809+
const fileName = doc.fileName ?? doc.uri.path ?? '';
810+
const dotIdx = fileName.lastIndexOf('.');
811+
if (dotIdx < 0) return;
812+
const ext = fileName.slice(dotIdx + 1).toLowerCase();
813+
if (!ext || !extensions.has(ext)) return;
814+
try {
815+
await vscode.languages.setTextDocumentLanguage(doc, 'opm-flow');
816+
} catch {
817+
// The doc may have been closed, or its scheme may not support
818+
// language reassignment — both are fine to skip.
819+
}
820+
}
821+
779822
export function activate(context: vscode.ExtensionContext): void {
780823
const index = loadKeywordIndex(context);
781824
const keywords = Object.keys(index);
782825

826+
// --- Additional file extensions ---
827+
// Retag any open file whose extension is listed in
828+
// `opm-flow.additionalFileExtensions` and watch for new opens + config
829+
// changes. The extension activates `onStartupFinished` so this works on
830+
// first open of an unknown-extension file too.
831+
const retagAllOpenDocuments = (): void => {
832+
const exts = getAdditionalFileExtensions();
833+
if (exts.size === 0) return;
834+
for (const doc of vscode.workspace.textDocuments) {
835+
void retagDocumentIfMatches(doc, exts);
836+
}
837+
};
838+
retagAllOpenDocuments();
839+
context.subscriptions.push(
840+
vscode.workspace.onDidOpenTextDocument(doc => {
841+
void retagDocumentIfMatches(doc, getAdditionalFileExtensions(doc.uri));
842+
}),
843+
vscode.workspace.onDidChangeConfiguration(e => {
844+
if (e.affectsConfiguration('opm-flow.additionalFileExtensions')) {
845+
retagAllOpenDocuments();
846+
}
847+
}),
848+
);
849+
783850
// --- Sidebar docs panel ---
784851
const docsProvider = new DocsViewProvider(context.extensionUri, index);
785852
context.subscriptions.push(

0 commit comments

Comments
 (0)