diff --git a/Cmdline/Action/AuthToken.cs b/Cmdline/Action/AuthToken.cs
index 5bb806fc5b..008220950d 100644
--- a/Cmdline/Action/AuthToken.cs
+++ b/Cmdline/Action/AuthToken.cs
@@ -23,7 +23,7 @@ public AuthToken() { }
///
/// Exit code
///
- public int RunSubCommand(SubCommandOptions unparsed)
+ public int RunSubCommand(KSPManager manager, CommonOptions opts, SubCommandOptions unparsed)
{
string[] args = unparsed.options.ToArray();
int exitCode = Exit.OK;
@@ -33,8 +33,12 @@ public int RunSubCommand(SubCommandOptions unparsed)
if (!string.IsNullOrEmpty(option) && suboptions != null)
{
CommonOptions options = (CommonOptions)suboptions;
+ options.Merge(opts);
user = new ConsoleUser(options.Headless);
- manager = new KSPManager(user);
+ if (manager == null)
+ {
+ manager = new KSPManager(user);
+ }
exitCode = options.Handle(manager, user);
if (exitCode == Exit.OK)
{
@@ -115,7 +119,6 @@ private int removeAuthToken(RemoveAuthTokenOptions opts)
private const string tokenHeader = "Token";
private IUser user;
- private KSPManager manager;
private static readonly ILog log = LogManager.GetLogger(typeof(AuthToken));
}
diff --git a/Cmdline/Action/CompatSubCommand.cs b/Cmdline/Action/Compat.cs
similarity index 94%
rename from Cmdline/Action/CompatSubCommand.cs
rename to Cmdline/Action/Compat.cs
index 2e066193c9..86d54a545c 100644
--- a/Cmdline/Action/CompatSubCommand.cs
+++ b/Cmdline/Action/Compat.cs
@@ -5,9 +5,9 @@
namespace CKAN.CmdLine.Action
{
- public class CompatSubCommand : ISubCommand
+ public class Compat : ISubCommand
{
- public CompatSubCommand() { }
+ public Compat() { }
public class CompatOptions : VerbCommandOptions
{
@@ -65,7 +65,7 @@ public class CompatForgetOptions : InstanceSpecificOptions
[ValueOption(0)] public string Version { get; set; }
}
- public int RunSubCommand(SubCommandOptions options)
+ public int RunSubCommand(KSPManager manager, CommonOptions opts, SubCommandOptions options)
{
var exitCode = Exit.OK;
@@ -75,9 +75,10 @@ public int RunSubCommand(SubCommandOptions options)
if (!string.IsNullOrEmpty(option) && suboptions != null)
{
CommonOptions comOpts = (CommonOptions)suboptions;
- _user = new ConsoleUser(comOpts.Headless);
- _kspManager = new KSPManager(_user);
- exitCode = comOpts.Handle(_kspManager, _user);
+ comOpts.Merge(opts);
+ _user = new ConsoleUser(comOpts.Headless);
+ _kspManager = manager ?? new KSPManager(_user);
+ exitCode = comOpts.Handle(_kspManager, _user);
if (exitCode != Exit.OK)
return;
@@ -88,7 +89,7 @@ public int RunSubCommand(SubCommandOptions options)
var ksp = MainClass.GetGameInstance(_kspManager);
const string versionHeader = "Version";
- const string actualHeader = "Actual";
+ const string actualHeader = "Actual";
var output = ksp
.GetCompatibleVersions()
@@ -196,7 +197,6 @@ public int RunSubCommand(SubCommandOptions options)
}
}
}, () => { exitCode = MainClass.AfterHelp(); });
- RegistryManager.DisposeAll();
return exitCode;
}
diff --git a/Cmdline/Action/ISubCommand.cs b/Cmdline/Action/ISubCommand.cs
index b87032b76d..27db3e41bc 100644
--- a/Cmdline/Action/ISubCommand.cs
+++ b/Cmdline/Action/ISubCommand.cs
@@ -2,7 +2,6 @@
{
internal interface ISubCommand
{
- int RunSubCommand(SubCommandOptions options);
+ int RunSubCommand(KSPManager manager, CommonOptions opts, SubCommandOptions options);
}
}
-
diff --git a/Cmdline/Action/KSP.cs b/Cmdline/Action/KSP.cs
index 58d8223d65..b158e39ee5 100644
--- a/Cmdline/Action/KSP.cs
+++ b/Cmdline/Action/KSP.cs
@@ -13,16 +13,16 @@ public KSP() { }
internal class KSPSubOptions : VerbCommandOptions
{
[VerbOption("list", HelpText = "List KSP installs")]
- public CommonOptions ListOptions { get; set; }
+ public CommonOptions ListOptions { get; set; }
[VerbOption("add", HelpText = "Add a KSP install")]
- public AddOptions AddOptions { get; set; }
+ public AddOptions AddOptions { get; set; }
[VerbOption("rename", HelpText = "Rename a KSP install")]
- public RenameOptions RenameOptions { get; set; }
+ public RenameOptions RenameOptions { get; set; }
[VerbOption("forget", HelpText = "Forget a KSP install")]
- public ForgetOptions ForgetOptions { get; set; }
+ public ForgetOptions ForgetOptions { get; set; }
[VerbOption("default", HelpText = "Set the default KSP install")]
public DefaultOptions DefaultOptions { get; set; }
@@ -94,7 +94,7 @@ internal class DefaultOptions : CommonOptions
}
// This is required by ISubCommand
- public int RunSubCommand(SubCommandOptions unparsed)
+ public int RunSubCommand(KSPManager manager, CommonOptions opts, SubCommandOptions unparsed)
{
string[] args = unparsed.options.ToArray();
@@ -123,8 +123,9 @@ public int RunSubCommand(SubCommandOptions unparsed)
if (!string.IsNullOrEmpty(option) && suboptions != null)
{
CommonOptions options = (CommonOptions)suboptions;
- User = new ConsoleUser(options.Headless);
- Manager = new KSPManager(User);
+ options.Merge(opts);
+ User = new ConsoleUser(options.Headless);
+ Manager = manager ?? new KSPManager(User);
exitCode = options.Handle(Manager, User);
if (exitCode != Exit.OK)
return;
@@ -159,7 +160,6 @@ public int RunSubCommand(SubCommandOptions unparsed)
}
}
}, () => { exitCode = MainClass.AfterHelp(); });
- RegistryManager.DisposeAll();
return exitCode;
}
diff --git a/Cmdline/Action/Prompt.cs b/Cmdline/Action/Prompt.cs
new file mode 100644
index 0000000000..205d5fda9c
--- /dev/null
+++ b/Cmdline/Action/Prompt.cs
@@ -0,0 +1,47 @@
+using System;
+using CommandLine;
+using CommandLine.Text;
+using log4net;
+
+namespace CKAN.CmdLine
+{
+
+ public class Prompt
+ {
+ public Prompt() { }
+
+ public int RunCommand(KSPManager manager, object raw_options)
+ {
+ CommonOptions opts = raw_options as CommonOptions;
+ bool done = false;
+ while (!done)
+ {
+ // Prompt if not in headless mode
+ if (!(opts?.Headless ?? false))
+ {
+ Console.Write(
+ manager.CurrentInstance != null
+ ? $"CKAN {Meta.GetVersion()}: KSP {manager.CurrentInstance.Version().ToString()} ({manager.CurrentInstance.Name})> "
+ : $"CKAN {Meta.GetVersion()}> "
+ );
+ }
+ // Get input
+ string command = Console.ReadLine();
+ if (command == null || command == exitCommand)
+ {
+ done = true;
+ }
+ else if (command != "")
+ {
+ // Parse input as if it was a normal command line,
+ // but with a persistent KSPManager object.
+ MainClass.Execute(manager, opts, command.Split(' '));
+ }
+ }
+ return Exit.OK;
+ }
+
+ private const string exitCommand = "exit";
+ }
+
+}
diff --git a/Cmdline/Action/Repair.cs b/Cmdline/Action/Repair.cs
index cc3d3eb1d1..131cd7ccd1 100644
--- a/Cmdline/Action/Repair.cs
+++ b/Cmdline/Action/Repair.cs
@@ -39,7 +39,7 @@ public string GetUsage(string verb)
}
}
- public int RunSubCommand(SubCommandOptions unparsed)
+ public int RunSubCommand(KSPManager manager, CommonOptions opts, SubCommandOptions unparsed)
{
int exitCode = Exit.OK;
// Parse and process our sub-verbs
@@ -49,8 +49,12 @@ public int RunSubCommand(SubCommandOptions unparsed)
if (!string.IsNullOrEmpty(option) && suboptions != null)
{
CommonOptions options = (CommonOptions)suboptions;
+ options.Merge(opts);
User = new ConsoleUser(options.Headless);
- KSPManager manager = new KSPManager(User);
+ if (manager == null)
+ {
+ manager = new KSPManager(User);
+ }
exitCode = options.Handle(manager, User);
if (exitCode != Exit.OK)
return;
@@ -68,7 +72,6 @@ public int RunSubCommand(SubCommandOptions unparsed)
}
}
}, () => { exitCode = MainClass.AfterHelp(); });
- RegistryManager.DisposeAll();
return exitCode;
}
@@ -79,7 +82,7 @@ public int RunSubCommand(SubCommandOptions unparsed)
///
private int Registry(CKAN.KSP ksp)
{
- var manager = RegistryManager.Instance(ksp);
+ RegistryManager manager = RegistryManager.Instance(ksp);
manager.registry.Repair();
manager.Save();
User.RaiseMessage("Registry repairs attempted. Hope it helped.");
diff --git a/Cmdline/Action/Repo.cs b/Cmdline/Action/Repo.cs
index 9e0dfb78c3..15a049370a 100644
--- a/Cmdline/Action/Repo.cs
+++ b/Cmdline/Action/Repo.cs
@@ -91,7 +91,7 @@ internal class ForgetOptions : InstanceSpecificOptions
}
// This is required by ISubCommand
- public int RunSubCommand(SubCommandOptions unparsed)
+ public int RunSubCommand(KSPManager manager, CommonOptions opts, SubCommandOptions unparsed)
{
string[] args = unparsed.options.ToArray();
@@ -118,8 +118,9 @@ public int RunSubCommand(SubCommandOptions unparsed)
if (!string.IsNullOrEmpty(option) && suboptions != null)
{
CommonOptions options = (CommonOptions)suboptions;
- User = new ConsoleUser(options.Headless);
- Manager = new KSPManager(User);
+ options.Merge(opts);
+ User = new ConsoleUser(options.Headless);
+ Manager = manager ?? new KSPManager(User);
exitCode = options.Handle(Manager, User);
if (exitCode != Exit.OK)
return;
@@ -154,7 +155,6 @@ public int RunSubCommand(SubCommandOptions unparsed)
}
}
}, () => { exitCode = MainClass.AfterHelp(); });
- RegistryManager.DisposeAll();
return exitCode;
}
diff --git a/Cmdline/CKAN-cmdline.csproj b/Cmdline/CKAN-cmdline.csproj
index b2750f681b..1392f4420f 100644
--- a/Cmdline/CKAN-cmdline.csproj
+++ b/Cmdline/CKAN-cmdline.csproj
@@ -56,7 +56,7 @@
-
+
@@ -64,6 +64,7 @@
+
diff --git a/Cmdline/Main.cs b/Cmdline/Main.cs
index 906e736bab..42ebf8d43f 100644
--- a/Cmdline/Main.cs
+++ b/Cmdline/Main.cs
@@ -56,6 +56,18 @@ public static int Main(string[] args)
return Gui(new GuiOptions(), args);
}
+ try
+ {
+ return Execute(null, null, args);
+ }
+ finally
+ {
+ RegistryManager.DisposeAll();
+ }
+ }
+
+ public static int Execute(KSPManager manager, CommonOptions opts, string[] args)
+ {
// We shouldn't instantiate Options if it's a subcommand.
// It breaks command-specific help, for starters.
try
@@ -63,19 +75,19 @@ public static int Main(string[] args)
switch (args[0])
{
case "repair":
- return (new Repair()).RunSubCommand(new SubCommandOptions(args));
+ return (new Repair()).RunSubCommand(manager, opts, new SubCommandOptions(args));
case "ksp":
- return (new KSP()).RunSubCommand(new SubCommandOptions(args));
+ return (new KSP()).RunSubCommand(manager, opts, new SubCommandOptions(args));
case "compat":
- return (new CompatSubCommand()).RunSubCommand(new SubCommandOptions(args));
+ return (new Compat()).RunSubCommand(manager, opts, new SubCommandOptions(args));
case "repo":
- return (new Repo()).RunSubCommand(new SubCommandOptions(args));
+ return (new Repo()).RunSubCommand(manager, opts, new SubCommandOptions(args));
case "authtoken":
- return (new AuthToken()).RunSubCommand(new SubCommandOptions(args));
+ return (new AuthToken()).RunSubCommand(manager, opts, new SubCommandOptions(args));
}
}
catch (NoGameInstanceKraken)
@@ -103,8 +115,16 @@ public static int Main(string[] args)
// Process commandline options.
CommonOptions options = (CommonOptions)cmdline.options;
+ options.Merge(opts);
IUser user = new ConsoleUser(options.Headless);
- KSPManager manager = new KSPManager(user);
+ if (manager == null)
+ {
+ manager = new KSPManager(user);
+ }
+ else
+ {
+ manager.User = user;
+ }
try
{
@@ -154,28 +174,31 @@ private static int RunSimpleAction(Options cmdline, CommonOptions options, strin
case "consoleui":
return ConsoleUi(options, args);
+ case "prompt":
+ return new Prompt().RunCommand(manager, cmdline.options);
+
case "version":
return Version(user);
case "update":
- return (new Update(user)).RunCommand(GetGameInstance(manager), (UpdateOptions)cmdline.options);
+ return (new Update(user)).RunCommand(GetGameInstance(manager), cmdline.options);
case "available":
- return (new Available(user)).RunCommand(GetGameInstance(manager), (AvailableOptions)cmdline.options);
+ return (new Available(user)).RunCommand(GetGameInstance(manager), cmdline.options);
case "add":
case "install":
Scan(GetGameInstance(manager), user, cmdline.action);
- return (new Install(user)).RunCommand(GetGameInstance(manager), (InstallOptions)cmdline.options);
+ return (new Install(user)).RunCommand(GetGameInstance(manager), cmdline.options);
case "scan":
return Scan(GetGameInstance(manager), user);
case "list":
- return (new List(user)).RunCommand(GetGameInstance(manager), (ListOptions)cmdline.options);
+ return (new List(user)).RunCommand(GetGameInstance(manager), cmdline.options);
case "show":
- return (new Show(user)).RunCommand(GetGameInstance(manager), (ShowOptions)cmdline.options);
+ return (new Show(user)).RunCommand(GetGameInstance(manager), cmdline.options);
case "search":
return (new Search(user)).RunCommand(GetGameInstance(manager), options);
@@ -206,10 +229,6 @@ private static int RunSimpleAction(Options cmdline, CommonOptions options, strin
{
return printMissingInstanceError(user);
}
- finally
- {
- RegistryManager.DisposeAll();
- }
}
private static int printMissingInstanceError(IUser user)
diff --git a/Cmdline/Options.cs b/Cmdline/Options.cs
index 14ad13f1d7..fe88650b03 100644
--- a/Cmdline/Options.cs
+++ b/Cmdline/Options.cs
@@ -15,7 +15,7 @@ namespace CKAN.CmdLine
public class Options
{
- public string action { get; set; }
+ public string action { get; set; }
public object options { get; set; }
///
@@ -28,7 +28,7 @@ public Options(string[] args)
(
args, new Actions(), (verb, suboptions) =>
{
- action = verb;
+ action = verb;
options = suboptions;
},
delegate
@@ -49,6 +49,9 @@ internal class Actions : VerbCommandOptions
[VerbOption("consoleui", HelpText = "Start the CKAN console UI")]
public ConsoleUIOptions ConsoleUIOptions { get; set; }
+ [VerbOption("prompt", HelpText = "Run CKAN prompt for executing multiple commands in a row")]
+ public CommonOptions PromptOptions { get; set; }
+
[VerbOption("search", HelpText = "Search for mods")]
public SearchOptions SearchOptions { get; set; }
@@ -100,7 +103,7 @@ internal class Actions : VerbCommandOptions
[VerbOption("compare", HelpText = "Compare version strings")]
public CompareOptions Compare { get; set; }
- [VerbOption("version", HelpText = "Show the version of the CKAN client being used.")]
+ [VerbOption("version", HelpText = "Show the version of the CKAN client being used")]
public VersionOptions Version { get; set; }
[HelpVerbOption]
@@ -244,6 +247,24 @@ public virtual int Handle(KSPManager manager, IUser user)
return Exit.OK;
}
+ ///
+ /// Combine two options objects.
+ /// This is mainly to ensure that --headless carries through for prompt.
+ ///
+ /// Options object to merge into this one
+ public void Merge(CommonOptions otherOpts)
+ {
+ if (otherOpts != null)
+ {
+ Verbose = Verbose || otherOpts.Verbose;
+ Debug = Debug || otherOpts.Debug;
+ Debugger = Debugger || otherOpts.Debugger;
+ NetUserAgent = NetUserAgent ?? otherOpts.NetUserAgent;
+ Headless = Headless || otherOpts.Headless;
+ AsRoot = AsRoot || otherOpts.AsRoot;
+ }
+ }
+
private static void CheckMonoVersion(IUser user, int rec_major, int rec_minor, int rec_patch)
{
try
diff --git a/Core/ModuleInstaller.cs b/Core/ModuleInstaller.cs
index 4f3ed0d43c..a0ab2d8bc3 100644
--- a/Core/ModuleInstaller.cs
+++ b/Core/ModuleInstaller.cs
@@ -213,7 +213,7 @@ public void InstallList(ICollection modules, RelationshipResolverOpt
registry_manager.Save(!options.without_enforce_consistency);
- User.RaiseProgress("Commiting filesystem changes", 80);
+ User.RaiseProgress("Committing filesystem changes", 80);
transaction.Complete();
@@ -250,7 +250,7 @@ public void InstallList(ModuleResolution modules, RelationshipResolverOptions op
registry_manager.Save(!options.without_enforce_consistency);
- User.RaiseProgress("Commiting filesystem changes", 80);
+ User.RaiseProgress("Committing filesystem changes", 80);
transaction.Complete();
}