@optique/man 1.4.0-dev.2628 → 1.4.0-dev.2631

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- const require_man = require('./man-C44Q4VSc.cjs');
2
+ const require_man = require('./man-DLcciZWq.cjs');
3
3
  require('./roff-C8MvQ2tL.cjs');
4
- const require_generator = require('./generator-CtkCu_MS.cjs');
4
+ const require_generator = require('./generator-CUCPcKy-.cjs');
5
5
  const __optique_core_constructs = require_man.__toESM(require("@optique/core/constructs"));
6
6
  const __optique_core_primitives = require_man.__toESM(require("@optique/core/primitives"));
7
7
  const __optique_core_valueparser = require_man.__toESM(require("@optique/core/valueparser"));
@@ -17,7 +17,7 @@ const node_url = require_man.__toESM(require("node:url"));
17
17
 
18
18
  //#region deno.json
19
19
  var name = "@optique/man";
20
- var version = "1.4.0-dev.2628+867c4f91";
20
+ var version = "1.4.0-dev.2631+0f2bd6a0";
21
21
  var license = "MIT";
22
22
  var exports$1 = {
23
23
  ".": "./src/index.ts",
@@ -88,6 +88,11 @@ a ${(0, __optique_core_message.metavar)("PROGRAM")} or ${(0, __optique_core_mess
88
88
  ${"1"} User commands
89
89
  ${"5"} File formats
90
90
  ${"8"} System administration` }),
91
+ showEnvironment: (0, __optique_core_modifiers.optional)((0, __optique_core_primitives.option)("--show-environment", (0, __optique_core_valueparser.choice)([
92
+ "inline",
93
+ "section",
94
+ "both"
95
+ ], { metavar: "LAYOUT" }), { description: __optique_core_message.message`Document declared environment bindings inline, in a section, or both.` })),
91
96
  exportName: (0, __optique_core_modifiers.withDefault)((0, __optique_core_primitives.option)("-e", "--export", (0, __optique_core_valueparser.string)({ metavar: "NAME" }), { description: __optique_core_message.message`JavaScript export name to use. The export must be
92
97
  a ${(0, __optique_core_message.metavar)("PROGRAM")} (from ${(0, __optique_core_message.commandLine)("defineProgram()")}) or
93
98
  a ${(0, __optique_core_message.metavar)("PARSER")}. If not specified, the default export is used.` }), "default"),
@@ -396,14 +401,16 @@ async function main() {
396
401
  name: args.name,
397
402
  date,
398
403
  version: args.versionString,
399
- manual: args.manual
404
+ manual: args.manual,
405
+ showEnvironment: args.showEnvironment == null ? void 0 : { placement: args.showEnvironment }
400
406
  });
401
407
  else manPage = await require_generator.generateManPageAsync(target, {
402
408
  name: name$1,
403
409
  section: args.section,
404
410
  date,
405
411
  version: args.versionString,
406
- manual: args.manual
412
+ manual: args.manual,
413
+ showEnvironment: args.showEnvironment == null ? void 0 : { placement: args.showEnvironment }
407
414
  });
408
415
  } catch (error) {
409
416
  generationError(error instanceof Error ? error : new Error(String(error)));
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import "./roff-Bh9bsH6u.js";
3
- import "./man-Cq0qfXg0.js";
4
- import { generateManPageAsync } from "./generator-DywTJCMH.js";
3
+ import "./man-CTCssitL.js";
4
+ import { generateManPageAsync } from "./generator-IQLTxhd0.js";
5
5
  import { object } from "@optique/core/constructs";
6
6
  import { argument, option } from "@optique/core/primitives";
7
7
  import { choice, string } from "@optique/core/valueparser";
@@ -17,7 +17,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
17
17
 
18
18
  //#region deno.json
19
19
  var name = "@optique/man";
20
- var version = "1.4.0-dev.2628+867c4f91";
20
+ var version = "1.4.0-dev.2631+0f2bd6a0";
21
21
  var license = "MIT";
22
22
  var exports = {
23
23
  ".": "./src/index.ts",
@@ -88,6 +88,11 @@ a ${metavar("PROGRAM")} or ${metavar("PARSER")} to generate a man page from.` })
88
88
  ${"1"} User commands
89
89
  ${"5"} File formats
90
90
  ${"8"} System administration` }),
91
+ showEnvironment: optional(option("--show-environment", choice([
92
+ "inline",
93
+ "section",
94
+ "both"
95
+ ], { metavar: "LAYOUT" }), { description: message`Document declared environment bindings inline, in a section, or both.` })),
91
96
  exportName: withDefault(option("-e", "--export", string({ metavar: "NAME" }), { description: message`JavaScript export name to use. The export must be
92
97
  a ${metavar("PROGRAM")} (from ${commandLine("defineProgram()")}) or
93
98
  a ${metavar("PARSER")}. If not specified, the default export is used.` }), "default"),
@@ -396,14 +401,16 @@ async function main() {
396
401
  name: args.name,
397
402
  date,
398
403
  version: args.versionString,
399
- manual: args.manual
404
+ manual: args.manual,
405
+ showEnvironment: args.showEnvironment == null ? void 0 : { placement: args.showEnvironment }
400
406
  });
401
407
  else manPage = await generateManPageAsync(target, {
402
408
  name: name$1,
403
409
  section: args.section,
404
410
  date,
405
411
  version: args.versionString,
406
- manual: args.manual
412
+ manual: args.manual,
413
+ showEnvironment: args.showEnvironment == null ? void 0 : { placement: args.showEnvironment }
407
414
  });
408
415
  } catch (error) {
409
416
  generationError(error instanceof Error ? error : new Error(String(error)));
@@ -1,4 +1,4 @@
1
- import { ManPageOptions } from "./man-CHYiSoI_.js";
1
+ import { ManPageOptions } from "./man-B0OHE33m.js";
2
2
  import { Program } from "@optique/core/program";
3
3
  import { Mode, ModeValue, Parser } from "@optique/core/parser";
4
4
 
@@ -1,4 +1,4 @@
1
- const require_man = require('./man-C44Q4VSc.cjs');
1
+ const require_man = require('./man-DLcciZWq.cjs');
2
2
  const __optique_core_parser = require_man.__toESM(require("@optique/core/parser"));
3
3
 
4
4
  //#region src/generator.ts
@@ -55,6 +55,7 @@ function extractParserAndOptions(parserOrProgram, options) {
55
55
  footer: programOptions.footer ?? metadata.footer,
56
56
  seeAlso: programOptions.seeAlso,
57
57
  environment: programOptions.environment,
58
+ showEnvironment: programOptions.showEnvironment,
58
59
  files: programOptions.files,
59
60
  exitStatus: programOptions.exitStatus
60
61
  }
@@ -1,4 +1,4 @@
1
- import { formatDocPageAsMan } from "./man-Cq0qfXg0.js";
1
+ import { formatDocPageAsMan } from "./man-CTCssitL.js";
2
2
  import { getDocPageAsync, getDocPageSync } from "@optique/core/parser";
3
3
 
4
4
  //#region src/generator.ts
@@ -55,6 +55,7 @@ function extractParserAndOptions(parserOrProgram, options) {
55
55
  footer: programOptions.footer ?? metadata.footer,
56
56
  seeAlso: programOptions.seeAlso,
57
57
  environment: programOptions.environment,
58
+ showEnvironment: programOptions.showEnvironment,
58
59
  files: programOptions.files,
59
60
  exitStatus: programOptions.exitStatus
60
61
  }
@@ -1,4 +1,4 @@
1
- import { ManPageOptions } from "./man-C3FUTPuQ.cjs";
1
+ import { ManPageOptions } from "./man-Yl3ZzrBK.cjs";
2
2
  import { Mode, ModeValue, Parser } from "@optique/core/parser";
3
3
  import { Program } from "@optique/core/program";
4
4
 
@@ -1,6 +1,6 @@
1
- require('./man-C44Q4VSc.cjs');
1
+ require('./man-DLcciZWq.cjs');
2
2
  require('./roff-C8MvQ2tL.cjs');
3
- const require_generator = require('./generator-CtkCu_MS.cjs');
3
+ const require_generator = require('./generator-CUCPcKy-.cjs');
4
4
 
5
5
  exports.generateManPage = require_generator.generateManPage;
6
6
  exports.generateManPageAsync = require_generator.generateManPageAsync;
@@ -1,3 +1,3 @@
1
- import "./man-C3FUTPuQ.cjs";
2
- import { GenerateManPageOptions, GenerateManPageProgramOptions, generateManPage, generateManPageAsync, generateManPageSync } from "./generator-I9cXlw1Z.cjs";
1
+ import "./man-Yl3ZzrBK.cjs";
2
+ import { GenerateManPageOptions, GenerateManPageProgramOptions, generateManPage, generateManPageAsync, generateManPageSync } from "./generator-stLqR1GX.cjs";
3
3
  export { GenerateManPageOptions, GenerateManPageProgramOptions, generateManPage, generateManPageAsync, generateManPageSync };
@@ -1,3 +1,3 @@
1
- import "./man-CHYiSoI_.js";
2
- import { GenerateManPageOptions, GenerateManPageProgramOptions, generateManPage, generateManPageAsync, generateManPageSync } from "./generator-MbR1I1SH.js";
1
+ import "./man-B0OHE33m.js";
2
+ import { GenerateManPageOptions, GenerateManPageProgramOptions, generateManPage, generateManPageAsync, generateManPageSync } from "./generator-BK-jIonK.js";
3
3
  export { GenerateManPageOptions, GenerateManPageProgramOptions, generateManPage, generateManPageAsync, generateManPageSync };
package/dist/generator.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "./roff-Bh9bsH6u.js";
2
- import "./man-Cq0qfXg0.js";
3
- import { generateManPage, generateManPageAsync, generateManPageSync } from "./generator-DywTJCMH.js";
2
+ import "./man-CTCssitL.js";
3
+ import { generateManPage, generateManPageAsync, generateManPageSync } from "./generator-IQLTxhd0.js";
4
4
 
5
5
  export { generateManPage, generateManPageAsync, generateManPageSync };
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
- const require_man = require('./man-C44Q4VSc.cjs');
1
+ const require_man = require('./man-DLcciZWq.cjs');
2
2
  const require_roff = require('./roff-C8MvQ2tL.cjs');
3
- const require_generator = require('./generator-CtkCu_MS.cjs');
3
+ const require_generator = require('./generator-CUCPcKy-.cjs');
4
4
 
5
5
  exports.escapeHyphens = require_roff.escapeHyphens;
6
6
  exports.escapeQuotedValue = require_roff.escapeQuotedValue;
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { ManPageOptions, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-C3FUTPuQ.cjs";
2
- import { GenerateManPageOptions, GenerateManPageProgramOptions, generateManPage, generateManPageAsync, generateManPageSync } from "./generator-I9cXlw1Z.cjs";
1
+ import { ManPageOptions, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-Yl3ZzrBK.cjs";
2
+ import { GenerateManPageOptions, GenerateManPageProgramOptions, generateManPage, generateManPageAsync, generateManPageSync } from "./generator-stLqR1GX.cjs";
3
3
  import { RoffFormatOptions, escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatMessageAsRoff } from "./roff-Cpm_FJok.cjs";
4
4
  export { type GenerateManPageOptions, type GenerateManPageProgramOptions, type ManPageOptions, type RoffFormatOptions, escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatDateForMan, formatDocPageAsMan, formatMessageAsRoff, formatUsageTermAsRoff, generateManPage, generateManPageAsync, generateManPageSync };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ManPageOptions, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-CHYiSoI_.js";
2
- import { GenerateManPageOptions, GenerateManPageProgramOptions, generateManPage, generateManPageAsync, generateManPageSync } from "./generator-MbR1I1SH.js";
1
+ import { ManPageOptions, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-B0OHE33m.js";
2
+ import { GenerateManPageOptions, GenerateManPageProgramOptions, generateManPage, generateManPageAsync, generateManPageSync } from "./generator-BK-jIonK.js";
3
3
  import { RoffFormatOptions, escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatMessageAsRoff } from "./roff-DkJvVQ1o.js";
4
4
  export { type GenerateManPageOptions, type GenerateManPageProgramOptions, type ManPageOptions, type RoffFormatOptions, escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatDateForMan, formatDocPageAsMan, formatMessageAsRoff, formatUsageTermAsRoff, generateManPage, generateManPageAsync, generateManPageSync };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatMessageAsRoff } from "./roff-Bh9bsH6u.js";
2
- import { formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-Cq0qfXg0.js";
3
- import { generateManPage, generateManPageAsync, generateManPageSync } from "./generator-DywTJCMH.js";
2
+ import { formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-CTCssitL.js";
3
+ import { generateManPage, generateManPageAsync, generateManPageSync } from "./generator-IQLTxhd0.js";
4
4
 
5
5
  export { escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatDateForMan, formatDocPageAsMan, formatMessageAsRoff, formatUsageTermAsRoff, generateManPage, generateManPageAsync, generateManPageSync };
@@ -1,5 +1,5 @@
1
- import { DocPage, DocSection } from "@optique/core/doc";
2
1
  import { Message } from "@optique/core/message";
2
+ import { DocPage, DocSection, ShowEnvironmentOptions } from "@optique/core/doc";
3
3
  import { UsageTerm } from "@optique/core/usage";
4
4
 
5
5
  //#region src/man.d.ts
@@ -70,6 +70,15 @@ interface ManPageOptions {
70
70
  * Environment variables to document in the ENVIRONMENT section.
71
71
  */
72
72
  readonly environment?: DocSection;
73
+ /**
74
+ * Displays declared environment bindings. `true` selects inline annotations;
75
+ * an object can select a generated section or both. Defaults to `false`.
76
+ * A supplied `environment` section overrides the generated section, including
77
+ * an empty section. Inline annotations are independent of that override.
78
+ * `sectionTitle` only affects generated sections and is uppercased.
79
+ * @since 1.4.0
80
+ */
81
+ readonly showEnvironment?: boolean | ShowEnvironmentOptions;
73
82
  /**
74
83
  * File paths to document in the FILES section.
75
84
  */
@@ -148,7 +157,8 @@ declare function formatUsageTermAsRoff(term: UsageTerm): string;
148
157
  * @param page The documentation page to format.
149
158
  * @param options The man page options.
150
159
  * @returns The complete man page in roff format.
151
- * @throws {TypeError} If the program name is empty.
160
+ * @throws {TypeError} If the program name is empty or a generated environment
161
+ * section title is empty, whitespace-only, or contains control characters.
152
162
  * @throws {RangeError} If the section number or any `seeAlso` entry's section
153
163
  * number is not a valid man page section (1–8).
154
164
  * @since 0.10.0
@@ -1,4 +1,5 @@
1
1
  import { escapeHyphens, escapeRequestArg, escapeRoff, formatMessageAsRoff } from "./roff-Bh9bsH6u.js";
2
+ import { deriveEnvironmentSection } from "@optique/core/doc";
2
3
  import { isDocHidden, isUsageHidden } from "@optique/core/usage";
3
4
 
4
5
  //#region src/man.ts
@@ -225,22 +226,29 @@ function inferSectionTitle(entries) {
225
226
  * @param section The section to format.
226
227
  * @returns The roff-formatted section content.
227
228
  */
228
- function formatDocSectionEntries(section) {
229
+ function formatDocSectionEntries(section, showEnvironment = false) {
229
230
  const lines = [];
230
231
  for (const entry of section.entries) {
231
232
  const termStr = formatDocEntryTerm(entry.term);
232
233
  if (termStr === "") continue;
233
234
  lines.push(".TP");
234
235
  lines.push(termStr);
236
+ const envNames = showEnvironment ? [...new Set(entry.envVars ?? [])].filter((name) => name !== "") : [];
237
+ const envAnnotation = envNames.length === 0 ? "" : `[env: ${envNames.map((name) => formatMessageAsRoff([{
238
+ type: "envVar",
239
+ envVar: name
240
+ }])).join(", ")}]`;
235
241
  if (entry.description) {
236
242
  let desc = formatMessageAsRoff(entry.description);
237
243
  if (entry.default) desc += ` [${formatMessageAsRoff(entry.default)}]`;
238
244
  if (entry.choices) desc += ` (choices: ${formatMessageAsRoff(entry.choices, { quotes: false })})`;
239
- lines.push(desc);
240
- } else if (entry.default || entry.choices) {
245
+ const separator = desc === "" || desc.endsWith("\n") ? "" : " ";
246
+ lines.push(envAnnotation === "" ? desc : desc + separator + envAnnotation);
247
+ } else if (entry.default || entry.choices || envAnnotation !== "") {
241
248
  const parts = [];
242
249
  if (entry.default) parts.push(`[${formatMessageAsRoff(entry.default)}]`);
243
250
  if (entry.choices) parts.push(`(choices: ${formatMessageAsRoff(entry.choices, { quotes: false })})`);
251
+ if (envAnnotation !== "") parts.push(envAnnotation);
244
252
  lines.push(parts.join(" "));
245
253
  }
246
254
  }
@@ -273,7 +281,8 @@ function formatDocSectionEntries(section) {
273
281
  * @param page The documentation page to format.
274
282
  * @param options The man page options.
275
283
  * @returns The complete man page in roff format.
276
- * @throws {TypeError} If the program name is empty.
284
+ * @throws {TypeError} If the program name is empty or a generated environment
285
+ * section title is empty, whitespace-only, or contains control characters.
277
286
  * @throws {RangeError} If the section number or any `seeAlso` entry's section
278
287
  * number is not a valid man page section (1–8).
279
288
  * @since 0.10.0
@@ -315,18 +324,23 @@ function formatDocPageAsMan(page, options) {
315
324
  lines.push(".SH DESCRIPTION");
316
325
  lines.push(formatMessageAsRoff(description));
317
326
  }
327
+ const placement = typeof options.showEnvironment === "object" ? options.showEnvironment.placement ?? "inline" : options.showEnvironment ? "inline" : void 0;
328
+ const inlineEnvironment = placement === "inline" || placement === "both";
318
329
  for (const section of page.sections) {
319
330
  if (section.entries.length === 0) continue;
320
- const content = formatDocSectionEntries(section);
331
+ const content = formatDocSectionEntries(section, inlineEnvironment);
321
332
  if (content === "") continue;
322
333
  const title = section.title?.toUpperCase() ?? inferSectionTitle(section.entries);
323
334
  lines.push(`.SH "${escapeRequestArg(title)}"`);
324
335
  lines.push(content);
325
336
  }
326
- if (options.environment && options.environment.entries.length > 0) {
327
- const content = formatDocSectionEntries(options.environment);
337
+ const automaticEnvironment = options.environment == null && (placement === "section" || placement === "both") ? deriveEnvironmentSection(page, { title: typeof options.showEnvironment === "object" ? options.showEnvironment.sectionTitle : void 0 }) : void 0;
338
+ const environment = options.environment ?? automaticEnvironment;
339
+ if (environment != null && environment.entries.length > 0) {
340
+ const content = formatDocSectionEntries(environment);
328
341
  if (content !== "") {
329
- lines.push(".SH ENVIRONMENT");
342
+ const title = automaticEnvironment == null ? "ENVIRONMENT" : automaticEnvironment.title?.toUpperCase() ?? "ENVIRONMENT";
343
+ lines.push(title === "ENVIRONMENT" ? ".SH ENVIRONMENT" : `.SH "${escapeRequestArg(title)}"`);
330
344
  lines.push(content);
331
345
  }
332
346
  }
@@ -22,6 +22,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
22
22
 
23
23
  //#endregion
24
24
  const require_roff = require('./roff-C8MvQ2tL.cjs');
25
+ const __optique_core_doc = __toESM(require("@optique/core/doc"));
25
26
  const __optique_core_usage = __toESM(require("@optique/core/usage"));
26
27
 
27
28
  //#region src/man.ts
@@ -248,22 +249,29 @@ function inferSectionTitle(entries) {
248
249
  * @param section The section to format.
249
250
  * @returns The roff-formatted section content.
250
251
  */
251
- function formatDocSectionEntries(section) {
252
+ function formatDocSectionEntries(section, showEnvironment = false) {
252
253
  const lines = [];
253
254
  for (const entry of section.entries) {
254
255
  const termStr = formatDocEntryTerm(entry.term);
255
256
  if (termStr === "") continue;
256
257
  lines.push(".TP");
257
258
  lines.push(termStr);
259
+ const envNames = showEnvironment ? [...new Set(entry.envVars ?? [])].filter((name) => name !== "") : [];
260
+ const envAnnotation = envNames.length === 0 ? "" : `[env: ${envNames.map((name) => require_roff.formatMessageAsRoff([{
261
+ type: "envVar",
262
+ envVar: name
263
+ }])).join(", ")}]`;
258
264
  if (entry.description) {
259
265
  let desc = require_roff.formatMessageAsRoff(entry.description);
260
266
  if (entry.default) desc += ` [${require_roff.formatMessageAsRoff(entry.default)}]`;
261
267
  if (entry.choices) desc += ` (choices: ${require_roff.formatMessageAsRoff(entry.choices, { quotes: false })})`;
262
- lines.push(desc);
263
- } else if (entry.default || entry.choices) {
268
+ const separator = desc === "" || desc.endsWith("\n") ? "" : " ";
269
+ lines.push(envAnnotation === "" ? desc : desc + separator + envAnnotation);
270
+ } else if (entry.default || entry.choices || envAnnotation !== "") {
264
271
  const parts = [];
265
272
  if (entry.default) parts.push(`[${require_roff.formatMessageAsRoff(entry.default)}]`);
266
273
  if (entry.choices) parts.push(`(choices: ${require_roff.formatMessageAsRoff(entry.choices, { quotes: false })})`);
274
+ if (envAnnotation !== "") parts.push(envAnnotation);
267
275
  lines.push(parts.join(" "));
268
276
  }
269
277
  }
@@ -296,7 +304,8 @@ function formatDocSectionEntries(section) {
296
304
  * @param page The documentation page to format.
297
305
  * @param options The man page options.
298
306
  * @returns The complete man page in roff format.
299
- * @throws {TypeError} If the program name is empty.
307
+ * @throws {TypeError} If the program name is empty or a generated environment
308
+ * section title is empty, whitespace-only, or contains control characters.
300
309
  * @throws {RangeError} If the section number or any `seeAlso` entry's section
301
310
  * number is not a valid man page section (1–8).
302
311
  * @since 0.10.0
@@ -338,18 +347,23 @@ function formatDocPageAsMan(page, options) {
338
347
  lines.push(".SH DESCRIPTION");
339
348
  lines.push(require_roff.formatMessageAsRoff(description));
340
349
  }
350
+ const placement = typeof options.showEnvironment === "object" ? options.showEnvironment.placement ?? "inline" : options.showEnvironment ? "inline" : void 0;
351
+ const inlineEnvironment = placement === "inline" || placement === "both";
341
352
  for (const section of page.sections) {
342
353
  if (section.entries.length === 0) continue;
343
- const content = formatDocSectionEntries(section);
354
+ const content = formatDocSectionEntries(section, inlineEnvironment);
344
355
  if (content === "") continue;
345
356
  const title = section.title?.toUpperCase() ?? inferSectionTitle(section.entries);
346
357
  lines.push(`.SH "${require_roff.escapeRequestArg(title)}"`);
347
358
  lines.push(content);
348
359
  }
349
- if (options.environment && options.environment.entries.length > 0) {
350
- const content = formatDocSectionEntries(options.environment);
360
+ const automaticEnvironment = options.environment == null && (placement === "section" || placement === "both") ? (0, __optique_core_doc.deriveEnvironmentSection)(page, { title: typeof options.showEnvironment === "object" ? options.showEnvironment.sectionTitle : void 0 }) : void 0;
361
+ const environment = options.environment ?? automaticEnvironment;
362
+ if (environment != null && environment.entries.length > 0) {
363
+ const content = formatDocSectionEntries(environment);
351
364
  if (content !== "") {
352
- lines.push(".SH ENVIRONMENT");
365
+ const title = automaticEnvironment == null ? "ENVIRONMENT" : automaticEnvironment.title?.toUpperCase() ?? "ENVIRONMENT";
366
+ lines.push(title === "ENVIRONMENT" ? ".SH ENVIRONMENT" : `.SH "${require_roff.escapeRequestArg(title)}"`);
353
367
  lines.push(content);
354
368
  }
355
369
  }
@@ -1,6 +1,6 @@
1
+ import { DocPage, DocSection, ShowEnvironmentOptions } from "@optique/core/doc";
1
2
  import { Message } from "@optique/core/message";
2
3
  import { UsageTerm } from "@optique/core/usage";
3
- import { DocPage, DocSection } from "@optique/core/doc";
4
4
 
5
5
  //#region src/man.d.ts
6
6
 
@@ -70,6 +70,15 @@ interface ManPageOptions {
70
70
  * Environment variables to document in the ENVIRONMENT section.
71
71
  */
72
72
  readonly environment?: DocSection;
73
+ /**
74
+ * Displays declared environment bindings. `true` selects inline annotations;
75
+ * an object can select a generated section or both. Defaults to `false`.
76
+ * A supplied `environment` section overrides the generated section, including
77
+ * an empty section. Inline annotations are independent of that override.
78
+ * `sectionTitle` only affects generated sections and is uppercased.
79
+ * @since 1.4.0
80
+ */
81
+ readonly showEnvironment?: boolean | ShowEnvironmentOptions;
73
82
  /**
74
83
  * File paths to document in the FILES section.
75
84
  */
@@ -148,7 +157,8 @@ declare function formatUsageTermAsRoff(term: UsageTerm): string;
148
157
  * @param page The documentation page to format.
149
158
  * @param options The man page options.
150
159
  * @returns The complete man page in roff format.
151
- * @throws {TypeError} If the program name is empty.
160
+ * @throws {TypeError} If the program name is empty or a generated environment
161
+ * section title is empty, whitespace-only, or contains control characters.
152
162
  * @throws {RangeError} If the section number or any `seeAlso` entry's section
153
163
  * number is not a valid man page section (1–8).
154
164
  * @since 0.10.0
package/dist/man.cjs CHANGED
@@ -1,4 +1,4 @@
1
- const require_man = require('./man-C44Q4VSc.cjs');
1
+ const require_man = require('./man-DLcciZWq.cjs');
2
2
  require('./roff-C8MvQ2tL.cjs');
3
3
 
4
4
  exports.formatDateForMan = require_man.formatDateForMan;
package/dist/man.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { ManPageOptions, ManPageSection, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-C3FUTPuQ.cjs";
1
+ import { ManPageOptions, ManPageSection, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-Yl3ZzrBK.cjs";
2
2
  export { ManPageOptions, ManPageSection, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff };
package/dist/man.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { ManPageOptions, ManPageSection, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-CHYiSoI_.js";
1
+ import { ManPageOptions, ManPageSection, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-B0OHE33m.js";
2
2
  export { ManPageOptions, ManPageSection, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff };
package/dist/man.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import "./roff-Bh9bsH6u.js";
2
- import { formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-Cq0qfXg0.js";
2
+ import { formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-CTCssitL.js";
3
3
 
4
4
  export { formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/man",
3
- "version": "1.4.0-dev.2628",
3
+ "version": "1.4.0-dev.2631",
4
4
  "description": "Man page generator for Optique CLI parsers",
5
5
  "keywords": [
6
6
  "CLI",
@@ -90,11 +90,11 @@
90
90
  "optique-man": "./dist/cli.js"
91
91
  },
92
92
  "dependencies": {
93
- "@optique/core": "1.4.0-dev.2628+867c4f91",
94
- "@optique/run": "1.4.0-dev.2628+867c4f91"
93
+ "@optique/core": "1.4.0-dev.2631+0f2bd6a0",
94
+ "@optique/run": "1.4.0-dev.2631+0f2bd6a0"
95
95
  },
96
96
  "devDependencies": {
97
- "@optique/testing": "1.4.0-dev.2628+867c4f91",
97
+ "@optique/testing": "1.4.0-dev.2631+0f2bd6a0",
98
98
  "@types/node": "^24.0.0",
99
99
  "tsdown": "^0.13.0",
100
100
  "tsx": "^4.21.0",