Skip to content

Migrate CLI parsing to System.CommandLine; fix -c/-k unquoted command (#65)#72

Open
mkrueger wants to merge 11 commits intomainfrom
dev/mkrueger/system-commandline
Open

Migrate CLI parsing to System.CommandLine; fix -c/-k unquoted command (#65)#72
mkrueger wants to merge 11 commits intomainfrom
dev/mkrueger/system-commandline

Conversation

@mkrueger
Copy link
Copy Markdown
Contributor

@mkrueger mkrueger commented May 4, 2026

Migrates CLI parsing from CommandLineParser (maintenance mode) to System.CommandLine, and uses the migration to fix #65.

Why

CommandLineParser does not have a "consume the remainder" option, so today CosmosDBShell -c help mkitem parses as -c=help plus a stray mkitem token, prints the general help, and ignores the user's intent. System.CommandLine is actively maintained by Microsoft and lets us cleanly model that the rest of the command line belongs to -c / -k.

What changed

Commit 1 - Migrate CLI parsing from CommandLineParser to System.CommandLine

  • Replace CommandLineParser 2.9.1 with System.CommandLine 2.0.0-beta4 in Directory.Packages.props and the main project.
  • Rewrite Program.cs to declare options via Option<T> and project the parsed result onto the existing CosmosShellOptions POCO. --mcp now uses native ArgumentArity.ZeroOrOne instead of arg patching.
  • New NormalizeArguments step before parsing:
    1. Translates Windows-style /c, /C, /k, /K to -c / -k.
    2. Once -c or -k is encountered, joins all remaining tokens into a single command string. So CosmosDBShell -c help mkitem and CosmosDBShell /c help mkitem now work without quoting (CosmosDBShell -c help mkitem doesn't work #65).
  • LocalizableSentenceBuilder no longer derives from CommandLine.Text.SentenceBuilder; it stays as a static accessor for localized option descriptions consumed by the new option builder.
  • Drop unused using CommandLine[.Text] references.

Commit 2 - Document and test -c/-k consume-rest behavior

  • Update -c / -k localized help strings to mention that quoting is optional and /c / /k are accepted.
  • README, docs/navigation.md, docs/programming.md: clarify that app-level options must come before -c / -k (since everything after them is captured as the command). Fix examples that previously placed --connect after -c.
  • New NormalizeArgumentsTests covering pass-through, -c / -k consume-rest, /c, /C, /k, /K translation, app options before -c, dangling -c, and option-like tokens being absorbed after -c.

Behavior notes

  • App-level options (e.g. --connect) must come before -c / -k now. This is consistent with cmd /c and bash -c.
  • --help / --version are intercepted up-front so we keep our own localized version heading. Plain text help is rendered by BuildHelpText; if richer formatting is desired we can later route through Spectre.
  • All previously working forms (-c "help mkitem", --connect ... -c "...") continue to work.

Validation

  • dotnet build of both CosmosDBShell and CosmosDBShell.Tests succeeds.
  • 12 new NormalizeArguments tests pass.
  • Smoke tested -c "echo hello", -c echo hello world, /c help mkitem against the built binary.

Fixes #65.

mkrueger added 2 commits May 4, 2026 10:59
- Replace CommandLineParser 2.9.1 with System.CommandLine 2.0.0-beta4.
- Rewrite Program.cs to declare options via Option<T> and project the
  parsed result onto the existing CosmosShellOptions POCO.
- Pre-process argv so -c/-k (and Windows-style /c, /k) consume all
  remaining tokens as a single command string. This makes
  `CosmosDBShell -c help mkitem` work without quotes (issue #65).
- LocalizableSentenceBuilder no longer derives from
  CommandLine.Text.SentenceBuilder; it stays as a static accessor for
  localized option descriptions used by the new option builder.
- Drop unused `using CommandLine[.Text]` references in HelpCommand
  and ParseDocDBConnectionTests; trim SentenceBuilderTests to the
  parts that still apply.
- Update -c / -k localized help strings to mention that quoting is
  optional and Windows-style /c, /k are accepted.
- README, docs/navigation.md, docs/programming.md: clarify that app-
  level options must come before -c / -k since everything after -c / -k
  is captured as the command. Fix examples that previously placed
  --connect after -c.
- Add NormalizeArgumentsTests covering pass-through, -c/-k consume-rest,
  /c, /C, /k, /K translation, app options before -c, dangling -c, and
  option-like tokens being absorbed after -c.
@mkrueger mkrueger requested review from a team and Copilot May 4, 2026 09:01
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates CosmosDBShell’s host-process CLI argument parsing from CommandLineParser to System.CommandLine, and introduces an argv normalization step so -c/-k can consume the remaining command tail without requiring quoting (fixing #65). It also updates docs/localized help text and adds unit tests for the new normalization behavior.

Changes:

  • Replace CommandLineParser-based parsing with System.CommandLine option definitions and POCO projection in Program.cs.
  • Add NormalizeArguments to translate /c//k to -c/-k and collapse the remainder of argv after -c/-k into a single command string.
  • Update docs and localized help strings, and add new tests for argument normalization.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
docs/programming.md Documents new -c/-k consume-rest behavior and option ordering requirement.
docs/navigation.md Updates startup option table to reflect consume-rest and /c//k support.
README.md Updates examples to place app options before -c and show unquoted tails.
Directory.Packages.props Replaces CommandLineParser package version with System.CommandLine.
CosmosDBShell/lang/en.ftl Updates localized help strings for -c/-k to explain consume-rest behavior.
CosmosDBShell/Program.cs Implements System.CommandLine parsing, argv normalization, and custom help/version handling.
CosmosDBShell/CosmosDBShell.csproj Swaps package reference from CommandLineParser to System.CommandLine.
CosmosDBShell/Azure.Data.Cosmos.Shell.Util/LocalizableSentenceBuilder.cs Removes CommandLineParser SentenceBuilder inheritance; keeps localized string accessors.
CosmosDBShell/Azure.Data.Cosmos.Shell.Commands/HelpCommand.cs Removes unused CommandLine.Text using.
CosmosDBShell.Tests/UtilTest/SentenceBuilderTests.cs Removes tests that depended on SentenceBuilder instantiation.
CosmosDBShell.Tests/UtilTest/ParseDocDBConnectionTests.cs Removes unused CommandLine-related usings.
CosmosDBShell.Tests/UtilTest/NormalizeArgumentsTests.cs Adds unit tests for NormalizeArguments behavior (consume-rest + /c//k).

Comment thread CosmosDBShell/Program.cs
Comment thread CosmosDBShell/Program.cs
Comment thread CosmosDBShell/Program.cs
@mkrueger mkrueger added enhancement New feature or request labels May 4, 2026
mkrueger added 2 commits May 4, 2026 11:27
- BuildHelpText now includes a one-line usage synopsis and the --help
  / --version pseudo-options, fixing ShellProcessTests.HelpOption_
  PrintsHelpAndExitsZero (was missing --version in --help output).
- LSP detection (--lsp/--stdio) runs after NormalizeArguments, so a
  --lsp or --stdio token that is part of a -c/-k command tail is
  absorbed as command text instead of accidentally starting the LSP
  server.
- Add LocalizedCliResources, a System.CommandLine.LocalizationResources
  subclass that maps the most common parse errors (unrecognized
  option/argument, missing value, missing required argument, bad
  conversion) to the existing help-error-* entries in en.ftl, so the
  localized error strings authored for the previous parser are not
  lost. Other messages fall back to the default English text.
Replace the hardcoded synopsis line, command-tail note, and --help/
--version descriptions in BuildHelpText with new help-UsageSynopsis,
help-CommandTailNote, help-HelpOptionDescription, and
help-VersionOptionDescription entries in en.ftl.
Copilot AI review requested due to automatic review settings May 4, 2026 09:58
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

CosmosDBShell/Program.cs:33

  • --lsp/--stdio detection currently scans the fully-normalized argv (args.Contains(...)). If the user runs a command tail that is exactly --lsp/--stdio (e.g., cosmosdbshell -c --lsp), NormalizeArguments collapses the tail into a single token that still equals --lsp, so the shell will incorrectly enter LSP mode instead of executing the command. Consider only honoring --lsp/--stdio when they appear before any -c/-k token (scan args until -c/-k and ignore anything after), so command tails are always treated as command text.
        // Handle LSP mode early, before any other code can write to stdout.
        // The LSP protocol requires exclusive access to stdin/stdout.
        if (args.Contains("--lsp") || args.Contains("--stdio"))
        {
            var server = await LspServer.CreateLanguageServerAsync();
            await server.WaitForExit;

Comment thread CosmosDBShell/Program.cs
mkrueger added 2 commits May 4, 2026 12:35
Introduce TakePreCommandArgs and route the manual --help/--version
and --lsp/--stdio interception through it. Previously a single
trailing token after -c (e.g. `-c --help`) would still match the
element-equality check and be intercepted as an app-level flag
instead of being forwarded to the shell command. Add four
TakePreCommandArgs unit tests.
Copilot AI review requested due to automatic review settings May 4, 2026 11:49
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Comment thread CosmosDBShell/Program.cs
Comment thread CosmosDBShell/Program.cs Outdated
Comment thread docs/navigation.md Outdated
mkrueger added 2 commits May 4, 2026 14:21
…n, doc -k

- Stdin-piped script error path now stops the MCP host (and stops
  StartLspServer's hostTask) before returning, matching the explicit-
  command error path; previously the early return left the background
  host task running against the soon-to-be-disposed IHost.
- LocalizedCliResources.UnrecognizedCommandOrArgument /
  UnrecognizedArgument now branches on whether the token starts with
  `-`: option-shaped tokens still get the localized`Option '...' is
  unknown` message, but bare positional tokens map to a new
  `help-error-UnknownArgumentError` (`Unrecognized argument '...'`)
  so root-level stray positionals are not misreported as options.
- docs/navigation.md `-k` row now states explicitly that app-level
  options must come before `-k`, mirroring the `-c` row.
Copilot AI review requested due to automatic review settings May 5, 2026 07:46
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.

Comment thread CosmosDBShell/Program.cs Outdated
Comment thread CosmosDBShell/Program.cs Outdated
Comment thread CosmosDBShell/Program.cs Outdated
Comment thread CosmosDBShell/Program.cs Outdated
mkrueger added 2 commits May 5, 2026 10:13
Rename --clearhistory to --clear-history and --cs to --color-system to match the hyphenated convention used by the other startup options. The original short forms are kept as aliases for back-compat.
Auto-size the option column, add value placeholders (<n>, <endpoint>, <direct|gateway>, [<port>], etc.), split OPTIONS and NOTES sections, and clean up the -c/-k and --color-system descriptions.
Copilot AI review requested due to automatic review settings May 5, 2026 08:16
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Comment thread CosmosDBShell/Program.cs Outdated
Comment thread CosmosDBShell/Program.cs Outdated
Comment thread CosmosDBShell/Program.cs
Remove --connect-mode default-option binding so stray root arguments remain unrecognized arguments. Centralize MCP host shutdown and await the host task on all early returns that stop the host. Use the user-facing option alias in localized missing-value/required-option diagnostics. Add process-level tests for root unknown arguments and missing --connect values.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CosmosDBShell -c help mkitem doesn't work

2 participants