diff --git a/KSPPartRemover.Tests/Integration/MunMkICraftTest.cs b/KSPPartRemover.Tests/Integration/MunMkICraftTest.cs index da5cd5f..5480334 100644 --- a/KSPPartRemover.Tests/Integration/MunMkICraftTest.cs +++ b/KSPPartRemover.Tests/Integration/MunMkICraftTest.cs @@ -19,7 +19,7 @@ public void CanRemoveBoostersAttachedToNoseConeFromCraftFile () File.WriteAllText (tempFileName, inputCraftText); // when - var returnCode = Program.Main ("remove-parts", "--part", "noseCone_4294253786", "-i", tempFileName, "-o", tempFileName, "--silent"); + var returnCode = Program.Main ("remove-parts", "--part", "noseCone_4294253786", "-i", tempFileName, "--silent"); // then Assert.That (returnCode, Is.EqualTo (0)); diff --git a/KSPPartRemover.Tests/Integration/ProgramTest.cs b/KSPPartRemover.Tests/Integration/ProgramTest.cs index b1dd0d9..a23a7b4 100644 --- a/KSPPartRemover.Tests/Integration/ProgramTest.cs +++ b/KSPPartRemover.Tests/Integration/ProgramTest.cs @@ -9,6 +9,7 @@ namespace KSPPartRemover.Tests.Integration { public class ProgramTest { + private static readonly String TestFilePath = "test.sfs"; private static readonly StringBuilder StdOutput = new StringBuilder (); private static readonly StringWriter StdOutputWriter = new StringWriter (StdOutput); @@ -38,8 +39,8 @@ public void PrintsInfoHeaderIfSilentSwitchIsNotOn () var inputText = KspObjToString (inputCrafts); // when - File.WriteAllText ("input.txt", inputText); - var returnCode = Program.Main ("list-crafts", "-i", "input.txt"); + File.WriteAllText (TestFilePath, inputText); + var returnCode = Program.Main ("list-crafts", "-i", TestFilePath); // then Assert.That (StdOutput.ToString (), Is.StringStarting ("KSPPartRemover v")); @@ -108,11 +109,11 @@ public void CanRemovePartByIdAndOutputResult () var expectedResult = KspObjToString (expectedCraft); // when - File.WriteAllText ("input.txt", inputText); - var returnCode = Program.Main ("remove-parts", "-p", "0", "-i", "input.txt", "-s"); + File.WriteAllText (TestFilePath, inputText); + var returnCode = Program.Main ("remove-parts", "-p", "0", "-i", TestFilePath, "-s"); // then - Assert.That (StdOutput.ToString (), Is.EqualTo (expectedResult)); + Assert.That (File.ReadAllText (TestFilePath), Is.EqualTo (expectedResult)); Assert.That (returnCode, Is.EqualTo (0)); } @@ -134,11 +135,11 @@ public void CanRemovePartByNameAndOutputResult () var expectedResult = KspObjToString (expectedCraft); // when - File.WriteAllText ("input.txt", inputText); - var returnCode = Program.Main ("remove-parts", "-p", "fuelTank", "-i", "input.txt", "-s"); + File.WriteAllText (TestFilePath, inputText); + var returnCode = Program.Main ("remove-parts", "-p", "fuelTank", "-i", TestFilePath, "-s"); // then - Assert.That (StdOutput.ToString (), Is.EqualTo (expectedResult)); + Assert.That (File.ReadAllText (TestFilePath), Is.EqualTo (expectedResult)); Assert.That (returnCode, Is.EqualTo (0)); } @@ -176,11 +177,11 @@ public void CanRemovePartsOfMultipleCraftsAndOutputResult () var expectedResult = KspObjToString (expectedCrafts); // when - File.WriteAllText ("input.txt", inputText); - var returnCode = Program.Main ("remove-parts", "-p", "fuelTank", "-c", "!craft2", "-i", "input.txt", "-s"); + File.WriteAllText (TestFilePath, inputText); + var returnCode = Program.Main ("remove-parts", "-p", "fuelTank", "-c", "!craft2", "-i", TestFilePath, "-o", TestFilePath, "-s"); // then - Assert.That (StdOutput.ToString (), Is.EqualTo (expectedResult)); + Assert.That (File.ReadAllText (TestFilePath), Is.EqualTo (expectedResult)); Assert.That (returnCode, Is.EqualTo (0)); } @@ -198,8 +199,8 @@ public void CanPrintCraftList () var expectedResult = "someCraft" + Environment.NewLine + "anotherCraft" + Environment.NewLine; // when - File.WriteAllText ("input.txt", inputText); - var returnCode = Program.Main ("list-crafts", "-c", ".*Craft", "-i", "input.txt"); + File.WriteAllText (TestFilePath, inputText); + var returnCode = Program.Main ("list-crafts", "-c", ".*Craft", "-i", TestFilePath); // then Assert.That (StdOutput.ToString (), Is.StringEnding (expectedResult)); @@ -232,8 +233,8 @@ public void CanPrintPartList () "\t[1]fuelTank" + Environment.NewLine; // when - File.WriteAllText ("input.txt", inputText); - var returnCode = Program.Main ("list-parts", "-p", "[s,f].*", "-c", ".*Craft", "-i", "input.txt"); + File.WriteAllText (TestFilePath, inputText); + var returnCode = Program.Main ("list-parts", "-p", "[s,f].*", "-c", ".*Craft", "-i", TestFilePath); // then Assert.That (StdOutput.ToString (), Is.StringEnding (expectedResult)); @@ -274,8 +275,8 @@ public void CanPrintPartDependencies () "\t\t[1]fuelTank2[attN(bottom)]" + Environment.NewLine; // when - File.WriteAllText ("input.txt", inputText); - var returnCode = Program.Main ("list-partdeps", "-p", ".*uelTank.*", "-c", ".*Craft", "-i", "input.txt"); + File.WriteAllText (TestFilePath, inputText); + var returnCode = Program.Main ("list-partdeps", "-p", ".*uelTank.*", "-c", ".*Craft", "-i", TestFilePath); // then Assert.That (StdOutput.ToString (), Is.StringEnding (expectedResult)); @@ -294,8 +295,8 @@ public void PrintsAndReturnsErrorIfPartIdToRemoveIsNotFound () var inputText = KspObjToString (inputCraft); // when - File.WriteAllText ("input.txt", inputText); - var returnCode = Program.Main ("remove-parts", "-p", "2", "-i", "input.txt", "-s"); + File.WriteAllText (TestFilePath, inputText); + var returnCode = Program.Main ("remove-parts", "-p", "2", "-i", TestFilePath, "-s"); // then Assert.That (StdOutput.ToString (), Is.EqualTo ("ERROR: No parts removed\n")); @@ -314,8 +315,8 @@ public void PrintsAndReturnsErrorIfPartNameToRemoveIsNotFound () var inputText = KspObjToString (inputCraft); // when - File.WriteAllText ("input.txt", inputText); - var returnCode = Program.Main ("remove-parts", "-p", "nonExistingPart", "-i", "input.txt", "-s"); + File.WriteAllText (TestFilePath, inputText); + var returnCode = Program.Main ("remove-parts", "-p", "nonExistingPart", "-i", TestFilePath, "-s"); // then Assert.That (StdOutput.ToString (), Is.EqualTo ("ERROR: No parts removed\n")); @@ -333,8 +334,8 @@ public void PrintsAndReturnsErrorIfNoCraftWithMatchingCraftNameIsFound () var inputText = KspObjToString (inputCrafts); // when - File.WriteAllText ("input.txt", inputText); - var returnCode = Program.Main ("remove-parts", "-p", "somePart", "--craft", "nonExistingCraft", "-i", "input.txt", "-s"); + File.WriteAllText (TestFilePath, inputText); + var returnCode = Program.Main ("remove-parts", "-p", "somePart", "--craft", "nonExistingCraft", "-i", TestFilePath, "-s"); // then Assert.That (StdOutput.ToString (), Is.EqualTo ("No craft matching 'nonExistingCraft' found, aborting" + Environment.NewLine)); diff --git a/KSPPartRemover.Tests/Integration/SaveFileTest.cs b/KSPPartRemover.Tests/Integration/SaveFileTest.cs index 27013db..577d560 100644 --- a/KSPPartRemover.Tests/Integration/SaveFileTest.cs +++ b/KSPPartRemover.Tests/Integration/SaveFileTest.cs @@ -19,7 +19,7 @@ public void CanRemoveEnginesFromAllBowserCrafts () File.WriteAllText (tempFileName, inputCraftText); // when - var returnCode = Program.Main ("remove-parts", "--part", "liquidEngine.*", "--craft", "Bowser.*", "-i", tempFileName, "-o", tempFileName, "--silent"); + var returnCode = Program.Main ("remove-parts", "--part", "liquidEngine.*", "--craft", "Bowser.*", "-i", tempFileName, "--silent"); // then Assert.That (returnCode, Is.EqualTo (0)); diff --git a/KSPPartRemover.Tests/Integration/SpaceStationTest.cs b/KSPPartRemover.Tests/Integration/SpaceStationTest.cs index d62a1c5..1040969 100644 --- a/KSPPartRemover.Tests/Integration/SpaceStationTest.cs +++ b/KSPPartRemover.Tests/Integration/SpaceStationTest.cs @@ -19,7 +19,7 @@ public class SpaceStationTest File.WriteAllText (tempFileName, inputCraftText); // when - var returnCode = Program.Main ("remove-parts", "--part", "ladder1", "-i", tempFileName, "-o", tempFileName, "--silent"); + var returnCode = Program.Main ("remove-parts", "--part", "ladder1", "-i", tempFileName, "--silent"); // then Assert.That (returnCode, Is.EqualTo (0)); diff --git a/KSPPartRemover/Command/Help.cs b/KSPPartRemover/Command/Help.cs index eee50de..026fc5e 100644 --- a/KSPPartRemover/Command/Help.cs +++ b/KSPPartRemover/Command/Help.cs @@ -20,7 +20,7 @@ public int Execute () var sb = new StringBuilder (); sb.Append ("usage: "); sb.Append (Path.GetFileName (assemblyName.CodeBase)); - sb.AppendLine (" [] -i [-o ]"); + sb.AppendLine (" [] -i "); sb.AppendLine (); sb.AppendLine ("Commands:"); sb.AppendLine (); @@ -44,7 +44,7 @@ public int Execute () sb.AppendLine (); sb.AppendLine ("\t[Optional]"); sb.AppendLine ("\t -o "); - sb.AppendLine ("\t\t specifies the output file (prints to stdout if not specified)"); + sb.AppendLine ("\t\t specifies the output file (modifies input file if not specified)"); sb.AppendLine (); sb.AppendLine ("\t[Optional]"); sb.AppendLine ("\t -c, --craft "); diff --git a/KSPPartRemover/Command/ListCrafts.cs b/KSPPartRemover/Command/ListCrafts.cs index 6dc1497..fce40f0 100644 --- a/KSPPartRemover/Command/ListCrafts.cs +++ b/KSPPartRemover/Command/ListCrafts.cs @@ -22,9 +22,11 @@ public int Execute (Parameters parameters) { var allCrafts = CraftLoader.LoadFromFile (parameters.InputFilePath); ui.DisplayUserMessage ($"Searching for crafts matching '{parameters.CraftFilter}'..."); - var filteredCrafts = parameters.CraftFilter.Apply (allCrafts, craft => craft.Name); + var filteredCrafts = parameters.CraftFilter.Apply (allCrafts, craft => craft.Name).ToList (); - ui.DisplayCraftList (filteredCrafts); + if (filteredCrafts.Count > 0) { + ui.DisplayCraftList (filteredCrafts); + } return 0; } diff --git a/KSPPartRemover/Command/ListPartDeps.cs b/KSPPartRemover/Command/ListPartDeps.cs index ef734c8..fc690da 100644 --- a/KSPPartRemover/Command/ListPartDeps.cs +++ b/KSPPartRemover/Command/ListPartDeps.cs @@ -27,12 +27,14 @@ public int Execute (Parameters parameters) ui.DisplayUserMessage ($"Searching for parts with dependencies to '{parameters.PartFilter}'..."); var partDependencies = filteredCrafts.ToDictionary (craft => craft, craft => FindPartDependencies (craft, parameters.PartFilter)); - ui.DisplayPartDependencyList (partDependencies); + if (partDependencies.Any (entry => entry.Value.Count > 0)) { + ui.DisplayPartDependencyList (partDependencies); + } return 0; } - private IReadOnlyDictionary> FindPartDependencies (KspCraftObject craft, RegexFilter filter) + private Dictionary> FindPartDependencies (KspCraftObject craft, RegexFilter filter) { ui.DisplayUserMessage ($"Entering craft '{craft.Name}'..."); var partLookup = new PartLookup (craft); diff --git a/KSPPartRemover/Command/ListParts.cs b/KSPPartRemover/Command/ListParts.cs index 3711599..d8d8902 100644 --- a/KSPPartRemover/Command/ListParts.cs +++ b/KSPPartRemover/Command/ListParts.cs @@ -26,7 +26,9 @@ public int Execute (Parameters parameters) ui.DisplayUserMessage ($"Searching for parts matching '{parameters.PartFilter}'..."); var filteredParts = filteredCrafts.ToDictionary (craft => craft, craft => FindParts (craft, parameters.PartFilter)); - ui.DisplayPartList (filteredParts); + if (filteredParts.Any (entry => entry.Value.Count > 0)) { + ui.DisplayPartList (filteredParts); + } return 0; } diff --git a/KSPPartRemover/Program.cs b/KSPPartRemover/Program.cs index 28b281f..6fb81ee 100644 --- a/KSPPartRemover/Program.cs +++ b/KSPPartRemover/Program.cs @@ -17,8 +17,7 @@ public static int Main (params String[] args) { var parameters = new Parameters () { CraftFilter = new RegexFilter (""), - PartFilter = new RegexFilter (""), - OutputTextWriter = Console.Out + PartFilter = new RegexFilter ("") }; var ui = new ProgramUI (parameters); @@ -48,8 +47,8 @@ public static int Main (params String[] args) var commandLineParser = new CommandLineParser () .RequiredArgument (0, parseCommand) - .RequiredSwitchArg ("-i", fileName => parameters.InputText = ReadInputFile (fileName)) - .OptionalSwitchArg ("-o", fileName => parameters.OutputTextWriter = OpenOutputFile (fileName)) + .RequiredSwitchArg ("-i", filePath => parameters.InputFilePath = filePath) + .OptionalSwitchArg ("-o", filePath => parameters.OutputFilePath = filePath) .OptionalSwitchArg ("-c", pattern => parameters.CraftFilter = new RegexFilter (pattern)) .OptionalSwitchArg ("--craft", pattern => parameters.CraftFilter = new RegexFilter (pattern)) .OptionalSwitchArg ("-p", pattern => parameters.PartFilter = new RegexFilter (pattern)) @@ -60,6 +59,9 @@ public static int Main (params String[] args) try { commandLineParser.Parse (args); + if (parameters.OutputFilePath == null) { + parameters.OutputFilePath = parameters.InputFilePath; + } if (errors.Count > 0) { printInfoHeader.Execute (); diff --git a/KSPPartRemover/ProgramUI.cs b/KSPPartRemover/ProgramUI.cs index b3f85ec..6279b04 100644 --- a/KSPPartRemover/ProgramUI.cs +++ b/KSPPartRemover/ProgramUI.cs @@ -17,12 +17,12 @@ public ProgramUI (Parameters parameters) this.parameters = parameters; } - public void DisplayCraftList (IEnumerable crafts) + public void DisplayCraftList (List crafts) { PrintList ("Crafts", crafts.Select (CraftObjectToString)); } - public void DisplayPartList (IReadOnlyDictionary> craftParts) + public void DisplayPartList (Dictionary> craftParts) { var listEntries = new List (); @@ -34,7 +34,7 @@ public void DisplayPartList (IReadOnlyDictionary>> craftPartLinks) + public void DisplayPartDependencyList (Dictionary>> craftPartLinks) { var listEntries = new List (); diff --git a/README.md b/README.md index 8e66bd2..48bb09d 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Removes parts from Kerbal Space Program crafts KSPPartRemover v0.3.0.0 Compatible with KSP version: 1.1 -usage: KSPPartRemover.exe [] -i [-o ] +usage: KSPPartRemover.exe [] -i Commands: @@ -41,13 +41,13 @@ Switches: [Optional] -o - specifies the output file (prints to stdout if not specified) + specifies the output file (modifies input file if not specified) [Optional] -c, --craft apply craft filter (applies to all crafts if not specified) '!' in front of the regex performs inverse matching - example for name pattern: --craft '!^Asteroid' + example for name pattern: --craft '^Asteroid' example for inverse matching: --craft '!Mün' [Optional] @@ -65,13 +65,12 @@ Switches: ## General notes -If no output file is specified, standard output (console) is used. -That way, if used in combination with --silent, it can be used programmatically should you desire. - -This tool has been tested with the following types of files so far : -* .craft files generated by KSP 1.1 -* .sfs files generated by KSP 1.1 -* .txt craft files generated by the DarkMultiplayer Server (a pretty old version, quite a while ago) +* If no output file is specified, the input file is modified. +* This tool supports a **--silent** switch and can be used programmatically should you desire. +* It has been tested with the following types of files so far : + * .craft files generated by KSP 1.1 + * .sfs files generated by KSP 1.1 + * .txt craft files generated by the DarkMultiplayer Server (a pretty old version, quite a while ago) Release notes =======================