-
Notifications
You must be signed in to change notification settings - Fork 44
HelpView should include the Suggestions #78
Comments
@xyting, would you mind giving an example? |
I use following code: public static class ToolsParser
{
public static Parser Instance = new Parser(
options: ToolsCommand());
private static Command ToolsCommand() =>
Command("codegen",
"Generate EF/EF Core/Dapper code from database",
Option("-c|--connectionstring",
"Specify which database reverse engineering.",
ExactlyOneArgument()
.With(name: "CONNECTIONSTRING")),
Option("-t|--target",
"Specify which type code to generate. Allowed vaues are ef, efcore, dapper",
ExactlyOneArgument()
.With(defaultValue: () => "ef")
.WithSuggestionsFrom("ef",
"efcore",
"dapper")
.With(name: "TARGET")),
Option("-o|--output",
"Output directory in which to place the generated code.",
ExactlyOneArgument()
.With(name: "OUTPUT_DIR")),
HelpOption());
private static Option HelpOption() =>
Option("-h|--help",
"Show help information",
NoArguments());
}
class Program
{
static int Main(string[] args)
{
var parseResult = ToolsParser.Instance.Parse(args);
#if DEBUG
Console.WriteLine(parseResult.Diagram());
#endif
var appliedOptions = parseResult["codegen"];
if (appliedOptions.HasOption("help"))
{
Console.WriteLine(parseResult.Command().HelpView());
return 0;
}
}
} The help View show: Usage: codegen [options]
Options:
-c, --connectionstring <CONNECTIONSTRING> Specify which database reverse engineering.
-t, --target <TARGET> Specify which type code to generate. Allowed vaues are ef, efcore, dapper
-o, --output <OUTPUT_DIR> Output directory in which to place the generated code.
-h, --help Show help information But I want the help view to show the |
This is currently supported, but not via Option("-t|--target",
"Specify which type code to generate. Allowed vaues are ef, efcore, dapper",
ExactlyOneArgument()
.With(defaultValue: () => "ef")
.WithSuggestionsFrom("ef",
"efcore",
"dapper") to this: Option("-t|--target",
"Specify which type code to generate. Allowed vaues are ef, efcore, dapper",
AnyOneOf("ef",
"efcore",
"dapper")
.With(defaultValue: () => "ef") then the help output will be:
|
I had change to your suggested code, but the help output have not any changed. I want the I want the help will be: Usage: codegen [options]
Options:
-c, --connectionstring <CONNECTIONSTRING> Specify which database reverse engineering.
-t, --target <TARGET> Specify which type code to generate. The allowed vaues are ef, efcore, dapper (ef, efcore, dapper are generated from AnyOneOf)
-o, --output <OUTPUT_DIR> Output directory in which to place the generated code.
-h, --help Show help information |
Apologies, I confused the validation error messages (which do show the allowed values when you use As for what the help output should look like, something like this would be easier to make consistent and more localization-friendly:
As I mentioned above, this would show up for Thoughts? |
@jonsequitur Thanks. I see, the output look like following will be better.
But, the options maybe more than 3/4...10 items, so, the |
I like the compact display of the options. For when there are a lot of options, which would make the page wide, perhaps a display like we're using in dotnet/templating would be desirable - like for the
But we have a lot of highly customized output display going on there, so this might be overkill for the general case. |
I've implemented an extension to this where it'll automatically include short and long options based on an enum.
I have a few helper methods: public static class EnumOption
{
internal static Option Create<TEnum>(string alias, string help, bool allowFirstChar = true)
{
var values = GetEnumOptionValues(typeof(TEnum), allowFirstChar).ToArray();
var enumHelp = GetEnumHelpText(typeof(TEnum), allowFirstChar);
return Option(alias, help + enumHelp, AnyOneOf(values));
}
internal static IEnumerable<string> GetEnumOptionValues(Type enumType, bool allowFirstChar)
{
var names = Enum.GetNames(enumType).Select(n => n.ToLowerInvariant());
var letters = new Dictionary<char, bool>();
foreach (var name in names)
{
yield return name;
if (allowFirstChar)
{
var letter = name[0];
if (!letters.ContainsKey(letter))
{
letters.Add(letter, true);
yield return letter.ToString();
}
else
{
throw new ArgumentException(
"Cannot create enum-based option with allowFirstChar unless " +
"all enum names start with a unique character.",
nameof(allowFirstChar));
}
}
}
}
internal static string GetEnumHelpText(Type enumType, bool allowFirstChar)
{
var names = Enum.GetNames(enumType).Select(n => n.ToLowerInvariant());
return " Allowed values are: " + String.Join(", ",
names.Select(n => allowFirstChar
? n.Insert(1, "[").Insert(n.Length + 1, "]")
: n));
}
internal static TEnum Parse<TEnum>(AppliedOption option)
{
var names = Enum.GetNames(typeof(TEnum));
var value = option.Value<string>();
if (value != null && value.Length == 1)
{
// first char
var name = names.FirstOrDefault(n => n.ToLowerInvariant().StartsWith(value));
if (name != null)
{
return (TEnum) Enum.Parse(typeof(TEnum), name);
}
}
else if (value != null && value.Length > 1)
{
var name = names.FirstOrDefault(n => n.ToLowerInvariant() == value);
if (name != null)
{
return (TEnum) Enum.Parse(typeof(TEnum), name);
}
}
throw new ArgumentException(
$"Could not parse enum '{typeof(TEnum)}' " +
$"for option '{option.Name}' with value '{value}'",
nameof(option));
}
} You can use it like this: public static Option VerbosityOption =>
EnumOption.Create<VerbosityLevel>("-v|--verbosity", "Set the verbosity level of the command.")
// accessing value
if (command.HasOption(CommonOptions.VerbosityOption.Name))
{
var level = EnumOption.Parse<VerbosityLevel>(
command[CommonOptions.VerbosityOption.Name]);
} @jonsequitur @seancpeters your ideas would work great, the main thing I'd like is Enum support which I had to add myself and the shortened name support. So with the help text as an argument:
|
If one command have options with suggenstions, the help view should output the suggestions. Or I lost something?
The text was updated successfully, but these errors were encountered: