Enhance CommandLine
- Allow CommandLineApplication to handle .rsp files. - Allow CommandOption to handle MultilpeValue options that have "..." at the end of their template. - Allow CommandOption to handle boolean values with explicit or null values.
This commit is contained in:
parent
44483ddc98
commit
6fa3a8132e
3 changed files with 84 additions and 3 deletions
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -42,6 +43,7 @@ namespace Microsoft.DotNet.Cli.CommandLine
|
|||
public Func<string> LongVersionGetter { get; set; }
|
||||
public Func<string> ShortVersionGetter { get; set; }
|
||||
public List<CommandLineApplication> Commands { get; private set; }
|
||||
public bool HandleResponseFiles { get; set; }
|
||||
|
||||
public CommandLineApplication Command(string name, Action<CommandLineApplication> configuration,
|
||||
bool throwOnUnexpectedArg = true)
|
||||
|
@ -102,6 +104,11 @@ namespace Microsoft.DotNet.Cli.CommandLine
|
|||
CommandOption option = null;
|
||||
IEnumerator<CommandArgument> arguments = null;
|
||||
|
||||
if (HandleResponseFiles)
|
||||
{
|
||||
args = ExpandResponseFiles(args).ToArray();
|
||||
}
|
||||
|
||||
for (var index = 0; index < args.Length; index++)
|
||||
{
|
||||
var arg = args[index];
|
||||
|
@ -151,7 +158,7 @@ namespace Microsoft.DotNet.Cli.CommandLine
|
|||
}
|
||||
option = null;
|
||||
}
|
||||
else if (option.OptionType == CommandOptionType.NoValue)
|
||||
else if (option.OptionType == CommandOptionType.NoValue || option.OptionType == CommandOptionType.BoolValue)
|
||||
{
|
||||
// No value is needed for this option
|
||||
option.TryParse(null);
|
||||
|
@ -196,7 +203,7 @@ namespace Microsoft.DotNet.Cli.CommandLine
|
|||
}
|
||||
option = null;
|
||||
}
|
||||
else if (option.OptionType == CommandOptionType.NoValue)
|
||||
else if (option.OptionType == CommandOptionType.NoValue || option.OptionType == CommandOptionType.BoolValue)
|
||||
{
|
||||
// No value is needed for this option
|
||||
option.TryParse(null);
|
||||
|
@ -479,6 +486,50 @@ namespace Microsoft.DotNet.Cli.CommandLine
|
|||
}
|
||||
}
|
||||
|
||||
private IEnumerable<string> ExpandResponseFiles(IEnumerable<string> args)
|
||||
{
|
||||
foreach (var arg in args)
|
||||
{
|
||||
if (!arg.StartsWith("@", StringComparison.Ordinal))
|
||||
{
|
||||
yield return arg;
|
||||
}
|
||||
else
|
||||
{
|
||||
var fileName = arg.Substring(1);
|
||||
|
||||
var responseFileArguments = ParseResponseFile(fileName);
|
||||
|
||||
// ParseResponseFile can suppress expanding this response file by
|
||||
// returning null. In that case, we'll treat the response
|
||||
// file token as a regular argument.
|
||||
|
||||
if (responseFileArguments == null)
|
||||
{
|
||||
yield return arg;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var responseFileArgument in responseFileArguments)
|
||||
yield return responseFileArgument.Trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<string> ParseResponseFile(string fileName)
|
||||
{
|
||||
if (!HandleResponseFiles)
|
||||
return null;
|
||||
|
||||
if (!File.Exists(fileName))
|
||||
{
|
||||
throw new InvalidOperationException($"Response file '{fileName}' doesn't exist.");
|
||||
}
|
||||
|
||||
return File.ReadLines(fileName);
|
||||
}
|
||||
|
||||
private class CommandArgumentEnumerator : IEnumerator<CommandArgument>
|
||||
{
|
||||
private readonly IEnumerator<CommandArgument> _enumerator;
|
||||
|
|
|
@ -39,8 +39,12 @@ namespace Microsoft.DotNet.Cli.CommandLine
|
|||
{
|
||||
ValueName = part.Substring(1, part.Length - 2);
|
||||
}
|
||||
else
|
||||
else if (optionType == CommandOptionType.MultipleValue && part.StartsWith("<") && part.EndsWith(">..."))
|
||||
{
|
||||
ValueName = part.Substring(1, part.Length - 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Invalid template pattern '{template}'", nameof(template));
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +62,7 @@ namespace Microsoft.DotNet.Cli.CommandLine
|
|||
public string ValueName { get; set; }
|
||||
public string Description { get; set; }
|
||||
public List<string> Values { get; private set; }
|
||||
public bool? BoolValue { get; private set; }
|
||||
public CommandOptionType OptionType { get; private set; }
|
||||
|
||||
public bool TryParse(string value)
|
||||
|
@ -74,6 +79,30 @@ namespace Microsoft.DotNet.Cli.CommandLine
|
|||
}
|
||||
Values.Add(value);
|
||||
break;
|
||||
case CommandOptionType.BoolValue:
|
||||
if (Values.Any())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
// add null to indicate that the option was present, but had no value
|
||||
Values.Add(null);
|
||||
BoolValue = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool boolValue;
|
||||
if (!bool.TryParse(value, out boolValue))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Values.Add(value);
|
||||
BoolValue = boolValue;
|
||||
}
|
||||
break;
|
||||
case CommandOptionType.NoValue:
|
||||
if (value != null)
|
||||
{
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace Microsoft.DotNet.Cli.CommandLine
|
|||
{
|
||||
MultipleValue,
|
||||
SingleValue,
|
||||
BoolValue,
|
||||
NoValue
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue