Skip to content

Conversation

@mraleph
Copy link
Member

@mraleph mraleph commented Dec 8, 2025

Make it possible to add default subcommand (designated by an empty
name) for a branch command: default subcommand will be run when no other
subcommand is selected. This allows creating command line interfaces
where both program command and program command subcommand are
runnable.

Fixes #103

  • Thanks for your contribution! Please replace this text with a description of what this PR is changing or adding and why, list any relevant issues, and review the contribution guidelines below.

  • I’ve reviewed the contributor guide and applied the relevant portions to this PR.
Contribution guidelines:

Many Dart repos have a weekly cadence for reviewing PRs - please allow for some latency before initial review feedback.

Note: The Dart team is trialing Gemini Code Assist. Don't take its comments as final Dart team feedback. Use the suggestions if they're helpful; otherwise, wait for a human reviewer.

@mraleph mraleph requested a review from lrhn December 8, 2025 11:32
@github-actions
Copy link

github-actions bot commented Dec 8, 2025

Package publishing

Package Version Status Publish tag (post-merge)
package:args 2.8.0 ready to publish args-v2.8.0
package:async 2.13.1-wip WIP (no publish necessary)
package:characters 1.4.1 already published at pub.dev
package:collection 1.20.0-wip WIP (no publish necessary)
package:convert 3.1.3-wip WIP (no publish necessary)
package:crypto 3.0.7 already published at pub.dev
package:fixnum 1.2.0-wip WIP (no publish necessary)
package:lints 6.1.0-wip WIP (no publish necessary)
package:logging 1.3.1-wip WIP (no publish necessary)
package:os_detect 2.0.4-wip WIP (no publish necessary)
package:path 1.9.2-wip WIP (no publish necessary)
package:platform 3.1.7-wip WIP (no publish necessary)
package:typed_data 1.4.1-wip WIP (no publish necessary)

Documentation at https://github.com/dart-lang/ecosystem/wiki/Publishing-automation.

@github-actions
Copy link

github-actions bot commented Dec 8, 2025

PR Health

License Headers ✔️
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
Files
no missing headers

All source files should start with a license header.

This check can be disabled by tagging the PR with skip-license-check.

API leaks ✔️

The following packages contain symbols visible in the public API, but not exported by the library. Export these symbols or remove them from your publicly visible API.

Package Leaked API symbol Leaking sources

This check can be disabled by tagging the PR with skip-leaking-check.

Breaking changes ⚠️
Package Change Current Version New Version Needed Version Looking good?
args Breaking 2.7.0 2.8.0 3.0.0
Got "2.8.0" expected >= "3.0.0" (breaking changes)
⚠️

This check can be disabled by tagging the PR with skip-breaking-check.

Coverage ⚠️
File Coverage
pkgs/args/lib/command_runner.dart 💚 97 % ⬆️ 0 %
pkgs/args/lib/src/allow_anything_parser.dart 💔 67 % ⬇️ 11 %
pkgs/args/lib/src/arg_parser.dart 💚 94 %
pkgs/args/lib/src/parser.dart 💚 99 % ⬆️ 0 %

This check for test coverage is informational (issues shown here will not fail the PR).

This check can be disabled by tagging the PR with skip-coverage-check.

Changelog Entry ✔️
Package Changed Files

Changes to files need to be accounted for in their respective changelogs.

This check can be disabled by tagging the PR with skip-changelog-check.

@mraleph
Copy link
Member Author

mraleph commented Dec 8, 2025

A was looking at adding a subcommand to dart info (dart info record-performance, see CL) when I discovered that commands with subcommands are not runnable themselves. I don't want to change behavior of dart info nor do I want to make record-performance top level command (e.g. dart record-performance). So I decided to look at the simplest way to package:args can be extended to support this use case.

I think this is the simplest way.

Can you take a look @lrhn? (You commented before on #103 :) )

@mraleph mraleph marked this pull request as ready for review December 8, 2025 11:36
@mraleph mraleph requested a review from a team as a code owner December 8, 2025 11:36
Copy link
Member

@natebosch natebosch left a comment

Choose a reason for hiding this comment

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

Would it make sense to model this as picking a default named subcommand, instead of adding a single unnamed subcommand? The usage string is probably awkward to formulate either way, but it might be a little easier to show a default in the list of commands than to split the subcommand/no subcommand usage.

Allow designating a top-level command or a subcommand as a default one by
passing `isDefault: true` to `addCommand` or `addSubcommand`.
Default command will be selected by argument parser if no sibling command
matches. This allows creating command line interfaces where both
`program command` and `program command subcommand` are runnable

Fixes dart-lang#103
@mraleph
Copy link
Member Author

mraleph commented Dec 9, 2025

Thanks for the review @natebosch

Would it make sense to model this as picking a default named subcommand, instead of adding a single unnamed subcommand? The usage string is probably awkward to formulate either way, but it might be a little easier to show a default in the list of commands than to split the subcommand/no subcommand usage.

Yeah, I think this is a much better model. I have rewritten code to match this model. Can you take another look?

@mraleph
Copy link
Member Author

mraleph commented Dec 10, 2025

@natebosch Thanks! Can you take a final look, as I was doing the final testing I realized that behavior of program command -h was a bit surprising (and different from program help command) if command has a default subcommand: in this case program command -h would be equivalent to program command subcommand -h.

I have now changed the code to make program command -h print usage for command rather than select subcommand and print usage for the subcommand.

Does this change look reasonable to you? Thanks.

(I have also updated pubspec.yaml and CHANGELOG.md to remove -dev from the version, because I am planning to release it after landing this change).

@natebosch
Copy link
Member

Does this change look reasonable to you? Thanks.

Good catch. Yes that sounds like the right behavior to me.

I have also updated pubspec.yaml and CHANGELOG.md to remove -dev from the version, because I am planning to release it after landing this change

We'll want to make sure it lands smoothly in the Dart SDK repo and in google3 before we publish. https://github.com/dart-lang/sdk/blob/main/docs/External-Package-Maintenance.md#publishing-a-package

Let me know if you'd like me to help with that.

@mraleph
Copy link
Member Author

mraleph commented Dec 11, 2025

Thanks.

We'll want to make sure it lands smoothly in the Dart SDK repo and in google3 before we publish. https://github.com/dart-lang/sdk/blob/main/docs/External-Package-Maintenance.md#publishing-a-package

Ah! I actually got it backwards in my head for some reason. I was thinking I need to publish before the roll, but it makes sense that I need to roll it first. (roll is actually the only thing I care about - because I want to use this in the SDK :))

@mraleph mraleph merged commit 58b0a10 into dart-lang:main Dec 11, 2025
14 checks passed
@mraleph mraleph deleted the fix-103 branch December 11, 2025 08:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

How to run a command that has subcommands?

2 participants