From 3c1d1958490aa433a1b38598f166da9a68d7403c Mon Sep 17 00:00:00 2001 From: Timerix Date: Sun, 6 Apr 2025 13:53:21 +0500 Subject: [PATCH] split CLI modes to separate files --- .../{Modes.cs => Modes/Interactive.cs} | 65 ++++--------------- ParadoxSaveParser.CLI/Modes/Search.cs | 49 ++++++++++++++ .../ParadoxSaveParser.CLI.csproj | 2 +- .../ParadoxSaveParser.CLI.csproj.DotSettings | 2 + ParadoxSaveParser.CLI/Program.cs | 38 ++++++----- 5 files changed, 85 insertions(+), 71 deletions(-) rename ParadoxSaveParser.CLI/{Modes.cs => Modes/Interactive.cs} (65%) create mode 100644 ParadoxSaveParser.CLI/Modes/Search.cs create mode 100644 ParadoxSaveParser.CLI/ParadoxSaveParser.CLI.csproj.DotSettings diff --git a/ParadoxSaveParser.CLI/Modes.cs b/ParadoxSaveParser.CLI/Modes/Interactive.cs similarity index 65% rename from ParadoxSaveParser.CLI/Modes.cs rename to ParadoxSaveParser.CLI/Modes/Interactive.cs index 1fe345a..fe094a8 100644 --- a/ParadoxSaveParser.CLI/Modes.cs +++ b/ParadoxSaveParser.CLI/Modes/Interactive.cs @@ -12,51 +12,11 @@ internal enum Mode Unset, Search, Interactive } -internal static class Modes +internal static partial class Modes { - internal static void Search(string searchQuery, IOPath inputPath, IOPath? outputPath) - { - Stream inputStream = File.OpenRead(inputPath); - try - { - byte[] head4 = new byte[4]; - inputStream.ReadExactly(head4); - inputStream.Seek(0, SeekOrigin.Begin); - if (head4.SequenceEqual([(byte)'P', (byte)'K', 3, 4])) - { - var zipArchive = new ZipArchive(inputStream, ZipArchiveMode.Read); - var zipEntry = zipArchive.Entries.FirstOrDefault(e => e.Name == "gamestate"); - if (zipEntry is null) - throw new Exception("'gamestate' file not found in zip archive"); - var unzipped = new MemoryStream((int)zipEntry.Length); - zipEntry.Open().CopyTo(unzipped); - zipArchive.Dispose(); // closes inputStream - unzipped.Seek(0, SeekOrigin.Begin); - inputStream = unzipped; - } - - using var outputStream = outputPath is null - ? Console.OpenStandardOutput() - : File.OpenWrite(outputPath.Value); - - var searchExpression = SearchExpressionCompiler.Compile(searchQuery); - - var parser = new SaveParserEU4(inputStream, searchExpression); - var parsedValue = parser.Parse(); - JsonSerializer.Serialize(outputStream, parsedValue, - ParsedValueJsonContext.Default.DictionaryStringListObject); - outputStream.WriteByte((byte)'\n'); - } - finally - { - inputStream.Dispose(); - } - } - internal static void Interactive() { - Console.Clear(); - Console.ResetColor(); + ColoredConsole.Clear(); ColoredConsole.WriteTitle("interactive mode", fg: ConsoleColor.Cyan); ColoredConsole.WriteLine($"working directory: '{Environment.CurrentDirectory}'", ConsoleColor.Gray); IOPath? inputPath = null; @@ -67,8 +27,7 @@ internal static class Modes try { ColoredConsole.Write("> ", ConsoleColor.Blue); - Console.ForegroundColor = ConsoleColor.Gray; - string? input = Console.ReadLine(); + string input = ColoredConsole.ReadLine(ConsoleColor.Gray); if (string.IsNullOrEmpty(input)) continue; @@ -108,13 +67,13 @@ internal static class Modes case "h": case "help": - ColoredConsole.WriteLine(helpMessage, fg: ConsoleColor.White); + ColoredConsole.WriteLine(helpMessage, ConsoleColor.White); break; case "i": case "input": - input = ColoredConsole.ReadLine("Input file path", - ConsoleColor.Blue); + ColoredConsole.Write("Input file path: ", ConsoleColor.Blue); + input = ColoredConsole.ReadLine(ConsoleColor.Gray); if (string.IsNullOrEmpty(input)) throw new NullReferenceException(); inputPath = input; @@ -122,8 +81,8 @@ internal static class Modes case "o": case "output": - input = ColoredConsole.ReadLine("Output file path [default=stdout]", - ConsoleColor.Blue); + ColoredConsole.Write("Output file path [default=stdout]: ", ConsoleColor.Blue); + input = ColoredConsole.ReadLine(ConsoleColor.Gray); if (string.IsNullOrEmpty(input)) throw new ArgumentException("Input file path is required"); inputPath = input; @@ -134,8 +93,8 @@ internal static class Modes if (inputPath is null) throw new ArgumentException("Input file path is required"); - var searchQuery = ColoredConsole.ReadLine("search expression", - ConsoleColor.Blue); + ColoredConsole.Write("search expression: ", ConsoleColor.Blue); + var searchQuery = ColoredConsole.ReadLine(ConsoleColor.Gray); if (string.IsNullOrEmpty(searchQuery)) throw new ArgumentException("Search expression is required"); @@ -150,8 +109,8 @@ internal static class Modes break; case "cd": - input = ColoredConsole.ReadLine("Change working directory to", - ConsoleColor.Blue); + ColoredConsole.Write("Change working directory to: ", ConsoleColor.Blue); + input = ColoredConsole.ReadLine(ConsoleColor.Gray); if (!string.IsNullOrEmpty(input)) { Environment.CurrentDirectory = new IOPath(input).Str; diff --git a/ParadoxSaveParser.CLI/Modes/Search.cs b/ParadoxSaveParser.CLI/Modes/Search.cs new file mode 100644 index 0000000..993a10d --- /dev/null +++ b/ParadoxSaveParser.CLI/Modes/Search.cs @@ -0,0 +1,49 @@ +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Text.Json; +using ParadoxSaveParser.Lib; + +namespace ParadoxSaveParser.CLI; + +internal static partial class Modes +{ + internal static void Search(string searchQuery, IOPath inputPath, IOPath? outputPath) + { + Stream inputStream = File.OpenRead(inputPath); + try + { + byte[] head4 = new byte[4]; + inputStream.ReadExactly(head4); + inputStream.Seek(0, SeekOrigin.Begin); + if (head4.SequenceEqual([(byte)'P', (byte)'K', 3, 4])) + { + var zipArchive = new ZipArchive(inputStream, ZipArchiveMode.Read); + var zipEntry = zipArchive.Entries.FirstOrDefault(e => e.Name == "gamestate"); + if (zipEntry is null) + throw new Exception("'gamestate' file not found in zip archive"); + var unzipped = new MemoryStream((int)zipEntry.Length); + zipEntry.Open().CopyTo(unzipped); + zipArchive.Dispose(); // closes inputStream + unzipped.Seek(0, SeekOrigin.Begin); + inputStream = unzipped; + } + + using var outputStream = outputPath is null + ? Console.OpenStandardOutput() + : File.OpenWrite(outputPath.Value); + + var searchExpression = SearchExpressionCompiler.Compile(searchQuery); + + var parser = new SaveParserEU4(inputStream, searchExpression); + var parsedValue = parser.Parse(); + JsonSerializer.Serialize(outputStream, parsedValue, + ParsedValueJsonContext.Default.DictionaryStringListObject); + outputStream.WriteByte((byte)'\n'); + } + finally + { + inputStream.Dispose(); + } + } +} \ No newline at end of file diff --git a/ParadoxSaveParser.CLI/ParadoxSaveParser.CLI.csproj b/ParadoxSaveParser.CLI/ParadoxSaveParser.CLI.csproj index 6a8e78d..117211a 100644 --- a/ParadoxSaveParser.CLI/ParadoxSaveParser.CLI.csproj +++ b/ParadoxSaveParser.CLI/ParadoxSaveParser.CLI.csproj @@ -14,6 +14,6 @@ - + diff --git a/ParadoxSaveParser.CLI/ParadoxSaveParser.CLI.csproj.DotSettings b/ParadoxSaveParser.CLI/ParadoxSaveParser.CLI.csproj.DotSettings new file mode 100644 index 0000000..180f43f --- /dev/null +++ b/ParadoxSaveParser.CLI/ParadoxSaveParser.CLI.csproj.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/ParadoxSaveParser.CLI/Program.cs b/ParadoxSaveParser.CLI/Program.cs index c18e8b3..bbb4e69 100644 --- a/ParadoxSaveParser.CLI/Program.cs +++ b/ParadoxSaveParser.CLI/Program.cs @@ -14,26 +14,26 @@ try string? searchQuery = null; new LaunchArgumentParser( - new LaunchArgument(["-i", "--input"], - "Set input file path", - s => inputPath = s, - "gamestate or zip file"), + new LaunchArgument(["-i", "--input"], + "Set input file path", + s => inputPath = s, + "gamestate or zip file"), - new LaunchArgument(["-o", "--output"], - "Set output file path", - s => outputPath = s, - "json file [default=stdout]"), + new LaunchArgument(["-o", "--output"], + "Set output file path", + s => outputPath = s, + "json file [default=stdout]"), - new LaunchArgument(["-s", "--search"], - "Search in input file", - s => - { - searchQuery = s; - mode = Mode.Search; - }, - "search expression") + new LaunchArgument(["-s", "--search"], + "Search in input file", + s => + { + searchQuery = s; + mode = Mode.Search; + }, + "search expression") ) - .WithNoExit() + .AllowNoArguments() .ParseAndHandle(args); if (args.Length == 0) @@ -57,6 +57,10 @@ try break; } } +catch (LaunchArgumentParser.ExitAfterHelpException) +{ + // this exception is throwed after -h argument to close the program +} catch (Exception ex) { ColoredConsole.WriteLine(ex.ToStringDemystified(), ConsoleColor.Red);