Skip to content

Commit

Permalink
Update CommandLineParser
Browse files Browse the repository at this point in the history
  • Loading branch information
Olympic1 committed Aug 6, 2020
1 parent a0858d6 commit d2f844a
Show file tree
Hide file tree
Showing 34 changed files with 2,993 additions and 3,116 deletions.
268 changes: 139 additions & 129 deletions Cmdline/Action/AuthToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,180 +3,190 @@
using Autofac;
using CKAN.Configuration;
using CommandLine;
using CommandLine.Text;
using log4net;

namespace CKAN.CmdLine
namespace CKAN.CmdLine.Action
{
/// <summary>
/// Subcommand for managing authentication tokens
/// Class for managing authentication tokens.
/// </summary>
public class AuthToken : ISubCommand
{
/// <summary>
/// Initialize the subcommand
/// </summary>
public AuthToken() { }
private KSPManager _manager;
private IUser _user;

/// <summary>
/// Run the subcommand
/// Run the 'authtoken' command.
/// </summary>
/// <param name="mgr">Manager to provide game instances</param>
/// <param name="opts">Command line parameters paritally handled by parser</param>
/// <param name="unparsed">Command line parameters not yet handled by parser</param>
/// <returns>
/// Exit code
/// </returns>
public int RunSubCommand(KSPManager manager, CommonOptions opts, SubCommandOptions unparsed)
/// <inheritdoc cref="ISubCommand.RunCommand"/>
public int RunCommand(KSPManager manager, object args)
{
string[] args = unparsed.options.ToArray();
int exitCode = Exit.OK;
var s = args.ToString();
var opts = s.Replace(s.Substring(0, s.LastIndexOf('.') + 1), "").Split('+');

CommonOptions options = new CommonOptions();
_user = new ConsoleUser(options.Headless);
_manager = manager ?? new KSPManager(_user);
var exitCode = options.Handle(_manager, _user);

if (exitCode != Exit.Ok)
return exitCode;

Parser.Default.ParseArgumentsStrict(args, new AuthTokenSubOptions(), (string option, object suboptions) =>
switch (opts[1])
{
if (!string.IsNullOrEmpty(option) && suboptions != null)
{
CommonOptions options = (CommonOptions)suboptions;
options.Merge(opts);
user = new ConsoleUser(options.Headless);
if (manager == null)
{
manager = new KSPManager(user);
}
exitCode = options.Handle(manager, user);
if (exitCode == Exit.OK)
{
switch (option)
{
case "list":
exitCode = listAuthTokens(options);
break;
case "add":
exitCode = addAuthToken((AddAuthTokenOptions)options);
break;
case "remove":
exitCode = removeAuthToken((RemoveAuthTokenOptions)options);
break;
}
}
}
}, () => { exitCode = MainClass.AfterHelp(); });
case "AddAuthToken":
exitCode = AddAuthToken(args);
break;
case "ListAuthToken":
exitCode = ListAuthTokens();
break;
case "RemoveAuthToken":
exitCode = RemoveAuthToken(args);
break;
default:
exitCode = Exit.BadOpt;
break;
}

return exitCode;
}

private int listAuthTokens(CommonOptions opts)
/// <inheritdoc cref="ISubCommand.GetUsage"/>
public string GetUsage(string prefix, string[] args)
{
List<string> hosts = new List<string>(ServiceLocator.Container.Resolve<IConfiguration>().GetAuthTokenHosts());
if (hosts.Count > 0)
if (args.Length == 1)
return $"{prefix} {args[0]} <command> [options]";

switch (args[1])
{
int longestHostLen = hostHeader.Length;
int longestTokenLen = tokenHeader.Length;
foreach (string host in hosts)
{
longestHostLen = Math.Max(longestHostLen, host.Length);
string token;
if (ServiceLocator.Container.Resolve<IConfiguration>().TryGetAuthToken(host, out token))
{
longestTokenLen = Math.Max(longestTokenLen, token.Length);
}
}
// Create format string: {0,-longestHostLen} {1,-longestTokenLen}
string fmt = string.Format("{0}0,-{2}{1} {0}1,-{3}{1}",
"{", "}", longestHostLen, longestTokenLen);
user.RaiseMessage(fmt, hostHeader, tokenHeader);
user.RaiseMessage(fmt,
new string('-', longestHostLen),
new string('-', longestTokenLen)
);
foreach (string host in hosts)
{
string token;
if (ServiceLocator.Container.Resolve<IConfiguration>().TryGetAuthToken(host, out token))
{
user.RaiseMessage(fmt, host, token);
}
}
case "add":
return $"{prefix} {args[0]} {args[1]} [options] <host> <token>";
case "list":
return $"{prefix} {args[0]} {args[1]} [options]";
case "remove":
return $"{prefix} {args[0]} {args[1]} [options] <host>";
default:
return $"{prefix} {args[0]} <command> [options]";
}
return Exit.OK;
}

private int addAuthToken(AddAuthTokenOptions opts)
private int AddAuthToken(object args)
{
if (Uri.CheckHostName(opts.host) != UriHostNameType.Unknown)
var opts = (AuthTokenOptions.AddAuthToken)args;
if (opts.Host == null || opts.Token == null)
{
ServiceLocator.Container.Resolve<IConfiguration>().SetAuthToken(opts.host, opts.token);
_user.RaiseMessage("add <host> <token> - argument(s) missing, perhaps you forgot it?");
return Exit.BadOpt;
}

if (Uri.CheckHostName(opts.Host) != UriHostNameType.Unknown)
{
ServiceLocator.Container.Resolve<IConfiguration>().SetAuthToken(opts.Host, opts.Token);
_user.RaiseMessage("Successfully added \"{0}\".", opts.Host);
}
else
{
user.RaiseError("Invalid host name: {0}", opts.host);
_user.RaiseMessage("Invalid host name.");
return Exit.BadOpt;
}
return Exit.OK;

return Exit.Ok;
}

private int removeAuthToken(RemoveAuthTokenOptions opts)
private int ListAuthTokens()
{
ServiceLocator.Container.Resolve<IConfiguration>().SetAuthToken(opts.host, null);
return Exit.OK;
}
const string hostHeader = "Host";
const string tokenHeader = "Token";

private const string hostHeader = "Host";
private const string tokenHeader = "Token";
var hosts = new List<string>(ServiceLocator.Container.Resolve<IConfiguration>().GetAuthTokenHosts());
if (hosts.Count > 0)
{
var hostWidth = hostHeader.Length;
var tokenWidth = tokenHeader.Length;
foreach (var host in hosts)
{
hostWidth = Math.Max(hostWidth, host.Length);
if (ServiceLocator.Container.Resolve<IConfiguration>().TryGetAuthToken(host, out string token) && token != null)
{
tokenWidth = Math.Max(tokenWidth, token.Length);
}
}

private IUser user;
private static readonly ILog log = LogManager.GetLogger(typeof(AuthToken));
}
_user.RaiseMessage("{0} {1}",
hostHeader.PadRight(hostWidth),
tokenHeader.PadRight(tokenWidth)
);

internal class AuthTokenSubOptions : VerbCommandOptions
{
[VerbOption("list", HelpText = "List auth tokens")]
public CommonOptions ListOptions { get; set; }
_user.RaiseMessage("{0} {1}",
new string('-', hostWidth),
new string('-', tokenWidth)
);

[VerbOption("add", HelpText = "Add an auth token")]
public AddAuthTokenOptions AddOptions { get; set; }
foreach (var host in hosts)
{
if (ServiceLocator.Container.Resolve<IConfiguration>().TryGetAuthToken(host, out string token))
{
_user.RaiseMessage("{0} {1}",
host.PadRight(hostWidth),
token.PadRight(tokenWidth)
);
}
}
}

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

[HelpVerbOption]
public string GetUsage(string verb)
private int RemoveAuthToken(object args)
{
HelpText ht = HelpText.AutoBuild(this, verb);
// Add a usage prefix line
ht.AddPreOptionsLine(" ");
if (string.IsNullOrEmpty(verb))
var opts = (AuthTokenOptions.RemoveAuthToken)args;
if (opts.Host == null)
{
ht.AddPreOptionsLine("ckan authtoken - Manage authentication tokens");
ht.AddPreOptionsLine($"Usage: ckan authtoken <command> [options]");
_user.RaiseMessage("remove <host> - argument missing, perhaps you forgot it?");
return Exit.BadOpt;
}

var hosts = new List<string>(ServiceLocator.Container.Resolve<IConfiguration>().GetAuthTokenHosts());
if (hosts.Contains(opts.Host))
{
ServiceLocator.Container.Resolve<IConfiguration>().SetAuthToken(opts.Host, null);
_user.RaiseMessage("Successfully removed \"{0}\".", opts.Host);
}
else
{
ht.AddPreOptionsLine("authtoken " + verb + " - " + GetDescription(verb));
switch (verb)
{
case "add":
ht.AddPreOptionsLine($"Usage: ckan authtoken {verb} [options] host token");
break;
case "remove":
ht.AddPreOptionsLine($"Usage: ckan authtoken {verb} [options] host");
break;
case "list":
ht.AddPreOptionsLine($"Usage: ckan authtoken {verb} [options]");
break;
}
_user.RaiseMessage("There is no host with the name \"{0}\".", opts.Host);
_user.RaiseMessage("Use 'ckan authtoken list' to view a list of hosts.");
return Exit.BadOpt;
}
return ht;

return Exit.Ok;
}
}

internal class AddAuthTokenOptions : CommonOptions
[Verb("authtoken", HelpText = "Manage authentication tokens")]
[ChildVerbs(typeof(AddAuthToken), typeof(ListAuthToken), typeof(RemoveAuthToken))]
internal class AuthTokenOptions
{
[ValueOption(0)] public string host { get; set; }
[ValueOption(1)] public string token { get; set; }
}
[VerbExclude]
[Verb("add", HelpText = "Add an authentication token")]
internal class AddAuthToken : CommonOptions
{
[Value(0, MetaName = "Host", HelpText = "The host (DNS / IP) to authenticate with")]
public string Host { get; set; }

internal class RemoveAuthTokenOptions : CommonOptions
{
[ValueOption(0)] public string host { get; set; }
}
[Value(1, MetaName = "Token", HelpText = "The token to authenticate with")]
public string Token { get; set; }
}

[VerbExclude]
[Verb("list", HelpText = "List authentication tokens")]
internal class ListAuthToken : CommonOptions { }

[VerbExclude]
[Verb("remove", HelpText = "Remove an authentication token")]
internal class RemoveAuthToken : CommonOptions
{
[Value(0, MetaName = "Host", HelpText = "The host (DNS / IP) to remove")]
public string Host { get; set; }
}
}
}
49 changes: 33 additions & 16 deletions Cmdline/Action/Available.cs
Original file line number Diff line number Diff line change
@@ -1,45 +1,62 @@
using System.Linq;
using System.Collections.Generic;
using CommandLine;

namespace CKAN.CmdLine
namespace CKAN.CmdLine.Action
{
/// <summary>
/// Class for listing the available mods.
/// </summary>
public class Available : ICommand
{
public IUser user { get; set; }
private readonly IUser _user;

/// <summary>
/// Initializes a new instance of the <see cref="CKAN.CmdLine.Action.Available"/> class.
/// </summary>
/// <param name="user">The current <see cref="CKAN.IUser"/> to raise messages to the user.</param>
public Available(IUser user)
{
this.user = user;
_user = user;
}

public int RunCommand(CKAN.KSP ksp, object raw_options)
/// <summary>
/// Run the 'available' command.
/// </summary>
/// <inheritdoc cref="ICommand.RunCommand"/>
public int RunCommand(CKAN.KSP ksp, object args)
{
AvailableOptions opts = (AvailableOptions)raw_options;
IRegistryQuerier registry = RegistryManager.Instance(ksp).registry;
var opts = (AvailableOptions)args;
IRegistryQuerier registry = RegistryManager.Instance(ksp).registry;

var compatible = registry
.CompatibleModules(ksp.VersionCriteria())
.Where(m => !m.IsDLC);

user.RaiseMessage("Modules compatible with KSP {0}", ksp.Version());
user.RaiseMessage("");
_user.RaiseMessage("Mods compatible with KSP {0}\r\n", ksp.Version());

if (opts.detail)
if (opts.Detail)
{
foreach (CkanModule module in compatible)
foreach (var module in compatible)
{
user.RaiseMessage("* {0} ({1}) - {2} - {3}", module.identifier, module.version, module.name, module.@abstract);
_user.RaiseMessage("* {0} ({1}) - {2} - {3}", module.identifier, module.version, module.name, module.@abstract);
}
}
else
{
foreach (CkanModule module in compatible)
foreach (var module in compatible)
{
user.RaiseMessage("* {0} ({1}) - {2}", module.identifier, module.version, module.name);
_user.RaiseMessage("* {0} ({1}) - {2}", module.identifier, module.version, module.name);
}
}

return Exit.OK;
return Exit.Ok;
}
}

[Verb("available", HelpText = "List available mods")]
internal class AvailableOptions : InstanceSpecificOptions
{
[Option("detail", HelpText = "Shows a short description of each mod")]
public bool Detail { get; set; }
}
}
Loading

0 comments on commit d2f844a

Please sign in to comment.