dotnet / dotnet/command-line-api

Command handlers are always executed

Open
#2,013 6 comments 0 reactions 0 assignees View on GitHub
Dominant language
C#
Stars
3.7k
Forks
428
PR merge metrics
No merged PRs in 30d

Description

If I run this basic test program(almost verbatim with the MSDN docs), the main argument handler is executed even when no command line arguments are specified at all

```cs
using System.CommandLine;
using Stacks.Parsing;

Option mainArgument = new(
aliases: new string[] { "--main", "-m" },
description: "path to stacks main sdl file");

RootCommand stacksCommands = new()
{
mainArgument
};

stacksCommands.SetHandler(MainArgumentHandler, mainArgument);

await stacksCommands.InvokeAsync(args);

Console.ReadKey();

void MainArgumentHandler(string path)
{
new Parser(path).TryParse(out var appModel);
}
```

Maybe I'm missing something really silly from the docs? I would assume no commands would be executed with cli arguments missing. If I run the program with a malformed argument, it fails during parsing, and the glossary/index of commands pops up. I would assume this would be the case when there are no command line arguments are specified as well.

This is what I would think would popup when args(string[] args in a top-level statement based project) is empty:
![image](https://user-images.githubusercontent.com/55720292/210502891-d8b9c4f2-0e5a-48fe-beba-4c6c39387bb2.png)

Also, what is the reason handlers cannot be bound to Options themselves? That code is kind of smelly to me. Even if there is - obvious - internal binding of handlers to options in a command, they're just Action/Action<T>'s. RootCommand could just grab that from the Option<T> from it. Then it could just be a constructor argument or propety on an Option itself. Much more clean IMO. The code above now becomes:

```cs
using System.CommandLine;
using Stacks.Parsing;

await new RootCommand()
{
new Option(
aliases: new string[] { "--main", "-m" },
description: "path to stacks main sdl file",
handler: MainArgumentHandler)
}
.InvokeAsync(args);

Console.ReadKey();

void MainArgumentHandler(string path)
{
new Parser(path).TryParse(out var appModel);
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.