Skip to content

Commit

Permalink
Merge pull request KSP-CKAN#10 from mgsdk/select_multiple
Browse files Browse the repository at this point in the history
Support for selecting one item from a list of items
  • Loading branch information
AlexanderDzhoganov committed Jan 5, 2015
2 parents a7ab4c4 + f382455 commit e8a4e0d
Show file tree
Hide file tree
Showing 3 changed files with 222 additions and 12 deletions.
60 changes: 53 additions & 7 deletions Action/KSP.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Linq;
using CommandLine;

namespace CKAN.CmdLine
Expand Down Expand Up @@ -212,21 +213,66 @@ private int ForgetInstall(ForgetOptions options)

private int SetDefaultInstall(DefaultOptions options)
{
if (options.name == null)
string name = options.name;

if (name == null)
{
User.RaiseMessage("default <name> - argument missing, perhaps you forgot it?");
return Exit.BADOPT;
// No input argument from the user. Present a list of the possible instances.
string message = "default <name> - argument missing, please select from the list below.";

// Check if there is a default instance.
string defaultInstance = Manager.Win32Registry.AutoStartInstance;
int defaultInstancePresent = 0;

if (!String.IsNullOrWhiteSpace(defaultInstance))
{
defaultInstancePresent = 1;
}

object[] keys = new object[Manager.Instances.Count + defaultInstancePresent];

// Populate the list of instances.
for (int i = 0; i < Manager.Instances.Count; i++)
{
var instance = Manager.Instances.ElementAt(i);

keys[i + defaultInstancePresent] = String.Format("\"{0}\" - {1}", instance.Key, instance.Value.GameDir());
}

// Mark the default intance for the user.
if (!String.IsNullOrWhiteSpace(defaultInstance))
{
keys[0] = Manager.Instances.IndexOfKey(defaultInstance);
}

int result = -1;

try
{
result = User.RaiseSelectionDialog(message, keys);
}
catch (Kraken)
{
return Exit.BADOPT;
}

if (result < 0)
{
return Exit.BADOPT;
}

name = Manager.Instances.ElementAt(result).Key;
}

if (!Manager.HasInstance(options.name))
if (!Manager.Instances.ContainsKey(name))
{
User.RaiseMessage("Couldn't find install with name \"{0}\", aborting..", options.name);
User.RaiseMessage("Couldn't find install with name \"{0}\", aborting..", name);
return Exit.BADOPT;
}

Manager.SetAutoStart(options.name);
Manager.SetAutoStart(name);

User.RaiseMessage("Successfully set \"{0}\" as the default KSP installation", options.name);
User.RaiseMessage("Successfully set \"{0}\" as the default KSP installation", name);
return Exit.OK;
}
}
Expand Down
140 changes: 140 additions & 0 deletions ConsoleUser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,146 @@ protected override void DisplayError(string message, params object[] args)
Console.Error.WriteLine(message, args);
}

protected override int DisplaySelectionDialog(string message, params object[] args)
{
// Validate input.
if (String.IsNullOrWhiteSpace(message))
{
throw new Kraken("Passed message string must be non-empty.");
}

if (args.Length == 0)
{
throw new Kraken("Passed list of selection candidates must be non-empty.");
}

// Check if we have a default selection.
int defaultSelection = -1;

if (args[0] is int)
{
// Check that the default selection makes sense.
defaultSelection = (int)args[0];

if (defaultSelection < 0 || defaultSelection > args.Length - 1)
{
throw new Kraken("Passed default arguments is out of range of the selection candidates.");
}

// Extract the relevant arguments.
object[] newArgs = new object[args.Length - 1];

for (int i = 1; i < args.Length; i++)
{
newArgs[i - 1] = args[i];
}

args = newArgs;
}

// Further data validation.
foreach (object argument in args)
{
if (String.IsNullOrWhiteSpace(argument.ToString()))
{
throw new Kraken("Candidate may not be empty.");
}
}

// List options.
for (int i = 0; i < args.Length; i++)
{
string CurrentRow = String.Format("{0}", i + 1);

if (i == defaultSelection)
{
CurrentRow += "*";
}

CurrentRow += String.Format(") {0}", args[i]);

RaiseMessage(CurrentRow);
}

// Create message string.
string output = String.Format("Enter a number between {0} and {1} (To cancel press \"c\" or \"n\".", 1, args.Length);

if (defaultSelection >= 0)
{
output += String.Format(" \"Enter\" will select {0}.", defaultSelection + 1);
}

output += "): ";

RaiseMessage(output);

bool valid = false;
int result = 0;

while (!valid)
{
// Wait for input from the command line.
string input = Console.ReadLine().Trim().ToLower();

// Check for default selection.
if (String.IsNullOrEmpty(input))
{
if (defaultSelection >= 0)
{
return defaultSelection;
}
}

// Check for cancellation characters.
if (input == "c" || input == "n")
{
RaiseMessage("Selection cancelled.");

return -1;
}

// Attempt to parse the input.
try
{
result = Convert.ToInt32(input);
}
catch (FormatException)
{
RaiseMessage("The input is not a number.");
continue;
}
catch (OverflowException)
{
RaiseMessage("The number in the input is too large.");
continue;
}

// Check the input against the boundaries.
if (result > args.Length)
{
RaiseMessage("The number in the input is too large.");
RaiseMessage(output);

continue;
}
else if (result < 1)
{
RaiseMessage("The number in the input is too small.");
RaiseMessage(output);

continue;
}

// The list we provide is index 1 based, but the array is index 0 based.
result--;

// We have checked for all errors and have gotten a valid result. Stop the input loop.
valid = true;
}

return result;
}

protected override void ReportProgress(string format, int percent)
{
if (Regex.IsMatch(format, "download", RegexOptions.IgnoreCase))
Expand Down
34 changes: 29 additions & 5 deletions Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -460,16 +460,40 @@ private static int Install(InstallOptions options, CKAN.KSP current_instance, IU
}
catch (TooManyModsProvideKraken ex)
{
user.RaiseMessage("Too many mods provide {0}. Please pick from the following:\n", ex.requested);
// Request the user selects one of the mods.
string[] mods = new string[ex.modules.Count];

foreach (CkanModule mod in ex.modules)
for (int i = 0; i < ex.modules.Count; i++)
{
user.RaiseMessage("* {0} ({1})", mod.identifier, mod.name);
mods[i] = String.Format("{0} ({1})", ex.modules[i].identifier, ex.modules[i].name);
}

user.RaiseMessage(String.Empty); // Looks tidier.
string message = String.Format("Too many mods provide {0}. Please pick from the following:\n", ex.requested);

return Exit.ERROR;
int result = -1;

try
{
result = user.RaiseSelectionDialog(message, mods);
}
catch (Kraken e)
{
user.RaiseMessage(e.Message);

return Exit.ERROR;
}

if (result < 0)
{
user.RaiseMessage(String.Empty); // Looks tidier.

return Exit.ERROR;
}

// Add the module to the list.
options.modules.Add(ex.modules[result].identifier);

return Install(options, current_instance, user);
}
catch (FileExistsKraken ex)
{
Expand Down

0 comments on commit e8a4e0d

Please sign in to comment.