-
Notifications
You must be signed in to change notification settings - Fork 431
Expand file tree
/
Copy pathOption.cs
More file actions
162 lines (140 loc) · 6.32 KB
/
Copy pathOption.cs
File metadata and controls
162 lines (140 loc) · 6.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.CommandLine.Completions;
using System.CommandLine.Invocation;
using System.CommandLine.Parsing;
using System.Linq;
namespace System.CommandLine
{
/// <summary>
/// A symbol defining a named parameter and a value for that parameter.
/// </summary>
public abstract class Option : Symbol
{
internal AliasSet? _aliases;
private List<Action<OptionResult>>? _validators;
/// <summary>
/// Initializes a new instance of the <see cref="Option"/> class.
/// </summary>
/// <param name="name">The name of the option. This is used during parsing and is displayed in help.</param>
/// <param name="aliases">Optional aliases by which the option can be specified on the command line.</param>
protected Option(string name, string[] aliases) : base(name)
{
if (aliases is { Length: > 0 })
{
_aliases = new(aliases);
}
}
/// <summary>
/// Gets the <see cref="Argument">argument</see> for the option.
/// </summary>
internal abstract Argument Argument { get; }
/// <summary>
/// Specifies if a default value is defined for the option.
/// </summary>
public bool HasDefaultValue => Argument.HasDefaultValue;
/// <summary>
/// Gets or sets the placeholder name shown in usage help for the option's value.
/// The value will be wrapped in angle brackets (<c><</c> and <c>></c>).
/// </summary>
/// <remarks>
/// If <c>null</c>, the <see cref="Symbol.Name"/> of the option will be used,
/// with leading dashes and slashes removed.
/// </remarks>
/// <example>
/// An option with <see cref="Symbol.Name"/> of <c>--option</c> and a
/// <see cref="HelpName"/> of <c>Value</c> will be shown in usage help as:
/// <c>--option <Value></c>. If <see cref="HelpName"/> is not set,
/// help output will show: <c>--option <option></c>.
/// </example>
/// <value>
/// The name to show as the placeholder for the option's value.
/// </value>
public string? HelpName
{
get => Argument.HelpName;
set => Argument.HelpName = value;
}
/// <summary>
/// Gets or sets the arity of the option.
/// </summary>
public ArgumentArity Arity
{
get => Argument.Arity;
set => Argument.Arity = value;
}
/// <summary>
/// When set to true, this option will be applied to its immediate parent command or commands and recursively to their subcommands.
/// </summary>
public bool Recursive { get; set; }
/// <summary>
/// Gets the <see cref="Type" /> that the option's parsed tokens will be converted to.
/// </summary>
public abstract Type ValueType { get; }
/// <summary>
/// Validators that will be called when the option is matched by the parser.
/// </summary>
public List<Action<OptionResult>> Validators => _validators ??= new();
internal bool HasValidators => _validators is not null && _validators.Count > 0;
/// <summary>
/// Gets the list of completion sources for the option.
/// </summary>
public List<Func<CompletionContext, IEnumerable<CompletionItem>>> CompletionSources => Argument.CompletionSources;
/// <summary>
/// Gets a value that indicates whether multiple argument tokens are allowed for each option identifier token.
/// </summary>
/// <example>
/// If set to <see langword="true"/>, the following command line is valid for passing multiple arguments:
/// <code>
/// > --opt 1 2 3
/// </code>
/// The following is equivalent and is always valid:
/// <code>
/// > --opt 1 --opt 2 --opt 3
/// </code>
/// </example>
public bool AllowMultipleArgumentsPerToken { get; set; }
internal virtual bool Greedy
=> Argument.Arity.MinimumNumberOfValues > 0 && Argument.ValueType != typeof(bool);
/// <summary>
/// Indicates whether the option is required when its parent command is invoked.
/// </summary>
/// <remarks>When an option is required and its parent command is invoked without it, an error results.</remarks>
public bool Required { get; set; }
/// <summary>
/// Gets the unique set of strings that can be used on the command line to specify the Option.
/// </summary>
/// <remarks>The collection does not contain the <see cref="Symbol.Name"/> of the Option.</remarks>
public ICollection<string> Aliases => _aliases ??= new();
/// <summary>
/// Gets or sets the <see cref="CommandLineAction"/> for the Option. The handler represents the action
/// that will be performed when the Option is invoked.
/// </summary>
public virtual CommandLineAction? Action { get; set; }
/// <inheritdoc />
public override IEnumerable<CompletionItem> GetCompletions(CompletionContext context)
{
List<CompletionItem>? completions = null;
foreach (var completion in Argument.GetCompletions(context))
{
if (completion.Label.ContainsCaseInsensitive(context.WordToComplete))
{
(completions ??= new List<CompletionItem>()).Add(completion);
}
}
if (completions is null)
{
return Array.Empty<CompletionItem>();
}
return completions
.OrderBy(item => item.SortText.IndexOfCaseInsensitive(context.WordToComplete))
.ThenBy(symbol => symbol.Label, StringComparer.OrdinalIgnoreCase);
}
/// <summary>
/// Gets the default value for the option.
/// </summary>
/// <returns>Returns the default value for the option, if defined. Null otherwise.</returns>
public object? GetDefaultValue() => Argument.GetDefaultValue();
}
}