Skip to content

Commit 0f5d3c1

Browse files
authored
Merge pull request #25 from zrckr/cli-flags
Add support for optional flags for CLI commands
2 parents e1f82d8 + 1bf7206 commit 0f5d3c1

12 files changed

+343
-90
lines changed

Core/Conversion/FormatConversion.cs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public static class FormatConversion
1818
/// convert it and store in a <see cref="FileBundle"/>.
1919
/// </summary>
2020
/// <param name="data">A reference to object to convert</param>
21+
/// <param name="configuration">A configuration dictionary to alter converter behaviour</param>
2122
/// <returns>
2223
/// A <see cref="FileBundle"/> containing file or files converted from given object.
2324
/// </returns>
@@ -27,7 +28,7 @@ public static class FormatConversion
2728
/// <exception cref="FormatConversionException">
2829
/// Thrown when a type of given object is not supported by Repacker
2930
/// </exception>
30-
public static FileBundle Convert(object? data)
31+
public static FileBundle Convert(object? data, IDictionary<string, object>? configuration = null)
3132
{
3233
if(data == null)
3334
{
@@ -36,11 +37,19 @@ public static FileBundle Convert(object? data)
3637

3738
var converter = FormatConverters.FindForType(data.GetType());
3839

39-
if(converter == null)
40+
if (converter == null)
4041
{
4142
throw new FormatConversionException($"Type {data.GetType()} is not supported for conversion.");
4243
}
4344

45+
if (configuration != null)
46+
{
47+
foreach (var pair in configuration)
48+
{
49+
converter.Configuration.Add(pair);
50+
}
51+
}
52+
4453
return converter.Convert(data);
4554
}
4655

@@ -49,20 +58,29 @@ public static FileBundle Convert(object? data)
4958
/// then attempts to deconvert it back to an object with a type assigned to this converter.
5059
/// </summary>
5160
/// <param name="bundle">A <see cref="FileBundle"/> containing files to convert.</param>
61+
/// <param name="configuration">A configuration dictionary to alter converter behaviour</param>
5262
/// <returns>
5363
/// An object deconverted from files contained in given <see cref="FileBundle"/>.
5464
/// </returns>
5565
/// <exception cref="FormatConversionException">
5666
/// Thrown when main extension of given <see cref="FileBundle"/> is not supported by Repacker
5767
/// </exception>
58-
public static object? Deconvert(FileBundle bundle)
68+
public static object? Deconvert(FileBundle bundle, IDictionary<string, object>? configuration = null)
5969
{
6070
var converter = FormatConverters.FindForFileBundle(bundle);
6171

6272
if (converter == null)
6373
{
6474
throw new FormatConversionException($"File bundle type {bundle.MainExtension} is not supported for conversion.");
6575
}
76+
77+
if (configuration != null)
78+
{
79+
foreach (var pair in configuration)
80+
{
81+
converter.Configuration.Add(pair);
82+
}
83+
}
6684

6785
return converter.Deconvert(bundle);
6886
}

Core/Conversion/FormatConverter.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using FEZRepacker.Core.FileSystem;
1+
using System.Collections.ObjectModel;
2+
3+
using FEZRepacker.Core.FileSystem;
24

35
namespace FEZRepacker.Core.Conversion
46
{
@@ -15,6 +17,8 @@ public abstract class FormatConverter
1517
public abstract FileBundle Convert(object? data);
1618
public abstract object? Deconvert(FileBundle bundle);
1719

20+
public IDictionary<string, object> Configuration { get; } = new Dictionary<string, object>();
21+
1822
public FileBundle Convert<T>(T data)
1923
{
2024
return Convert((object?)data);

Interface/Actions/ConvertFromXnbAction.cs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ namespace FEZRepacker.Interface.Actions
66
{
77
internal class ConvertFromXnbAction : CommandLineAction
88
{
9+
private const string XnbInput = "xnb-input";
10+
11+
private const string FileOutput = "file-output";
12+
913
public string Name => "--convert-from-xnb";
1014

1115
public string[] Aliases => new[] { "-x" };
@@ -16,11 +20,10 @@ internal class ConvertFromXnbAction : CommandLineAction
1620
"path recursively. If output directory is not given, outputs next to the input file(s).";
1721

1822
public CommandLineArgument[] Arguments => new[] {
19-
new CommandLineArgument("xnb-input"),
20-
new CommandLineArgument("file-output", true)
23+
new CommandLineArgument(XnbInput),
24+
new CommandLineArgument(FileOutput, ArgumentType.OptionalPositional)
2125
};
2226

23-
2427
private List<string> FindXnbFilesAtPath(string path)
2528
{
2629
if (Directory.Exists(path))
@@ -42,13 +45,11 @@ private List<string> FindXnbFilesAtPath(string path)
4245
throw new FileNotFoundException("Specified input path does not lead to any file or a directory");
4346
}
4447
}
45-
46-
47-
48-
public void Execute(string[] args)
48+
49+
public void Execute(Dictionary<string, string> args)
4950
{
50-
var inputPath = args[0];
51-
var outputPath = args.Length > 1 ? args[1] : inputPath;
51+
var inputPath = args[XnbInput];
52+
var outputPath = args.GetValueOrDefault(FileOutput, inputPath);
5253

5354
if (File.Exists(outputPath))
5455
{

Interface/Actions/ConvertToXnbAction.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ namespace FEZRepacker.Interface.Actions
99
{
1010
internal class ConvertToXnbAction : CommandLineAction
1111
{
12+
private const string FileInput = "file-input";
13+
14+
private const string XnbOutput = "xnb-output";
15+
1216
public string Name => "--convert-to-xnb";
1317

1418
public string[] Aliases => new[] { "-X" };
@@ -19,12 +23,12 @@ internal class ConvertToXnbAction : CommandLineAction
1923
"specified path recursively. If output directory is not given, outputs next to the input file(s).";
2024

2125
public CommandLineArgument[] Arguments => new[] {
22-
new CommandLineArgument("file-input"),
23-
new CommandLineArgument("xnb-output", true)
26+
new CommandLineArgument(FileInput),
27+
new CommandLineArgument(XnbOutput, ArgumentType.OptionalPositional)
2428
};
2529

26-
2730
public delegate void ConversionFunc(string path, string extension, Stream stream, bool converted);
31+
2832
public static void PerformBatchConversion(List<FileBundle> fileBundles, ConversionFunc processFileFunc)
2933
{
3034
Console.WriteLine($"Converting {fileBundles.Count()} assets...");
@@ -57,10 +61,10 @@ public static void PerformBatchConversion(List<FileBundle> fileBundles, Conversi
5761
}
5862
}
5963

60-
public void Execute(string[] args)
64+
public void Execute(Dictionary<string, string> args)
6165
{
62-
string inputPath = args[0];
63-
string outputPath = args.Length > 1 ? args[1] : inputPath;
66+
var inputPath = args[FileInput];
67+
var outputPath = args.GetValueOrDefault(XnbOutput, inputPath);
6468

6569
if (File.Exists(outputPath))
6670
{

Interface/Actions/HelpAction.cs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,19 @@
22
{
33
internal class HelpAction : CommandLineAction
44
{
5+
private const string Command = "command";
6+
57
public string Name => "--help";
68
public string[] Aliases => new[] { "help", "?", "-?", "-h" };
79
public string Description => "Displays help for all commands or help for given command.";
10+
811
public CommandLineArgument[] Arguments => new[] {
9-
new CommandLineArgument("command", true)
12+
new CommandLineArgument(Command, ArgumentType.OptionalPositional)
1013
};
1114

12-
public void Execute(string[] args)
15+
public void Execute(Dictionary<string, string> args)
1316
{
14-
if(args.Length == 0)
17+
if (args.Count == 0)
1518
{
1619
foreach (var cmd in CommandLineInterface.Commands)
1720
{
@@ -21,29 +24,39 @@ public void Execute(string[] args)
2124
return;
2225
}
2326

24-
var command = CommandLineInterface.FindCommand(args[0]);
27+
var arg = args.GetValueOrDefault(Command, string.Empty);
28+
var command = CommandLineInterface.FindCommand(arg);
2529
if (command != null)
2630
{
2731
ShowHelpFor(command);
2832
}
2933
else
3034
{
31-
Console.WriteLine($"Unknown command \"{args[0]}\".");
35+
Console.WriteLine($"Unknown command \"{arg}\".");
3236
Console.WriteLine($"Use \"--help\" parameter for a list of commands.");
3337
}
3438
}
3539

36-
private void ShowHelpFor(CommandLineAction command)
40+
private static void ShowHelpFor(CommandLineAction command)
3741
{
3842
string allNames = command.Name;
3943
if (command.Aliases.Length > 0)
4044
{
4145
allNames = $"[{command.Name}, {String.Join(", ", command.Aliases)}]";
4246
}
4347

44-
string argsStr = String.Join(" ", command.Arguments.Select(arg => arg.Optional ? $"<{arg.Name}>" : $"[{arg.Name}]"));
45-
46-
Console.WriteLine($"Usage: {allNames} {argsStr}");
48+
var args = command.Arguments.Select(arg =>
49+
{
50+
return arg.Type switch
51+
{
52+
ArgumentType.OptionalPositional => $"<{arg.Name}>",
53+
ArgumentType.RequiredPositional => $"[{arg.Name}]",
54+
ArgumentType.Flag => $"--{arg.Name}",
55+
_ => throw new ArgumentOutOfRangeException($"Invalid argument type: {arg.Type}")
56+
};
57+
});
58+
59+
Console.WriteLine($"Usage: {allNames} {String.Join(" ", args)}");
4760
Console.WriteLine($"Description: {command.Description}");
4861
}
4962
}

Interface/Actions/ListPackageContentAction.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,18 @@ namespace FEZRepacker.Interface.Actions
44
{
55
internal class ListPackageContentAction : CommandLineAction
66
{
7+
private const string PakPath = "pak-path";
8+
79
public string Name => "--list";
810
public string[] Aliases => new[] { "-l" };
911
public string Description => "Lists all files contained withing given .PAK package.";
1012
public CommandLineArgument[] Arguments => new[] {
11-
new CommandLineArgument("pak-path")
13+
new CommandLineArgument(PakPath)
1214
};
1315

14-
public void Execute(string[] args)
16+
public void Execute(Dictionary<string, string> args)
1517
{
16-
var pakPath = args[0];
17-
18+
var pakPath = args[PakPath];
1819
var pakPackage = PakPackage.ReadFromFile(pakPath);
1920

2021
Console.WriteLine($"PAK package \"{pakPath}\" with {pakPackage.Entries.Count} files.");

Interface/Actions/PackAction.cs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,19 @@ namespace FEZRepacker.Interface.Actions
66
{
77
internal class PackAction : CommandLineAction
88
{
9+
private const string InputDirectoryPath = "input-directory-path";
10+
private const string DestinationPakPath = "destination-pak-path";
11+
private const string IncludePakPath = "include-pak-path";
12+
913
public string Name => "--pack";
1014
public string[] Aliases => new[] { "-p" };
1115
public string Description =>
1216
"Loads files from given input directory path, tries to deconvert them and pack into a destination " +
1317
".PAK file with given path. If include .PAK path is provided, it'll add its content into the new .PAK package.";
1418
public CommandLineArgument[] Arguments => new[] {
15-
new CommandLineArgument("input-directory-path"),
16-
new CommandLineArgument("destination-pak-path"),
17-
new CommandLineArgument("include-pak-path", true)
19+
new CommandLineArgument(InputDirectoryPath),
20+
new CommandLineArgument(DestinationPakPath),
21+
new CommandLineArgument(IncludePakPath, ArgumentType.OptionalPositional)
1822
};
1923

2024
private class TemporaryPak : IDisposable
@@ -84,10 +88,10 @@ private void SortBundlesToPreventInvalidOrdering(ref List<FileBundle> fileBundle
8488
});
8589
}
8690

87-
public void Execute(string[] args)
91+
public void Execute(Dictionary<string, string> args)
8892
{
89-
string inputPath = args[0];
90-
string outputPackagePath = args[1];
93+
var inputPath = args[InputDirectoryPath];
94+
var outputPackagePath = args[DestinationPakPath];
9195

9296
var fileBundlesToAdd = FileBundle.BundleFilesAtPath(inputPath);
9397
SortBundlesToPreventInvalidOrdering(ref fileBundlesToAdd);
@@ -104,9 +108,9 @@ public void Execute(string[] args)
104108
});
105109

106110

107-
if (args.Length > 2)
111+
if (args.TryGetValue(IncludePakPath, out var includePackagePath))
108112
{
109-
IncludePackageIntoWriter(args[2], tempPak.Writer);
113+
IncludePackageIntoWriter(includePackagePath, tempPak.Writer);
110114
}
111115

112116
Console.WriteLine($"Packed {tempPak.Writer.FileCount} assets into {outputPackagePath}...");

Interface/Actions/UnpackAction.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ namespace FEZRepacker.Interface.Actions
99
{
1010
internal abstract class UnpackAction : CommandLineAction
1111
{
12+
private const string PakPath = "pak-path";
13+
private const string DestinationFolder = "destination-folder";
14+
1215
public enum UnpackingMode
1316
{
1417
Raw,
@@ -21,15 +24,14 @@ public enum UnpackingMode
2124
public abstract string[] Aliases { get; }
2225

2326
public CommandLineArgument[] Arguments => new[] {
24-
new CommandLineArgument("pak-path"),
25-
new CommandLineArgument("destination-folder")
27+
new CommandLineArgument(PakPath),
28+
new CommandLineArgument(DestinationFolder)
2629
};
2730

28-
public void Execute(string[] args)
31+
public void Execute(Dictionary<string, string> args)
2932
{
30-
var pakPath = args[0];
31-
var outputDir = args[1];
32-
33+
var pakPath = args[PakPath];
34+
var outputDir = args[DestinationFolder];
3335
UnpackPackage(pakPath, outputDir, Mode);
3436
}
3537

Interface/Actions/UnpackGameAction.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ namespace FEZRepacker.Interface.Actions
44
{
55
internal class UnpackGameAction : CommandLineAction
66
{
7+
private const string FezContentDirectory = "fez-content-directory";
8+
private const string DestinationFolder = "destination-folder";
9+
710
public string Name => "--unpack-fez-content";
811

912
public string[] Aliases => new[] { "-g" };
@@ -12,14 +15,14 @@ internal class UnpackGameAction : CommandLineAction
1215
"Unpacks and converts all game assets into specified directory (creates one if doesn't exist).";
1316

1417
public CommandLineArgument[] Arguments => new[] {
15-
new CommandLineArgument("fez-content-directory"),
16-
new CommandLineArgument("destination-folder")
18+
new CommandLineArgument(FezContentDirectory),
19+
new CommandLineArgument(DestinationFolder)
1720
};
1821

19-
public void Execute(string[] args)
22+
public void Execute(Dictionary<string, string> args)
2023
{
21-
var contentPath = args[0];
22-
var outputDir = args[1];
24+
var contentPath = args[FezContentDirectory];
25+
var outputDir = args[DestinationFolder];
2326

2427
var packagePaths = new string[] { "Essentials.pak", "Music.pak", "Other.pak", "Updates.pak" }
2528
.Select(path => Path.Combine(contentPath, path)).ToArray();

Interface/CommandLineAction.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ internal interface CommandLineAction
66
public string[] Aliases { get; }
77
public string Description { get; }
88
public CommandLineArgument[] Arguments { get; }
9-
public void Execute(string[] args);
9+
public void Execute(Dictionary<string, string> args);
1010

1111
}
1212
}

0 commit comments

Comments
 (0)