Skip to content

Commit 64b6112

Browse files
committed
Add embedded docs layout to widen parameter descriptions
Closes #26. Keywords with many parameters (e.g. WECON) squeezed the Description column down to a few characters. Add an "embedded" layout — now the default — that folds the Type, unit, and Default values into a muted sub-line beneath each description, freeing the full width for the description text. - New opm-flow.docs.layout setting ("embedded" | "columns", default "embedded"). The existing Type/unit/Default show-hide flags still control which values appear in either layout. - Shared metaBits() builder with HTML and markdown renderers, applied to both the docs sidebar and the hover tooltip. The original column layout is preserved under "columns".
1 parent 434e349 commit 64b6112

2 files changed

Lines changed: 106 additions & 8 deletions

File tree

vscode-extension/package.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,17 @@
166166
"configuration": {
167167
"title": "OPM Flow",
168168
"properties": {
169+
"opm-flow.docs.layout": {
170+
"type": "string",
171+
"enum": ["embedded", "columns"],
172+
"enumDescriptions": [
173+
"Fold the Type, unit, and Default values into a compact sub-line beneath each parameter description. Gives the Description column much more width — easier to read for keywords with many parameters (e.g. WECON).",
174+
"Render Type, units, and Default as separate table columns (the original layout)."
175+
],
176+
"default": "embedded",
177+
"description": "How the keyword docs sidebar and hover tooltips lay out parameter metadata. The Type / unit / Default show-hide settings still control which values appear in either layout.",
178+
"scope": "resource"
179+
},
169180
"opm-flow.columns.showType": {
170181
"type": "boolean",
171182
"default": true,

vscode-extension/src/extension.ts

Lines changed: 95 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -232,20 +232,72 @@ interface DocColumns {
232232
metric: boolean;
233233
lab: boolean;
234234
default: boolean;
235+
/**
236+
* 'columns' — render Type / units / Default as separate table columns
237+
* (the original layout).
238+
* 'embedded' — fold that metadata into a muted sub-line under each
239+
* description, giving the Description far more width. The
240+
* same show/hide flags still control which bits appear.
241+
*/
242+
layout: 'columns' | 'embedded';
235243
}
236244

237245
function getDocColumns(): DocColumns {
238246
const u = vscode.workspace.getConfiguration('opm-flow.units');
239247
const c = vscode.workspace.getConfiguration('opm-flow.columns');
248+
const d = vscode.workspace.getConfiguration('opm-flow.docs');
240249
return {
241250
type: c.get<boolean>('showType', true),
242251
field: u.get<boolean>('showField', true),
243252
metric: u.get<boolean>('showMetric', true),
244253
lab: u.get<boolean>('showLab', true),
245254
default: c.get<boolean>('showDefault', true),
255+
layout: d.get<'columns' | 'embedded'>('layout', 'embedded'),
246256
};
247257
}
248258

259+
/**
260+
* Build the metadata bits (type, units, default) for a parameter, honouring
261+
* the column show/hide flags and skipping anything the parameter doesn't
262+
* carry. Shared shape for both the sidebar (HTML) and the hover (markdown);
263+
* callers supply the per-bit renderers.
264+
*/
265+
function metaBits(
266+
p: Parameter,
267+
typeLabel: string,
268+
cols: DocColumns,
269+
fmt: { type: (s: string) => string; pair: (label: string, value: string) => string },
270+
): string[] {
271+
const bits: string[] = [];
272+
if (cols.type && typeLabel) bits.push(fmt.type(typeLabel));
273+
const u = p.units ?? {};
274+
if (cols.field && u.field) bits.push(fmt.pair('Field', u.field));
275+
if (cols.metric && u.metric) bits.push(fmt.pair('Metric', u.metric));
276+
if (cols.lab && u.laboratory) bits.push(fmt.pair('Lab', u.laboratory));
277+
if (cols.default && p.default) bits.push(fmt.pair('default', p.default));
278+
return bits;
279+
}
280+
281+
/** Embedded metadata sub-line for the sidebar (HTML). Empty string when no
282+
* bits are visible. */
283+
function buildMetaHtml(p: Parameter, typeLabel: string, cols: DocColumns): string {
284+
const bits = metaBits(p, typeLabel, cols, {
285+
type: t => `<span class="meta-type">${escWithBreaks(t)}</span>`,
286+
pair: (label, value) => `<span class="meta-key">${label}:</span> ${escWithBreaks(value)}`,
287+
});
288+
return bits.length ? `<div class="meta">${bits.join(' <span class="meta-sep">&middot;</span> ')}</div>` : '';
289+
}
290+
291+
/** Embedded metadata sub-line for the hover (markdown). Empty string when no
292+
* bits are visible. */
293+
function buildMetaMarkdown(p: Parameter, typeLabel: string, cols: DocColumns): string {
294+
const bits = metaBits(p, typeLabel, cols, {
295+
type: t => t,
296+
pair: (label, value) => `${label}: ${value}`,
297+
});
298+
return bits.length ? `_${bits.join(' · ')}_` : '';
299+
}
300+
249301
function buildDocsHtml(
250302
entry: KeywordEntry | null,
251303
highlightParam: Parameter | null,
@@ -293,6 +345,14 @@ function buildDocsHtml(
293345
}
294346
.placeholder { color: var(--vscode-descriptionForeground); font-style: italic; margin-top: 20px; }
295347
.sections { color: var(--vscode-descriptionForeground); font-size: 0.9em; margin: 0 0 8px 0; }
348+
.meta {
349+
color: var(--vscode-descriptionForeground);
350+
font-size: 0.92em;
351+
margin-top: 3px;
352+
}
353+
.meta-type { font-style: italic; }
354+
.meta-key { opacity: 0.8; }
355+
.meta-sep { opacity: 0.5; padding: 0 2px; }
296356
`;
297357

298358
if (!entry) {
@@ -308,6 +368,7 @@ function buildDocsHtml(
308368

309369
let paramsHtml = '';
310370
if (allParams.length > 0) {
371+
const embedded = cols.layout === 'embedded';
311372
const showField = cols.field && allParams.some(p => p.units?.field);
312373
const showMetric = cols.metric && allParams.some(p => p.units?.metric);
313374
const showLab = cols.lab && allParams.some(p => p.units?.laboratory);
@@ -321,22 +382,33 @@ function buildDocsHtml(
321382
const defaultCol = showDefault ? '<th>Default</th>' : '';
322383

323384
const renderRow = (p: Parameter, idx: number): string => {
385+
const sameRecord = (highlightParam?.record ?? 1) === (p.record ?? 1);
386+
const hl = highlightParam && highlightParam.index === p.index && sameRecord
387+
? ' class="highlight"' : '';
388+
const dataRecord = p.record !== undefined
389+
? ` data-record="${escHtml(String(p.record))}"` : '';
390+
const head = `<tr data-param-index="${escHtml(String(p.index))}"${dataRecord}${hl}>`
391+
+ `<td>${escHtml(String(p.index))}</td>`
392+
+ `<td class="name"><code>${escHtml(p.name)}</code></td>`;
393+
394+
if (embedded) {
395+
const descCell = `<td>${escHtml(p.description)}${buildMetaHtml(p, paramTypes[idx], cols)}</td>`;
396+
return `${head}${descCell}</tr>`;
397+
}
398+
324399
const u = p.units ?? {};
325400
const unitCells =
326401
(showField ? `<td>${escWithBreaks(u.field ?? '')}</td>` : '') +
327402
(showMetric ? `<td>${escWithBreaks(u.metric ?? '')}</td>` : '') +
328403
(showLab ? `<td>${escWithBreaks(u.laboratory ?? '')}</td>` : '');
329404
const typeCell = showType ? `<td>${escWithBreaks(paramTypes[idx])}</td>` : '';
330405
const defaultCell = showDefault ? `<td>${escHtml(p.default)}</td>` : '';
331-
const sameRecord = (highlightParam?.record ?? 1) === (p.record ?? 1);
332-
const hl = highlightParam && highlightParam.index === p.index && sameRecord
333-
? ' class="highlight"' : '';
334-
const dataRecord = p.record !== undefined
335-
? ` data-record="${escHtml(String(p.record))}"` : '';
336-
return `<tr data-param-index="${escHtml(String(p.index))}"${dataRecord}${hl}><td>${escHtml(String(p.index))}</td><td class="name"><code>${escHtml(p.name)}</code></td><td>${escHtml(p.description)}</td>${typeCell}${unitCells}${defaultCell}</tr>`;
406+
return `${head}<td>${escHtml(p.description)}</td>${typeCell}${unitCells}${defaultCell}</tr>`;
337407
};
338408

339-
const tableHead = `<thead><tr><th>No.</th><th class="name">Name</th><th>Description</th>${typeCol}${unitCols}${defaultCol}</tr></thead>`;
409+
const tableHead = embedded
410+
? `<thead><tr><th>No.</th><th class="name">Name</th><th>Description</th></tr></thead>`
411+
: `<thead><tr><th>No.</th><th class="name">Name</th><th>Description</th>${typeCol}${unitCols}${defaultCol}</tr></thead>`;
340412

341413
if (entry.records_meta?.length) {
342414
// Multi-record: render one table per record so the user can see
@@ -541,6 +613,20 @@ function appendParameterTable(
541613
): void {
542614
if (!parameters || parameters.length === 0) return;
543615
const types = parameters.map(paramTypeLabel);
616+
617+
if (cols.layout === 'embedded') {
618+
// Fold Type / units / Default into a muted sub-line beneath each
619+
// description so the Description column isn't squeezed.
620+
md.appendMarkdown(`**Parameters**\n\n| No. | Name | Description |\n|-----|------|-------------|\n`);
621+
parameters.forEach((p, i) => {
622+
const meta = buildMetaMarkdown(p, types[i], cols);
623+
const desc = meta ? `${p.description}<br>${meta}` : p.description;
624+
md.appendMarkdown(`| ${p.index} | \`${p.name}\` | ${desc} |\n`);
625+
});
626+
md.appendMarkdown('\n');
627+
return;
628+
}
629+
544630
const showField = cols.field && parameters.some(p => p.units?.field);
545631
const showMetric = cols.metric && parameters.some(p => p.units?.metric);
546632
const showLab = cols.lab && parameters.some(p => p.units?.laboratory);
@@ -904,7 +990,8 @@ export function activate(context: vscode.ExtensionContext): void {
904990
vscode.workspace.onDidChangeConfiguration(e => {
905991
if (
906992
e.affectsConfiguration('opm-flow.units') ||
907-
e.affectsConfiguration('opm-flow.columns')
993+
e.affectsConfiguration('opm-flow.columns') ||
994+
e.affectsConfiguration('opm-flow.docs')
908995
) {
909996
docsProvider.refresh();
910997
}

0 commit comments

Comments
 (0)