public int Execute (String inputFilePath, String outputFilePath, RegexFilter craftFilter, RegexFilter partFilter)
        {
            ui.DisplayUserMessage ($"Searching for crafts matching '{craftFilter}'...");

            var kspObjTree = CraftLoader.LoadFromFile (inputFilePath);
            var crafts = new CraftLookup (kspObjTree).LookupCrafts (craftFilter).ToList ();

            if (crafts.Count <= 0) {
                ui.DisplayErrorMessage ($"No craft matching '{craftFilter}' found, aborting");
                return -1;
            }

            ui.DisplayUserMessage ($"Searching for parts matching '{partFilter}'...");

            var partsRemoved = crafts.Aggregate (false, (removed, craft) => removed | RemoveMatchingParts (craft, partFilter));

            if (!partsRemoved) {
                ui.DisplayErrorMessage ($"No parts removed");
                return -1;
            }

            CraftLoader.SaveToFile (outputFilePath, kspObjTree);

            return 0;
        }
        public void CanLookupCraftsFromACraftTreeUsingTheProvidedFilter ()
        {
            // given
            var kspObjTree = createTestCraftTree ();
            var target = new CraftLookup (kspObjTree);

            // when / then
            Assert.That (target.LookupCrafts (new RegexFilter ("2")).Select (craft => craft.Name), Is.EqualTo (new[] { "craft2" }));
            Assert.That (target.LookupCrafts (new RegexFilter ("craft[1-3]")).Select (craft => craft.Name), Is.EqualTo (new[] { "craft1", "craft2", "craft3" }));
        }
        public void CanLookupCraftFromASingleCraftObjectUsingTheProvidedFilter ()
        {
            // given
            var kspObject = createTestCraft ();
            var target = new CraftLookup (kspObject);

            // when / then
            Assert.That (target.LookupCrafts (new RegexFilter ("")).Select (craft => craft.Name), Is.EqualTo (new[] { "craft1" }));
            Assert.That (target.LookupCrafts (new RegexFilter ("craft1")).Select (craft => craft.Name), Is.EqualTo (new[] { "craft1" }));
            Assert.That (target.LookupCrafts (new RegexFilter ("craft2")), Is.Empty);
        }
        public int Execute (String inputFilePath, RegexFilter craftFilter)
        {
            ui.DisplayUserMessage ($"Searching for crafts matching '{craftFilter}'...");

            var kspObjTree = CraftLoader.LoadFromFile (inputFilePath);
            var crafts = new CraftLookup (kspObjTree).LookupCrafts (craftFilter).ToList ();

            if (crafts.Count > 0) {
                ui.DisplayCraftList (crafts);
            }

            return 0;
        }
        public int Execute (String inputFilePath, RegexFilter craftFilter, RegexFilter partFilter)
        {
            ui.DisplayUserMessage ($"Searching for crafts matching '{craftFilter}'...");

            var kspObjTree = CraftLoader.LoadFromFile (inputFilePath);
            var crafts = new CraftLookup (kspObjTree).LookupCrafts (craftFilter);

            ui.DisplayUserMessage ($"Searching for parts matching '{partFilter}'...");

            var filteredParts = crafts.ToDictionary (craft => craft, craft => FindParts (craft, partFilter));

            if (filteredParts.Any (entry => entry.Value.Count > 0)) {
                ui.DisplayPartList (filteredParts);
            }

            return 0;
        }