Skip to content

Commit fe15c5d

Browse files
committed
implement verb aliases
1 parent 4c66e5c commit fe15c5d

File tree

4 files changed

+104
-62
lines changed

4 files changed

+104
-62
lines changed

src/CommandLine/Core/InstanceChooser.cs

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,18 @@ public static ParserResult<object> Choose(
5050
{
5151
var verbs = Verb.SelectFromTypes(types);
5252
var defaultVerbs = verbs.Where(t => t.Item1.IsDefault);
53-
53+
5454
int defaultVerbCount = defaultVerbs.Count();
5555
if (defaultVerbCount > 1)
5656
return MakeNotParsed(types, new MultipleDefaultVerbsError());
5757

5858
var defaultVerb = defaultVerbCount == 1 ? defaultVerbs.First() : null;
5959

60-
Func<ParserResult<object>> choose = () =>
60+
ParserResult<object> choose()
6161
{
6262
var firstArg = arguments.First();
6363

64-
Func<string, bool> preprocCompare = command =>
64+
bool preprocCompare(string command) =>
6565
nameComparer.Equals(command, firstArg) ||
6666
nameComparer.Equals(string.Concat("--", command), firstArg);
6767

@@ -72,7 +72,7 @@ public static ParserResult<object> Choose(
7272
: (autoVersion && preprocCompare("version"))
7373
? MakeNotParsed(types, new VersionRequestedError())
7474
: MatchVerb(tokenizer, verbs, defaultVerb, arguments, nameComparer, ignoreValueCase, parsingCulture, autoHelp, autoVersion, allowMultiInstance, nonFatalErrors);
75-
};
75+
}
7676

7777
return arguments.Any()
7878
? choose()
@@ -120,21 +120,29 @@ private static ParserResult<object> MatchVerb(
120120
bool allowMultiInstance,
121121
IEnumerable<ErrorType> nonFatalErrors)
122122
{
123-
return verbs.Any(a => nameComparer.Equals(a.Item1.Name, arguments.First()))
124-
? InstanceBuilder.Build(
125-
Maybe.Just<Func<object>>(
126-
() =>
127-
verbs.Single(v => nameComparer.Equals(v.Item1.Name, arguments.First())).Item2.AutoDefault()),
128-
tokenizer,
129-
arguments.Skip(1),
130-
nameComparer,
131-
ignoreValueCase,
132-
parsingCulture,
133-
autoHelp,
134-
autoVersion,
135-
allowMultiInstance,
136-
nonFatalErrors)
137-
: MatchDefaultVerb(tokenizer, verbs, defaultVerb, arguments, nameComparer, ignoreValueCase, parsingCulture, autoHelp, autoVersion, nonFatalErrors);
123+
string firstArg = arguments.First();
124+
125+
var verbUsed = verbs.FirstOrDefault(vt =>
126+
nameComparer.Equals(vt.Item1.Name, firstArg)
127+
|| vt.Item1.Aliases.Any(alias => nameComparer.Equals(alias, firstArg))
128+
);
129+
130+
if (verbUsed == default)
131+
{
132+
return MatchDefaultVerb(tokenizer, verbs, defaultVerb, arguments, nameComparer, ignoreValueCase, parsingCulture, autoHelp, autoVersion, nonFatalErrors);
133+
}
134+
return InstanceBuilder.Build(
135+
Maybe.Just<Func<object>>(
136+
() => verbUsed.Item2.AutoDefault()),
137+
tokenizer,
138+
arguments.Skip(1),
139+
nameComparer,
140+
ignoreValueCase,
141+
parsingCulture,
142+
autoHelp,
143+
autoVersion,
144+
allowMultiInstance,
145+
nonFatalErrors);
138146
}
139147

140148
private static HelpVerbRequestedError MakeHelpVerbRequestedError(

src/CommandLine/Core/Verb.cs

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,49 +9,36 @@ namespace CommandLine.Core
99
{
1010
sealed class Verb
1111
{
12-
private readonly string name;
13-
private readonly string helpText;
14-
private readonly bool hidden;
15-
private readonly bool isDefault;
16-
17-
public Verb(string name, string helpText, bool hidden = false, bool isDefault = false)
12+
public Verb(string name, string helpText, bool hidden, bool isDefault, IEnumerable<string> aliases)
1813
{
1914
if ( string.IsNullOrWhiteSpace(name))
2015
throw new ArgumentNullException(nameof(name));
21-
this.name = name;
16+
Name = name;
2217

23-
this.helpText = helpText ?? throw new ArgumentNullException(nameof(helpText));
24-
this.hidden = hidden;
25-
this.isDefault = isDefault;
18+
HelpText = helpText ?? throw new ArgumentNullException(nameof(helpText));
19+
Hidden = hidden;
20+
IsDefault = isDefault;
21+
Aliases = aliases ?? new string[0];
2622
}
2723

28-
public string Name
29-
{
30-
get { return name; }
31-
}
24+
public string Name { get; private set; }
3225

33-
public string HelpText
34-
{
35-
get { return helpText; }
36-
}
26+
public string HelpText { get; private set; }
3727

38-
public bool Hidden
39-
{
40-
get { return hidden; }
41-
}
28+
public bool Hidden { get; private set; }
4229

43-
public bool IsDefault
44-
{
45-
get => isDefault;
46-
}
30+
public bool IsDefault { get; private set; }
31+
32+
public IEnumerable<string> Aliases { get; private set; }
4733

4834
public static Verb FromAttribute(VerbAttribute attribute)
4935
{
5036
return new Verb(
5137
attribute.Name,
5238
attribute.HelpText,
5339
attribute.Hidden,
54-
attribute.IsDefault
40+
attribute.IsDefault,
41+
attribute.Aliases
5542
);
5643
}
5744

src/CommandLine/VerbAttribute.cs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information.
22

33
using System;
4+
using System.Collections.Generic;
45

56
namespace CommandLine
67
{
@@ -9,10 +10,8 @@ namespace CommandLine
910
/// </summary>
1011
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = true)]
1112
//public sealed class VerbAttribute : Attribute
12-
public class VerbAttribute : Attribute
13+
public class VerbAttribute : Attribute
1314
{
14-
private readonly string name;
15-
private readonly bool isDefault;
1615
private Infrastructure.LocalizableAttributeProperty helpText;
1716
private Type resourceType;
1817

@@ -21,24 +20,23 @@ public class VerbAttribute : Attribute
2120
/// </summary>
2221
/// <param name="name">The long name of the verb command.</param>
2322
/// <param name="isDefault">Whether the verb is the default verb.</param>
23+
/// <param name="aliases">aliases for this verb. i.e. "move" and "mv"</param>
2424
/// <exception cref="System.ArgumentException">Thrown if <paramref name="name"/> is null, empty or whitespace and <paramref name="isDefault"/> is false.</exception>
25-
public VerbAttribute(string name, bool isDefault = false)
25+
public VerbAttribute(string name, bool isDefault = false, string[] aliases = null)
2626
{
2727
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("name");
2828

29-
this.name = name ;
30-
this.isDefault = isDefault;
29+
Name = name;
30+
IsDefault = isDefault;
3131
helpText = new Infrastructure.LocalizableAttributeProperty(nameof(HelpText));
3232
resourceType = null;
33+
Aliases = aliases ?? new string[0];
3334
}
3435

3536
/// <summary>
3637
/// Gets the verb name.
3738
/// </summary>
38-
public string Name
39-
{
40-
get { return name; }
41-
}
39+
public string Name { get; private set; }
4240

4341
/// <summary>
4442
/// Gets or sets a value indicating whether a command line verb is visible in the help text.
@@ -54,7 +52,7 @@ public bool Hidden
5452
/// </summary>
5553
public string HelpText
5654
{
57-
get => helpText.Value??string.Empty;
55+
get => helpText.Value ?? string.Empty;
5856
set => helpText.Value = value ?? throw new ArgumentNullException("value");
5957
}
6058
/// <summary>
@@ -63,15 +61,17 @@ public string HelpText
6361
public Type ResourceType
6462
{
6563
get => resourceType;
66-
set => resourceType =helpText.ResourceType = value;
64+
set => resourceType = helpText.ResourceType = value;
6765
}
6866

6967
/// <summary>
7068
/// Gets whether this verb is the default verb.
7169
/// </summary>
72-
public bool IsDefault
73-
{
74-
get => isDefault;
75-
}
70+
public bool IsDefault { get; private set; }
71+
72+
/// <summary>
73+
/// Gets or sets the aliases
74+
/// </summary>
75+
public IEnumerable<string> Aliases { get; private set; }
7676
}
7777
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System;
2+
using System.Linq;
3+
using CommandLine.Tests.Fakes;
4+
using CommandLine.Text;
5+
using FluentAssertions;
6+
using Xunit;
7+
using Xunit.Abstractions;
8+
9+
//Issue #6
10+
//Support Aliases on verbs (i.e. "move" and "mv" are the same verb).
11+
12+
namespace CommandLine.Tests.Unit
13+
{
14+
public class Issue6Tests
15+
{
16+
[Theory]
17+
[InlineData("move -a bob", typeof(AliasedVerbOption1))]
18+
[InlineData("mv -a bob", typeof(AliasedVerbOption1))]
19+
[InlineData("copy -a bob", typeof(AliasedVerbOption2))]
20+
[InlineData("cp -a bob", typeof(AliasedVerbOption2))]
21+
public void Parse_option_with_aliased_verbs(string args, Type expectedArgType)
22+
{
23+
var arguments = args.Split(' ');
24+
object options = null;
25+
var result = Parser.Default.ParseArguments<AliasedVerbOption1, AliasedVerbOption2>(arguments)
26+
.WithParsed((o) => options = o)
27+
;
28+
29+
Assert.NotNull(options);
30+
Assert.Equal(expectedArgType, options.GetType());
31+
}
32+
33+
[Verb("move", aliases:new string[] { "mv" })]
34+
public class AliasedVerbOption1
35+
{
36+
[Option('a', "alpha", Required = true)]
37+
public string Option { get; set; }
38+
}
39+
40+
[Verb("copy", aliases: new string[] { "cp" })]
41+
public class AliasedVerbOption2
42+
{
43+
[Option('a', "alpha", Required = true)]
44+
public string Option { get; set; }
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)