Fix Commander parser for real-world CLI output#3
Merged
Conversation
Three issues fixed: 1. Multi-line wrapping: Commander wraps long descriptions/defaults across multiple lines (even with COLUMNS=200). Add unwrapContinuationLines() pre-processing that joins continuation lines (4+ spaces indent, not a new row) before lexing. Tested with real snip --help wrapped output. 2. Help command recursion: Commander always lists a "help [command]" subcommand. Recursing into it re-outputs the top-level help, causing duplicate content and wasted depth. Filter it out during post-processing. 3. Arguments section: Commander subcommands emit an "Arguments:" section for positional args (e.g. "snip add --help" shows "Arguments: filename"). Add startArgumentsSection token, argumentsSection parser rule, and visitor method mapping to ProgramInfo.positionals. Also updates snip --help.txt fixture to use real wrapped output instead of the manually unwrapped version. https://claude.ai/code/session_013xxgkuT1DBoaJ5MxQmrNuc
Add unwrapContinuationLines() to the Yargs parser, mirroring the Commander fix. Yargs wraps long descriptions and metadata ([string], [default:], [choices:]) across multiple lines at narrow terminal widths. The Yargs unwrap is section-aware: only joins continuation lines within Options/Commands/Positionals sections, preventing false matches on non-Yargs formats (e.g. meow's indented usage examples). Key differences from Commander unwrap: - Uses /^ *-/ to detect new option rows (Yargs uses variable indent: 2 spaces for aliased options, 6+ for long-only) - Section-aware: tracks Options:/Commands:/Positionals: headers, resets on blank lines - Does not attempt to unwrap command argument wrapping (e.g. <arg> at 2-space indent) as this creates ambiguous output New test fixture: yargs-wrapped-cli.js with .wrap(60) generating 10 options with long descriptions, choices, and defaults that wrap heavily across multiple lines. https://claude.ai/code/session_013xxgkuT1DBoaJ5MxQmrNuc
Document supported CLI frameworks with specific notes: - Yargs: .wrap() pattern for reliable piped output, known limitation with command argument wrapping at narrow widths - Commander: parenthesized defaults, env annotations, help command filtering - Meow: options-only support https://claude.ai/code/session_013xxgkuT1DBoaJ5MxQmrNuc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
unwrapContinuationLines()pre-processing that joins Commander's wrapped continuation lines (4+ spaces indent) before lexing. Real-world Commander CLIs like@kitschpatrol/snipwrap descriptions and(default: ...)values across multiple lines even withCOLUMNS=200. The lexer's ROW_MODE exits on\n, so continuation lines caused parse failures.help [command]from parsed commands. Recursing into it re-outputs the full top-level help, causing duplicate content and wasted recursion depth.Arguments:section support for Commander subcommands (e.g.snip add --helpemitsArguments: filename name of snippet). Maps toProgramInfo.positionals.Test plan
snip --help.txtfixture updated to use real wrapped output — parses correctlysnip add --helpoutput withArguments:section parses correctlyhttps://claude.ai/code/session_013xxgkuT1DBoaJ5MxQmrNuc