Open daryl-williams opened 1 year ago
This should be an Argument<FileInfo[]>
(or CliArgument<FileInfo[]>
if you're using the nightlies), but it could also be a string[]
, etc - 'accumulate multiple arguments' part comes from the fact that you should declare the type of the argument as an array/list/etc instead of just a single item.
Hi @baronfel,
Thank you for your very quick reply. So if I understand correctly I should be able to declare something like the following:
var inputFileOption = new Argument<FileInfo[]?> (new[] { "--input_file" }, description: "One or more image filename(s) to work on: image_file1 image_file2 ...", getDefaultValue: () => { return ""; });
is that right? I get confused sometimes as there seem to be different ways to define options and I not yet seen an example using Argument
Thanks again for your help.
Daryl
Yep! That should work well. Here's a simple example that I did in F# Interactive:
> let fileArg = Argument<FileInfo[]>("--input_file");;
val fileArg: Argument<FileInfo array> = Argument: --input_file
> fileArg.Parse([| "file1"; "file2"; "file3"; |]);;
val it: ParseResult =
ParseResult: [ fsi <file1> <file2> <file3> ]
{CommandResult = RootCommandResult: fsi file1 file2 file3;
Directives = seq [];
Errors = seq [];
Parser = System.CommandLine.Parsing.Parser;
RootCommandResult = RootCommandResult: fsi file1 file2 file3;
Tokens = [|file1; file2; file3|];
UnmatchedTokens = [||];
UnparsedTokens = [||];}
> it.GetValueForArgument(fileArg);;
val it: FileInfo array =
[|file1 {Attributes = -1;
CreationTime = 12/31/1600 6:00:00 PM;
CreationTimeUtc = 1/1/1601 12:00:00 AM;
Directory = D:\Code\dotnet-docs;
DirectoryName = "D:\Code\dotnet-docs";
Exists = false;
Extension = "";
FullName = "D:\Code\dotnet-docs\file1";
IsReadOnly = true;
LastAccessTime = 12/31/1600 6:00:00 PM;
LastAccessTimeUtc = 1/1/1601 12:00:00 AM;
LastWriteTime = 12/31/1600 6:00:00 PM;
LastWriteTimeUtc = 1/1/1601 12:00:00 AM;
Length = ?;
LinkTarget = null;
Name = "file1";
UnixFileMode = -1;};
file2 {Attributes = -1;
CreationTime = 12/31/1600 6:00:00 PM;
CreationTimeUtc = 1/1/1601 12:00:00 AM;
Directory = D:\Code\dotnet-docs;
DirectoryName = "D:\Code\dotnet-docs";
Exists = false;
Extension = "";
FullName = "D:\Code\dotnet-docs\file2";
IsReadOnly = true;
LastAccessTime = 12/31/1600 6:00:00 PM;
LastAccessTimeUtc = 1/1/1601 12:00:00 AM;
LastWriteTime = 12/31/1600 6:00:00 PM;
LastWriteTimeUtc = 1/1/1601 12:00:00 AM;
Length = ?;
LinkTarget = null;
Name = "file2";
UnixFileMode = -1;};
file3 {Attributes = -1;
CreationTime = 12/31/1600 6:00:00 PM;
CreationTimeUtc = 1/1/1601 12:00:00 AM;
Directory = D:\Code\dotnet-docs;
DirectoryName = "D:\Code\dotnet-docs";
Exists = false;
Extension = "";
FullName = "D:\Code\dotnet-docs\file3";
IsReadOnly = true;
LastAccessTime = 12/31/1600 6:00:00 PM;
LastAccessTimeUtc = 1/1/1601 12:00:00 AM;
LastWriteTime = 12/31/1600 6:00:00 PM;
LastWriteTimeUtc = 1/1/1601 12:00:00 AM;
Length = ?;
LinkTarget = null;
Name = "file3";
UnixFileMode = -1;}|]
You can see the definition (the important part is the FileInfo[] type definition), the parsing, and then the retrieval of the parsed values (which is a FileInfo []).
I have tried the following:
var inputFileListArg = new Argument<string[]?> (new[] {"--input_file"}, description: "One or more image filename(s) to work on: image_file1 image_file2 ...");
but get the following build error:
error CS1503: Argument 1: cannot convert from 'string[]' to 'string?'
I am trying to save the input_file args to a struct which I have struct defined as:
public struct CmdArgs { public string[]? inputFileList; }
I don't think that has anything to do with compile error, but my confidence is low when it comes to my understanding of this new environment.
Regards,
D
@daryl-williams do you have a complete sample code that we could look at to help more specifically?
I have (hopefully) attached a file below that, although edited for brevity, includes all the relevant parts I have mentioned. Thanks again for your help. If I can provide further information please let me know.
D
@daryl-williams looks like just a couple things to fix:
cmdArgs.inputFile
to cmdArgs.inputFileList
- this seems like a naming typo, that's itThat should get you compiling!
Hi @baronfel, I fixed the typo and changed the constructor to:
var inputFileListArg = new Argument<string> (new[] {"--input_file"}, description: "One or more image filename(s) to work on: image_file1 image_file2 ...");
but am still getting errors:
From the constructor declaration: error CS1503: Argument 1: cannot convert from 'string[]' to 'string?'
From the assignment to the struct (cmdArgs.inputFileList = inputFileListArg;): error CS0029: Cannot implicitly convert type 'string' to 'string[]'
D
change new[] {"--input_file"}
to just "input_file"
and you should be good to go. Here is the full gist that I was able to create: https://gist.github.com/baronfel/a8cc681437b12a2d1984c1637ec958f5
@baronfel Thank you so much for your help, I really appreciate it. I am still somewhat confused though about changing the type from string[] to string. Does mean the program can only have one input file? When I complied it gave me an error on there line where I save it to the CmdArgs.inputFileList var, which makes complete since they are now different types.
I guess I don't understand what you meant by "Arguments can't have aliases", I thought string[] is a Type? I realize I am very new to .Net and c# and have a lot to learn.
I think it's easier to explain if I show you and option and an argument side-by-side:
var outputFileOption = new Option<string?> (new[] { "--output", "-o" }, description: "Output filename or basename when passing multiple output files, i.e. outputfile-1 outputfile-2 ...", getDefaultValue: () => { return ""; });
var inputFileListArg = new Argument<string[]> ("input_file", description: "One or more image filename(s) to work on: image_file1 image_file2 ...");
These are from your code - for an Option
, the first parameter is a list of names for the option - the primary is the 'longest' name, and all other names are considered 'aliases'. This means a user could type in -o
at the terminal or --output
and get the same result.
However, Arguments
don't have a concept of aliases - they really only have one name since they can't be explicitly passed like an Option
is. This means the Argument
constructor only needs a single string. Note that this has nothing to do with the type of the argument/option - that's all covered by the generic type parameter FileInfo
when you created the argument using Argument<FileInfo>
.
I get it now, your explanation was very clear. I changed Argument type back to string[] and it compiled perfectly! Thanks again for your help, I learn as I go and this has been very helpful!
In cases where you want to control number of allowed values by the argument, Arity
property can be used:
Argument<string[]> inputFileListArg = new("input_file(s)",
description: "One or more image filename(s) to work on: image_file1 image_file2 ...")
{
Arity = ArgumentArity.OneOrMore
};
note that the API has changed in the upcoming v2, so in the future, it shape will become:
CliArgument<string[]> inputFileListArg = new("input_file(s)")
{
Description = "One or more image filename(s) to work on: image_file1 image_file2 ..."),
Arity = ArgumentArity.OneOrMore
};
Thank you Adele, I appreciate your input and information.On Aug 5, 2023, at 00:19, Adeel Mujahid @.***> wrote: In cases where you want to control number of allowed values by the argument, Arity property can be used: Argument<string[]> inputFileListArg = new("input_file(s)", description: "One or more image filename(s) to work on: image_file1 image_file2 ...") { Arity = ArgumentArity.OneOrMore }; note that the API has changed in the upcoming v2, so in the future, it shape will become: CliArgument<string[]> inputFileListArg = new("input_file(s)") { Description = "One or more image filename(s) to work on: image_file1 image_file2 ..."), Arity = ArgumentArity.OneOrMore };
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID: @.***>
Hello everyone,
I am new to .Net coming from a Unix background and I am developing a dotnet command line application that needs a couple of options, followed by a list of one or more input files, i.e:
mycmd —dpi 72 —grayscale input_file1.jpg input_file2.png
I have poured over the documentation and searched all over the web and have only been able to find examples of arguments that are part of an option, as in the —dpi 72 above. If someone could provide a simple example of how to define a standalone argument with an arity of OneOrMore or provide a link to some relevant documentation I would greatly appreciate it.
Best Regards,
Daryl