{"version":3,"file":"format-help.mjs","names":[],"sources":["../../src/lib/format-help.ts"],"sourcesContent":["import {\n  InternalOptionConfig,\n  UnknownOptionConfig,\n  readDefaultValue,\n  isOneOfOptionConfig,\n  isObjectOptionConfig,\n} from '@cli-forge/parser';\nimport { AnyInternalCLI } from './internal-cli';\n\nexport function formatHelp(parentCLI: AnyInternalCLI): string {\n  const help: string[] = [];\n  let command = parentCLI;\n  let epilogue = parentCLI.configuration?.epilogue;\n  for (const key of parentCLI.commandChain) {\n    command = command.registeredCommands[key] as typeof parentCLI;\n\n    // Properties that are ineherited from the parent command should be copied over\n    if (command.configuration?.epilogue) {\n      epilogue = command.configuration.epilogue;\n    }\n  }\n  help.push(\n    `Usage: ${\n      command.configuration?.usage\n        ? command.configuration.usage\n        : [\n            parentCLI.name,\n            ...parentCLI.commandChain,\n            ...command.parser.configuredPositionals.map((p) => {\n              const displayKey = command.parser.getDisplayKey(p.key);\n              return p.required ? `<${displayKey}>` : `[${displayKey}]`;\n            }),\n          ].join(' ')\n    }`\n  );\n  if (command.configuration?.description) {\n    help.push(command.configuration.description);\n  }\n  // Track displayed commands by their actual CLI instance to avoid duplicates\n  const displayedCommands = new Set<AnyInternalCLI>();\n  const visibleSubcommands: AnyInternalCLI[] = [];\n  for (const key in command.registeredCommands) {\n    const subcommand = command.registeredCommands[key];\n    // Skip if we've already displayed this command instance\n    if (displayedCommands.has(subcommand)) {\n      continue;\n    }\n    displayedCommands.add(subcommand);\n    if (subcommand.configuration?.hidden) {\n      continue;\n    }\n    visibleSubcommands.push(subcommand);\n  }\n  if (visibleSubcommands.length > 0) {\n    help.push('');\n    help.push('Commands:');\n  }\n  for (const subcommand of visibleSubcommands) {\n    // Use the localized command name for display based on the command's default name\n    const displayKey = command.getLocalizedCommandName(subcommand.name);\n    help.push(\n      `  ${displayKey}${\n        subcommand.configuration?.description\n          ? ' - ' + subcommand.configuration.description\n          : ''\n      }`\n    );\n  }\n  const groupedOptions = parentCLI.getGroupedOptions();\n  const nonpositionalOptions = Object.values(\n    command.parser.configuredOptions\n  ).filter((c) => !c.positional && !c.hidden);\n\n  help.push(...getOptionBlock('Options', nonpositionalOptions, command.parser));\n\n  for (const { label, keys } of groupedOptions) {\n    help.push(...getOptionBlock(label, keys, command.parser));\n  }\n\n  if (command.configuration?.examples?.length) {\n    help.push('');\n    help.push('Examples:');\n    for (const example of command.configuration.examples) {\n      help.push(`  \\`${example}\\``);\n    }\n  }\n\n  const configDocs = command.parser.getConfigurationDocs();\n  if (configDocs.length > 0) {\n    help.push('');\n    help.push('Configuration:');\n    for (const section of configDocs) {\n      help.push(`  ${section.heading}`);\n      help.push(`    ${section.body}`);\n    }\n  }\n\n  if (visibleSubcommands.length > 0) {\n    help.push(' ');\n    help.push(\n      `Run \\`${[parentCLI.name, ...parentCLI.commandChain].join(\n        ' '\n      )} [command] --help\\` for more information on a command`\n    );\n  }\n\n  if (epilogue) {\n    help.push('');\n    help.push(epilogue);\n  }\n\n  return help.join('\\n');\n}\n\nfunction getOptionParts(option: UnknownOptionConfig) {\n  const parts = [];\n  if (option.description) {\n    parts.push(option.description);\n  }\n  if (isOneOfOptionConfig(option)) {\n    const { valueTypes } = option;\n    const typeNames = valueTypes.map((vt) => vt.type).join('|');\n    parts.push(`[${typeNames}]`);\n    for (const vt of valueTypes) {\n      const subParts: string[] = [];\n      if (vt.description) {\n        subParts.push(vt.description);\n      }\n      if (vt.choices) {\n        const choices =\n          typeof vt.choices === 'function' ? vt.choices() : vt.choices;\n        subParts.push(`(${choices.join(', ')})`);\n      }\n      if (subParts.length > 0) {\n        parts.push(`${vt.type}: ${subParts.join(' ')}`);\n      }\n    }\n  } else if ('choices' in option && option.choices) {\n    const choices =\n      typeof option.choices === 'function' ? option.choices() : option.choices;\n    parts.push(`(${choices.join(', ')})`);\n  }\n  if (option.default) {\n    parts.push(\n      '[default: ' + formatDefaultValue(readDefaultValue(option)) + ']'\n    );\n  } else if (option.required) {\n    parts.push('[required]');\n  }\n  if (option.deprecated) {\n    parts.push('[deprecated: ' + option.deprecated + ']');\n  }\n  return parts;\n}\n\nfunction formatDefaultValue([value, description]: [any, string | undefined]) {\n  if (description) {\n    return description;\n  }\n  return removeTrailingAndLeadingQuotes(JSON.stringify(value));\n}\n\nfunction removeTrailingAndLeadingQuotes(str: string) {\n  return str.replace(/^['\"]/, '').replace(/['\"]$/, '');\n}\n\n/**\n * Extract the merged properties from a oneOf config's object valueTypes.\n * When a oneOf has object branches, their properties can be set via dot notation,\n * so we merge them for display in help output.\n */\nfunction getOneOfObjectProperties(\n  config: UnknownOptionConfig\n): Record<string, UnknownOptionConfig> | undefined {\n  if (!isOneOfOptionConfig(config)) return undefined;\n  const merged: Record<string, UnknownOptionConfig> = {};\n  let found = false;\n  for (const vt of config.valueTypes) {\n    if (\n      vt.type === 'object' &&\n      'properties' in vt &&\n      vt.properties &&\n      typeof vt.properties === 'object'\n    ) {\n      found = true;\n      for (const [k, v] of Object.entries(\n        vt.properties as Record<string, UnknownOptionConfig>\n      )) {\n        // First object branch wins for any given key\n        if (!(k in merged)) {\n          merged[k] = v;\n        }\n      }\n    }\n  }\n  return found ? merged : undefined;\n}\n\nfunction collectObjectProperties(\n  parentKey: string,\n  properties: Record<string, UnknownOptionConfig>\n): Array<{ key: string; config: UnknownOptionConfig }> {\n  const result: Array<{ key: string; config: UnknownOptionConfig }> = [];\n  for (const [name, config] of Object.entries(properties)) {\n    if (config.hidden) continue;\n    const fullKey = `${parentKey}.${name}`;\n    result.push({ key: fullKey, config });\n    if (isObjectOptionConfig(config) && config.properties) {\n      result.push(\n        ...collectObjectProperties(\n          fullKey,\n          config.properties as Record<string, UnknownOptionConfig>\n        )\n      );\n    } else {\n      const oneOfProps = getOneOfObjectProperties(config);\n      if (oneOfProps) {\n        result.push(...collectObjectProperties(fullKey, oneOfProps));\n      }\n    }\n  }\n  return result;\n}\n\nfunction getPropertyEntries(\n  option: UnknownOptionConfig\n): Array<{ key: string; config: UnknownOptionConfig }> {\n  let properties: Record<string, UnknownOptionConfig> | undefined;\n  if (isObjectOptionConfig(option) && option.properties) {\n    properties = option.properties as Record<string, UnknownOptionConfig>;\n  } else {\n    properties = getOneOfObjectProperties(option);\n  }\n  if (!properties) return [];\n  return collectObjectProperties(\n    (option as InternalOptionConfig).key,\n    properties\n  );\n}\n\nfunction formatFlag(name: string): string {\n  return name.length === 1 ? `-${name}` : `--${name}`;\n}\n\nfunction getDisplayAliases(\n  option: InternalOptionConfig,\n  displayKey: string\n): string[] {\n  const aliases = option.alias ?? [];\n  if (aliases.length === 0) return [];\n  const hiddenAliases = option.hiddenAliases ?? [];\n  return aliases.filter(\n    (alias) => alias !== displayKey && !hiddenAliases.includes(alias)\n  );\n}\n\nfunction buildFlagColumn(displayKey: string, aliases: string[]): string {\n  return [formatFlag(displayKey), ...aliases.map(formatFlag)].join(', ');\n}\n\nfunction getOptionBlock(\n  label: string,\n  options: InternalOptionConfig[],\n  parser: import('@cli-forge/parser').ReadonlyArgvParser<any>\n) {\n  const lines: string[] = [];\n\n  if (options.length > 0) {\n    lines.push('');\n    lines.push(label + ':');\n  }\n\n  // Collect all entries (options + their property sub-entries) into a flat list\n  const entries: Array<{\n    flagColumn: string;\n    parts: string[];\n    indent: number;\n  }> = [];\n\n  for (const option of options) {\n    const displayKey = parser.getDisplayKey(option.key);\n    const aliases = getDisplayAliases(option, displayKey);\n    entries.push({\n      flagColumn: buildFlagColumn(displayKey, aliases),\n      parts: getOptionParts(option),\n      indent: 0,\n    });\n    for (const { key, config } of getPropertyEntries(option)) {\n      entries.push({\n        flagColumn: `--${key}`,\n        parts: getOptionParts(config),\n        indent: 2,\n      });\n    }\n  }\n\n  // Compute flag column width accounting for indent so all `-` separators align\n  let flagColumnWidth = 0;\n  for (const entry of entries) {\n    flagColumnWidth = Math.max(\n      flagColumnWidth,\n      entry.indent + entry.flagColumn.length\n    );\n  }\n\n  // Compute padding for each part column across all entries\n  const partPadding: number[] = [];\n  for (const entry of entries) {\n    for (let j = 0; j < entry.parts.length; j++) {\n      if (!partPadding[j]) {\n        partPadding[j] = 0;\n      }\n      partPadding[j] = Math.max(partPadding[j], entry.parts[j].length);\n    }\n  }\n\n  for (const { flagColumn, parts, indent } of entries) {\n    const paddedFlagColumn = flagColumn.padEnd(flagColumnWidth - indent);\n    lines.push(\n      `${' '.repeat(2 + indent)}${paddedFlagColumn}${\n        parts.length ? ' - ' : ''\n      }${parts.map((part, i) => part.padEnd(partPadding[i])).join(' ')}`\n    );\n  }\n  return lines;\n}\n"],"mappings":"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"}