mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-05-04 08:32:52 +08:00
146 lines
4.9 KiB
C#
146 lines
4.9 KiB
C#
namespace Spectre.Console.Cli;
|
|
|
|
internal static class TemplateParser
|
|
{
|
|
public sealed class ArgumentResult
|
|
{
|
|
public string Value { get; set; }
|
|
public bool Required { get; set; }
|
|
|
|
public ArgumentResult(string value, bool required)
|
|
{
|
|
Value = value;
|
|
Required = required;
|
|
}
|
|
}
|
|
|
|
public sealed class OptionResult
|
|
{
|
|
public List<string> LongNames { get; set; }
|
|
public List<string> ShortNames { get; set; }
|
|
public string? Value { get; set; }
|
|
public bool ValueIsOptional { get; set; }
|
|
|
|
public OptionResult()
|
|
{
|
|
ShortNames = new List<string>();
|
|
LongNames = new List<string>();
|
|
}
|
|
}
|
|
|
|
public static ArgumentResult ParseArgumentTemplate(string template)
|
|
{
|
|
var valueName = default(string);
|
|
var required = false;
|
|
foreach (var token in TemplateTokenizer.Tokenize(template))
|
|
{
|
|
if (token.TokenKind == TemplateToken.Kind.ShortName ||
|
|
token.TokenKind == TemplateToken.Kind.LongName)
|
|
{
|
|
throw CommandTemplateException.ArgumentCannotContainOptions(template, token);
|
|
}
|
|
|
|
if (token.TokenKind == TemplateToken.Kind.OptionalValue ||
|
|
token.TokenKind == TemplateToken.Kind.RequiredValue)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(valueName))
|
|
{
|
|
throw CommandTemplateException.MultipleValuesAreNotSupported(template, token);
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(token.Value))
|
|
{
|
|
throw CommandTemplateException.ValuesMustHaveName(template, token);
|
|
}
|
|
|
|
valueName = token.Value;
|
|
required = token.TokenKind == TemplateToken.Kind.RequiredValue;
|
|
}
|
|
}
|
|
|
|
if (valueName == null)
|
|
{
|
|
throw CommandTemplateException.ArgumentsMustHaveValueName(template);
|
|
}
|
|
|
|
return new ArgumentResult(valueName, required);
|
|
}
|
|
|
|
public static OptionResult ParseOptionTemplate(string template)
|
|
{
|
|
var result = new OptionResult();
|
|
|
|
foreach (var token in TemplateTokenizer.Tokenize(template))
|
|
{
|
|
if (token.TokenKind == TemplateToken.Kind.LongName || token.TokenKind == TemplateToken.Kind.ShortName)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(token.Value))
|
|
{
|
|
throw CommandTemplateException.OptionsMustHaveName(template, token);
|
|
}
|
|
|
|
if (char.IsDigit(token.Value[0]))
|
|
{
|
|
throw CommandTemplateException.OptionNamesCannotStartWithDigit(template, token);
|
|
}
|
|
|
|
foreach (var character in token.Value)
|
|
{
|
|
if (!char.IsLetterOrDigit(character) && character != '-' && character != '_')
|
|
{
|
|
throw CommandTemplateException.InvalidCharacterInOptionName(template, token, character);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (token.TokenKind == TemplateToken.Kind.LongName)
|
|
{
|
|
if (token.Value.Length == 1)
|
|
{
|
|
throw CommandTemplateException.LongOptionMustHaveMoreThanOneCharacter(template, token);
|
|
}
|
|
|
|
result.LongNames.Add(token.Value);
|
|
}
|
|
|
|
if (token.TokenKind == TemplateToken.Kind.ShortName)
|
|
{
|
|
if (token.Value.Length > 1)
|
|
{
|
|
throw CommandTemplateException.ShortOptionMustOnlyBeOneCharacter(template, token);
|
|
}
|
|
|
|
result.ShortNames.Add(token.Value);
|
|
}
|
|
|
|
if (token.TokenKind == TemplateToken.Kind.RequiredValue ||
|
|
token.TokenKind == TemplateToken.Kind.OptionalValue)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(result.Value))
|
|
{
|
|
throw CommandTemplateException.MultipleOptionValuesAreNotSupported(template, token);
|
|
}
|
|
|
|
foreach (var character in token.Value)
|
|
{
|
|
if (!char.IsLetterOrDigit(character) &&
|
|
character != '=' && character != '-' && character != '_' && character != '|')
|
|
{
|
|
throw CommandTemplateException.InvalidCharacterInValueName(template, token, character);
|
|
}
|
|
}
|
|
|
|
result.Value = token.Value.ToUpperInvariant();
|
|
result.ValueIsOptional = token.TokenKind == TemplateToken.Kind.OptionalValue;
|
|
}
|
|
}
|
|
|
|
if (result.LongNames.Count == 0 &&
|
|
result.ShortNames.Count == 0)
|
|
{
|
|
throw CommandTemplateException.MissingLongAndShortName(template, null);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
} |