Skip to content

Commit f57c56e

Browse files
committed
Update CommandLineParser
1 parent 44aa32c commit f57c56e

34 files changed

+3020
-3165
lines changed

Cmdline/Action/AuthToken.cs

Lines changed: 139 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -3,180 +3,190 @@
33
using Autofac;
44
using CKAN.Configuration;
55
using CommandLine;
6-
using CommandLine.Text;
7-
using log4net;
86

9-
namespace CKAN.CmdLine
7+
namespace CKAN.CmdLine.Action
108
{
119
/// <summary>
12-
/// Subcommand for managing authentication tokens
10+
/// Class for managing authentication tokens.
1311
/// </summary>
1412
public class AuthToken : ISubCommand
1513
{
16-
/// <summary>
17-
/// Initialize the subcommand
18-
/// </summary>
19-
public AuthToken() { }
14+
private GameInstanceManager _manager;
15+
private IUser _user;
2016

2117
/// <summary>
22-
/// Run the subcommand
18+
/// Run the 'authtoken' command.
2319
/// </summary>
24-
/// <param name="mgr">Manager to provide game instances</param>
25-
/// <param name="opts">Command line parameters paritally handled by parser</param>
26-
/// <param name="unparsed">Command line parameters not yet handled by parser</param>
27-
/// <returns>
28-
/// Exit code
29-
/// </returns>
30-
public int RunSubCommand(GameInstanceManager manager, CommonOptions opts, SubCommandOptions unparsed)
20+
/// <inheritdoc cref="ISubCommand.RunCommand"/>
21+
public int RunCommand(GameInstanceManager manager, object args)
3122
{
32-
string[] args = unparsed.options.ToArray();
33-
int exitCode = Exit.OK;
23+
var s = args.ToString();
24+
var opts = s.Replace(s.Substring(0, s.LastIndexOf('.') + 1), "").Split('+');
25+
26+
CommonOptions options = new CommonOptions();
27+
_user = new ConsoleUser(options.Headless);
28+
_manager = manager ?? new GameInstanceManager(_user);
29+
var exitCode = options.Handle(_manager, _user);
30+
31+
if (exitCode != Exit.Ok)
32+
return exitCode;
3433

35-
Parser.Default.ParseArgumentsStrict(args, new AuthTokenSubOptions(), (string option, object suboptions) =>
34+
switch (opts[1])
3635
{
37-
if (!string.IsNullOrEmpty(option) && suboptions != null)
38-
{
39-
CommonOptions options = (CommonOptions)suboptions;
40-
options.Merge(opts);
41-
user = new ConsoleUser(options.Headless);
42-
if (manager == null)
43-
{
44-
manager = new GameInstanceManager(user);
45-
}
46-
exitCode = options.Handle(manager, user);
47-
if (exitCode == Exit.OK)
48-
{
49-
switch (option)
50-
{
51-
case "list":
52-
exitCode = listAuthTokens(options);
53-
break;
54-
case "add":
55-
exitCode = addAuthToken((AddAuthTokenOptions)options);
56-
break;
57-
case "remove":
58-
exitCode = removeAuthToken((RemoveAuthTokenOptions)options);
59-
break;
60-
}
61-
}
62-
}
63-
}, () => { exitCode = MainClass.AfterHelp(); });
36+
case "AddAuthToken":
37+
exitCode = AddAuthToken(args);
38+
break;
39+
case "ListAuthToken":
40+
exitCode = ListAuthTokens();
41+
break;
42+
case "RemoveAuthToken":
43+
exitCode = RemoveAuthToken(args);
44+
break;
45+
default:
46+
exitCode = Exit.BadOpt;
47+
break;
48+
}
49+
6450
return exitCode;
6551
}
6652

67-
private int listAuthTokens(CommonOptions opts)
53+
/// <inheritdoc cref="ISubCommand.GetUsage"/>
54+
public string GetUsage(string prefix, string[] args)
6855
{
69-
List<string> hosts = new List<string>(ServiceLocator.Container.Resolve<IConfiguration>().GetAuthTokenHosts());
70-
if (hosts.Count > 0)
56+
if (args.Length == 1)
57+
return $"{prefix} {args[0]} <command> [options]";
58+
59+
switch (args[1])
7160
{
72-
int longestHostLen = hostHeader.Length;
73-
int longestTokenLen = tokenHeader.Length;
74-
foreach (string host in hosts)
75-
{
76-
longestHostLen = Math.Max(longestHostLen, host.Length);
77-
string token;
78-
if (ServiceLocator.Container.Resolve<IConfiguration>().TryGetAuthToken(host, out token))
79-
{
80-
longestTokenLen = Math.Max(longestTokenLen, token.Length);
81-
}
82-
}
83-
// Create format string: {0,-longestHostLen} {1,-longestTokenLen}
84-
string fmt = string.Format("{0}0,-{2}{1} {0}1,-{3}{1}",
85-
"{", "}", longestHostLen, longestTokenLen);
86-
user.RaiseMessage(fmt, hostHeader, tokenHeader);
87-
user.RaiseMessage(fmt,
88-
new string('-', longestHostLen),
89-
new string('-', longestTokenLen)
90-
);
91-
foreach (string host in hosts)
92-
{
93-
string token;
94-
if (ServiceLocator.Container.Resolve<IConfiguration>().TryGetAuthToken(host, out token))
95-
{
96-
user.RaiseMessage(fmt, host, token);
97-
}
98-
}
61+
case "add":
62+
return $"{prefix} {args[0]} {args[1]} [options] <host> <token>";
63+
case "list":
64+
return $"{prefix} {args[0]} {args[1]} [options]";
65+
case "remove":
66+
return $"{prefix} {args[0]} {args[1]} [options] <host>";
67+
default:
68+
return $"{prefix} {args[0]} <command> [options]";
9969
}
100-
return Exit.OK;
10170
}
10271

103-
private int addAuthToken(AddAuthTokenOptions opts)
72+
private int AddAuthToken(object args)
10473
{
105-
if (Uri.CheckHostName(opts.host) != UriHostNameType.Unknown)
74+
var opts = (AuthTokenOptions.AddAuthToken)args;
75+
if (opts.Host == null || opts.Token == null)
10676
{
107-
ServiceLocator.Container.Resolve<IConfiguration>().SetAuthToken(opts.host, opts.token);
77+
_user.RaiseMessage("add <host> <token> - argument(s) missing, perhaps you forgot it?");
78+
return Exit.BadOpt;
79+
}
80+
81+
if (Uri.CheckHostName(opts.Host) != UriHostNameType.Unknown)
82+
{
83+
ServiceLocator.Container.Resolve<IConfiguration>().SetAuthToken(opts.Host, opts.Token);
84+
_user.RaiseMessage("Successfully added \"{0}\".", opts.Host);
10885
}
10986
else
11087
{
111-
user.RaiseError("Invalid host name: {0}", opts.host);
88+
_user.RaiseMessage("Invalid host name.");
89+
return Exit.BadOpt;
11290
}
113-
return Exit.OK;
91+
92+
return Exit.Ok;
11493
}
11594

116-
private int removeAuthToken(RemoveAuthTokenOptions opts)
95+
private int ListAuthTokens()
11796
{
118-
ServiceLocator.Container.Resolve<IConfiguration>().SetAuthToken(opts.host, null);
119-
return Exit.OK;
120-
}
97+
const string hostHeader = "Host";
98+
const string tokenHeader = "Token";
12199

122-
private const string hostHeader = "Host";
123-
private const string tokenHeader = "Token";
100+
var hosts = new List<string>(ServiceLocator.Container.Resolve<IConfiguration>().GetAuthTokenHosts());
101+
if (hosts.Count > 0)
102+
{
103+
var hostWidth = hostHeader.Length;
104+
var tokenWidth = tokenHeader.Length;
105+
foreach (var host in hosts)
106+
{
107+
hostWidth = Math.Max(hostWidth, host.Length);
108+
if (ServiceLocator.Container.Resolve<IConfiguration>().TryGetAuthToken(host, out string token) && token != null)
109+
{
110+
tokenWidth = Math.Max(tokenWidth, token.Length);
111+
}
112+
}
124113

125-
private IUser user;
126-
private static readonly ILog log = LogManager.GetLogger(typeof(AuthToken));
127-
}
114+
_user.RaiseMessage("{0} {1}",
115+
hostHeader.PadRight(hostWidth),
116+
tokenHeader.PadRight(tokenWidth)
117+
);
128118

129-
internal class AuthTokenSubOptions : VerbCommandOptions
130-
{
131-
[VerbOption("list", HelpText = "List auth tokens")]
132-
public CommonOptions ListOptions { get; set; }
119+
_user.RaiseMessage("{0} {1}",
120+
new string('-', hostWidth),
121+
new string('-', tokenWidth)
122+
);
133123

134-
[VerbOption("add", HelpText = "Add an auth token")]
135-
public AddAuthTokenOptions AddOptions { get; set; }
124+
foreach (var host in hosts)
125+
{
126+
if (ServiceLocator.Container.Resolve<IConfiguration>().TryGetAuthToken(host, out string token))
127+
{
128+
_user.RaiseMessage("{0} {1}",
129+
host.PadRight(hostWidth),
130+
token.PadRight(tokenWidth)
131+
);
132+
}
133+
}
134+
}
136135

137-
[VerbOption("remove", HelpText = "Delete an auth token")]
138-
public RemoveAuthTokenOptions RemoveOptions { get; set; }
136+
return Exit.Ok;
137+
}
139138

140-
[HelpVerbOption]
141-
public string GetUsage(string verb)
139+
private int RemoveAuthToken(object args)
142140
{
143-
HelpText ht = HelpText.AutoBuild(this, verb);
144-
// Add a usage prefix line
145-
ht.AddPreOptionsLine(" ");
146-
if (string.IsNullOrEmpty(verb))
141+
var opts = (AuthTokenOptions.RemoveAuthToken)args;
142+
if (opts.Host == null)
147143
{
148-
ht.AddPreOptionsLine("ckan authtoken - Manage authentication tokens");
149-
ht.AddPreOptionsLine($"Usage: ckan authtoken <command> [options]");
144+
_user.RaiseMessage("remove <host> - argument missing, perhaps you forgot it?");
145+
return Exit.BadOpt;
146+
}
147+
148+
var hosts = new List<string>(ServiceLocator.Container.Resolve<IConfiguration>().GetAuthTokenHosts());
149+
if (hosts.Contains(opts.Host))
150+
{
151+
ServiceLocator.Container.Resolve<IConfiguration>().SetAuthToken(opts.Host, null);
152+
_user.RaiseMessage("Successfully removed \"{0}\".", opts.Host);
150153
}
151154
else
152155
{
153-
ht.AddPreOptionsLine("authtoken " + verb + " - " + GetDescription(verb));
154-
switch (verb)
155-
{
156-
case "add":
157-
ht.AddPreOptionsLine($"Usage: ckan authtoken {verb} [options] host token");
158-
break;
159-
case "remove":
160-
ht.AddPreOptionsLine($"Usage: ckan authtoken {verb} [options] host");
161-
break;
162-
case "list":
163-
ht.AddPreOptionsLine($"Usage: ckan authtoken {verb} [options]");
164-
break;
165-
}
156+
_user.RaiseMessage("There is no host with the name \"{0}\".", opts.Host);
157+
_user.RaiseMessage("Use 'ckan authtoken list' to view a list of hosts.");
158+
return Exit.BadOpt;
166159
}
167-
return ht;
160+
161+
return Exit.Ok;
168162
}
169163
}
170164

171-
internal class AddAuthTokenOptions : CommonOptions
165+
[Verb("authtoken", HelpText = "Manage authentication tokens")]
166+
[ChildVerbs(typeof(AddAuthToken), typeof(ListAuthToken), typeof(RemoveAuthToken))]
167+
internal class AuthTokenOptions
172168
{
173-
[ValueOption(0)] public string host { get; set; }
174-
[ValueOption(1)] public string token { get; set; }
175-
}
169+
[VerbExclude]
170+
[Verb("add", HelpText = "Add an authentication token")]
171+
internal class AddAuthToken : CommonOptions
172+
{
173+
[Value(0, MetaName = "Host", HelpText = "The host (DNS / IP) to authenticate with")]
174+
public string Host { get; set; }
176175

177-
internal class RemoveAuthTokenOptions : CommonOptions
178-
{
179-
[ValueOption(0)] public string host { get; set; }
180-
}
176+
[Value(1, MetaName = "Token", HelpText = "The token to authenticate with")]
177+
public string Token { get; set; }
178+
}
179+
180+
[VerbExclude]
181+
[Verb("list", HelpText = "List authentication tokens")]
182+
internal class ListAuthToken : CommonOptions { }
181183

184+
[VerbExclude]
185+
[Verb("remove", HelpText = "Remove an authentication token")]
186+
internal class RemoveAuthToken : CommonOptions
187+
{
188+
[Value(0, MetaName = "Host", HelpText = "The host (DNS / IP) to remove")]
189+
public string Host { get; set; }
190+
}
191+
}
182192
}

Cmdline/Action/Available.cs

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,62 @@
11
using System.Linq;
2-
using System.Collections.Generic;
2+
using CommandLine;
33

4-
namespace CKAN.CmdLine
4+
namespace CKAN.CmdLine.Action
55
{
6+
/// <summary>
7+
/// Class for listing the available mods.
8+
/// </summary>
69
public class Available : ICommand
710
{
8-
public IUser user { get; set; }
11+
private readonly IUser _user;
912

13+
/// <summary>
14+
/// Initializes a new instance of the <see cref="CKAN.CmdLine.Action.Available"/> class.
15+
/// </summary>
16+
/// <param name="user">The current <see cref="CKAN.IUser"/> to raise messages to the user.</param>
1017
public Available(IUser user)
1118
{
12-
this.user = user;
19+
_user = user;
1320
}
1421

15-
public int RunCommand(CKAN.GameInstance ksp, object raw_options)
22+
/// <summary>
23+
/// Run the 'available' command.
24+
/// </summary>
25+
/// <inheritdoc cref="ICommand.RunCommand"/>
26+
public int RunCommand(CKAN.GameInstance inst, object args)
1627
{
17-
AvailableOptions opts = (AvailableOptions)raw_options;
18-
IRegistryQuerier registry = RegistryManager.Instance(ksp).registry;
19-
28+
var opts = (AvailableOptions)args;
29+
IRegistryQuerier registry = RegistryManager.Instance(inst).registry;
30+
2031
var compatible = registry
21-
.CompatibleModules(ksp.VersionCriteria())
32+
.CompatibleModules(inst.VersionCriteria())
2233
.Where(m => !m.IsDLC);
2334

24-
user.RaiseMessage("Modules compatible with KSP {0}", ksp.Version());
25-
user.RaiseMessage("");
35+
_user.RaiseMessage("Mods compatible with {0} {1}\r\n", inst.game.ShortName, inst.Version());
2636

27-
if (opts.detail)
37+
if (opts.Detail)
2838
{
29-
foreach (CkanModule module in compatible)
39+
foreach (var module in compatible)
3040
{
31-
user.RaiseMessage("* {0} ({1}) - {2} - {3}", module.identifier, module.version, module.name, module.@abstract);
41+
_user.RaiseMessage("* {0} ({1}) - {2} - {3}", module.identifier, module.version, module.name, module.@abstract);
3242
}
3343
}
3444
else
3545
{
36-
foreach (CkanModule module in compatible)
46+
foreach (var module in compatible)
3747
{
38-
user.RaiseMessage("* {0} ({1}) - {2}", module.identifier, module.version, module.name);
48+
_user.RaiseMessage("* {0} ({1}) - {2}", module.identifier, module.version, module.name);
3949
}
4050
}
4151

42-
return Exit.OK;
52+
return Exit.Ok;
4353
}
4454
}
55+
56+
[Verb("available", HelpText = "List available mods")]
57+
internal class AvailableOptions : InstanceSpecificOptions
58+
{
59+
[Option("detail", HelpText = "Shows a short description of each mod")]
60+
public bool Detail { get; set; }
61+
}
4562
}

0 commit comments

Comments
 (0)