Skip to content

Design for subcommands in Dragonfruit #128

Open
@jonsequitur

Description

@jonsequitur
No description provided.

Activity

added this to the Initial public preview milestone on Jun 5, 2018
Keboo

Keboo commented on Jun 6, 2018

@Keboo
Member

After tonight's meeting here is one possible approach.

  • Change dragonfriut to find all public and internal methods inside of Program. In addition, include methods on nested classes as well.
  • If there is only a single method that is found and its name if "Main", simply configure the implicit root command with the options from the method. Simply invoke ConfigureFromMethod on the builder without adding any commands.
  • If multiple method are found, add each to the builder as a command. The name of the command should be the method name. If the method is inside of a nested class add the nested class as a parent command using the class name as the command name.

Example with simple commands.
Allows invocations:

> Foo.exe Command1
> Foo.exe Command2
class Program
{
    internal static void Command1() { }
    internal static void Command2() { }
}

Example with nested commands:
Allows invocation

> Foo.exe Add Package
> Foo.exe Add Reference
class Program
{
    class Add
    {
        internal static void Package() { }
        internal static void Reference() { }
    }
}
MarkMichaelis

MarkMichaelis commented on Jun 8, 2018

@MarkMichaelis
Contributor

Another option to consider would be using Dragonfruit as the entry point for Starfruit. In other words, the app programmer could write a class such as:

class Program
{
  public static void Main( MyCommandLine commandLine )
}
class MyCommandLine
{
  string Arg1 { get; set ; }
  bool Switch1 { get; set; }
  int Count1 { get; set }
  SubCommand  { get; set}
}
class SubCommand 
{
  string Arg2 { get; set; }
}
removed this from the Initial public preview milestone on Sep 12, 2018
jonsequitur

jonsequitur commented on Nov 9, 2018

@jonsequitur
ContributorAuthor

Related: #297

jnm2

jnm2 commented on Dec 21, 2018

@jnm2

I love the idea of having public static methods in Program become subcommands. I'll often move the top-level methods into Program.Command1.cs and Program.Command2.cs.

So... I don't know how kosher this is, but there are a couple instances where we went with this format:

  • <command> <opt1> <opt2> <opt3> <inner command> <opt4> <opt5>
  • <command> <opt1> <opt2> <opt3> <inner command 2> <opt6> <opt7> <opt8>
  • <command 2> <opt1> <opt2> <opt9>

And so we modeled this as:

public static class Program
{
    public static async Task<int> Main(string[] args)
    {
        // Manually maintained code at the moment.
        // Makes calls like: await Foo(...).InnerCommand(...).ConfigureAwait(false);
    }

    public static FooCommand Foo(string opt1, string opt2, string opt3)
    {
        return new FooCommand(opt1, opt2, opt3);
    }

    public readonly struct FooCommand
    {
        private readonly string opt1;
        private readonly string opt2;
        private readonly string opt3;

        public FooCommand(string opt1, string opt2, string opt3)
        {
            this.opt1 = opt1;
            this.opt2 = opt2;
            this.opt3 = opt3;
        }

        public async Task InnerCommand(string opt4, string opt5)
        {
            // Do stuff with opt1, opt2, opt3, opt4, and opt5
        }

        public async Task InnerCommand2(string opt6, string opt7, string opt8)
        {
            // Do stuff with opt1, opt2, opt3, opt6, opt7, and opt8
        }
    }

    public static async Task Bar(string opt1, string opt2, string opt9)
    {
        // Do stuff with opt1, opt2, and opt9
    }
}

(Made everything string for clarity. In actuality there were arguments such as IReadOnlyList<string> files and bool loseWork = false.)

Does this seem like a good model to recognize?

Cyber1000

Cyber1000 commented on Feb 19, 2023

@Cyber1000

Any news on this? Sorry to answer an old thread, but it seems to be still open.
Thanks!

KathleenDollard

KathleenDollard commented on Feb 21, 2023

@KathleenDollard
Contributor

We still plan a generation based simplifying approach that will include subcommands. When the spec is further along we will post it.

vonj

vonj commented on Mar 14, 2023

@vonj

We still plan a generation based simplifying approach that will include subcommands. When the spec is further along we will post it.

Can't wait!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @jonsequitur@MarkMichaelis@Keboo@Cyber1000@vonj

        Issue actions

          Design for subcommands in Dragonfruit · Issue #128 · dotnet/command-line-api