Browse Source

Improved IPA argument parsing (again)

refactor
Anairkoen Schno 6 years ago
parent
commit
e2a2ae1a88
2 changed files with 134 additions and 17 deletions
  1. +105
    -4
      IPA/Arguments.cs
  2. +29
    -13
      IPA/Program.cs

+ 105
- 4
IPA/Arguments.cs View File

@ -1,22 +1,44 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace IPA
namespace IPA.ArgParsing
{
public class Arguments
{
public static Arguments Process = new Arguments(Environment.GetCommandLineArgs());
public static Arguments CmdLine = new Arguments(Environment.GetCommandLineArgs());
private List<string> positional = new List<string>();
private Dictionary<string, string> longFlags = new Dictionary<string, string>();
private Dictionary<char, string> flags = new Dictionary<char, string>();
private List<ArgumentFlag> flagObjects = new List<ArgumentFlag>();
private string[] toParse = null;
private Arguments(string[] args)
{
foreach(var arg in args)
toParse = args;
}
public Arguments Flags(params ArgumentFlag[] toAdd)
{
foreach (var f in toAdd) AddFlag(f);
return this;
}
public void AddFlag(ArgumentFlag toAdd)
{
if (toParse == null) throw new InvalidOperationException();
flagObjects.Add(toAdd);
}
public void Process()
{
foreach (var arg in toParse)
{
if (arg.StartsWith("--"))
{ // parse as a long flag
@ -27,7 +49,7 @@ namespace IPA
{
var spl = name.Split('=');
name = spl[0];
value = string.Join("=", spl, 1, spl.Length-1);
value = string.Join("=", spl, 1, spl.Length - 1);
}
longFlags.Add(name, value);
@ -73,6 +95,31 @@ namespace IPA
positional.Add(arg);
}
}
toParse = null;
foreach (var flag in flagObjects)
{
foreach (var chflag in flag.shortFlags)
{
if (flag.exists = HasFlag(chflag))
{
flag.value = GetFlagValue(chflag);
goto FoundValue; // continue to next flagObjects item
}
}
foreach (var lflag in flag.longFlags)
{
if (flag.exists = HasLongFlag(lflag))
{
flag.value = GetLongFlagValue(lflag);
goto FoundValue; // continue to next flagObjects item
}
}
FoundValue:;
}
}
public bool HasLongFlag(string flag)
@ -95,6 +142,60 @@ namespace IPA
return flags[flag];
}
public void PrintHelp()
{
const string indent = " ";
string filename = Path.GetFileName(Assembly.GetExecutingAssembly().Location);
string format = @"help:
{2}{0} [FLAGS] [ARGUMENTS]
flags:
{1}";
var flagsBuilder = new StringBuilder();
foreach (var flag in flagObjects)
{
flagsBuilder.AppendFormat("{2}{0}{1}",
string.Join(", ", flag.shortFlags.Select(s => $"-{s}").Concat( flag.longFlags.Select(s => $"--{s}")) ),
Environment.NewLine, indent);
flagsBuilder.AppendFormat("{2}{2}{0}{1}", flag.DocString, Environment.NewLine, indent);
}
Console.Write(string.Format(format, filename, flagsBuilder.ToString(), indent));
}
public IReadOnlyList<string> PositionalArgs => positional;
}
public class ArgumentFlag
{
internal List<char> shortFlags = new List<char>();
internal List<string> longFlags = new List<string>();
internal string value = null;
internal bool exists = false;
public ArgumentFlag(params string[] flags)
{
foreach (var part in flags)
AddPart(part);
}
private void AddPart(string flagPart)
{
if (flagPart.StartsWith("--"))
longFlags.Add(flagPart.Substring(2));
else if (flagPart.StartsWith("-"))
shortFlags.Add(flagPart[1]);
}
public bool Exists => exists;
public string Value => value;
public string DocString { get; set; } = "";
public static implicit operator bool(ArgumentFlag f)
{
return f.Exists;
}
}
}

+ 29
- 13
IPA/Program.cs View File

@ -9,6 +9,7 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using IPA.ArgParsing;
namespace IPA {
public class Program {
@ -20,13 +21,29 @@ namespace IPA {
private static Version Version => Assembly.GetEntryAssembly().GetName().Version;
public static ArgumentFlag ArgHelp = new ArgumentFlag("--help", "-h") { DocString = "prints this message" };
public static ArgumentFlag ArgWaitFor = new ArgumentFlag("--waitfor") { DocString = "waits for the specified PID to exit" };
public static ArgumentFlag ArgForce = new ArgumentFlag("--force", "-f") { DocString = "forces the operation to go through" };
public static ArgumentFlag ArgRevert = new ArgumentFlag("--revert") { DocString = "reverts the IPA installation" };
public static ArgumentFlag ArgNoWait = new ArgumentFlag("--nowait") { DocString = "doesn't wait for user input after the operation" };
public static ArgumentFlag ArgStart = new ArgumentFlag("--start") { DocString = "uses value as arguments to start the game after the patch/unpatch" };
public static ArgumentFlag ArgLaunch = new ArgumentFlag("--launch") { DocString = "uses positional parameters as arguments to start the game after patch/unpatch" };
static void Main(string[] args)
{
Arguments.CmdLine.Flags(ArgHelp, ArgWaitFor, ArgForce, ArgRevert, ArgNoWait, ArgStart, ArgLaunch).Process();
if (ArgHelp)
{
Arguments.CmdLine.PrintHelp();
return;
}
try
{
if (Arguments.Process.HasLongFlag("waitfor") && Arguments.Process.GetLongFlagValue("waitfor") != null)
if (ArgWaitFor && ArgWaitFor.Value != null)
{
int pid = int.Parse(Arguments.Process.GetLongFlagValue("waitfor"));
int pid = int.Parse(ArgWaitFor.Value);
try
{ // wait for beat saber to exit (ensures we can modify the file)
@ -41,7 +58,7 @@ namespace IPA {
PatchContext context;
var argExeName = Arguments.Process.PositionalArgs.FirstOrDefault(s => s.EndsWith(".exe"));
var argExeName = Arguments.CmdLine.PositionalArgs.FirstOrDefault(s => s.EndsWith(".exe"));
if (argExeName == null)
{
@ -55,7 +72,7 @@ namespace IPA {
context = PatchContext.Create(argExeName);
}
bool isRevert = Arguments.Process.HasLongFlag("revert") || Keyboard.IsKeyDown(Keys.LMenu);
bool isRevert = ArgRevert || Keyboard.IsKeyDown(Keys.LMenu);
// Sanitizing
Validate(context);
@ -107,8 +124,7 @@ namespace IPA {
var nativePluginFolder = Path.Combine(context.DataPathDst, "Plugins");
bool isFlat = Directory.Exists(nativePluginFolder) &&
Directory.GetFiles(nativePluginFolder).Any(f => f.EndsWith(".dll"));
bool force = !BackupManager.HasBackup(context) || Arguments.Process.HasFlag('f') ||
Arguments.Process.HasLongFlag("force");
bool force = !BackupManager.HasBackup(context) || ArgForce;
var architecture = DetectArchitecture(context.Executable);
Console.WriteLine("Architecture: {0}", architecture);
@ -202,7 +218,7 @@ namespace IPA {
}
if (!Arguments.Process.HasLongFlag("nowait"))
if (!ArgNoWait)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Finished!");
@ -232,7 +248,7 @@ namespace IPA {
Console.WriteLine("");
Console.WriteLine("--- Done reverting ---");
if (!Arguments.Process.HasLongFlag("nowait") && !isNewVersion) {
if (!ArgNoWait && !isNewVersion) {
Console.WriteLine("\n\n[Press any key to quit]");
Console.ReadKey();
}
@ -241,17 +257,17 @@ namespace IPA {
}
private static void StartIfNeedBe(PatchContext context) {
if (Arguments.Process.HasLongFlag("start") && Arguments.Process.GetLongFlagValue("start") != null)
if (ArgStart && ArgStart.Value != null)
{
Process.Start(context.Executable, Arguments.Process.GetLongFlagValue("start"));
Process.Start(context.Executable, ArgStart.Value);
}
else
{
var argList = Arguments.Process.PositionalArgs.ToList();
var argList = Arguments.CmdLine.PositionalArgs.ToList();
argList.Remove(context.Executable);
if (Arguments.Process.HasLongFlag("launch"))
if (ArgLaunch)
{
Process.Start(context.Executable, Args(argList.ToArray()));
}
@ -332,7 +348,7 @@ namespace IPA {
static void Fail(string message) {
Console.Error.Write("ERROR: " + message);
if (!Arguments.Process.HasLongFlag("nowait")) {
if (!ArgNoWait) {
Console.WriteLine("\n\n[Press any key to quit]");
Console.ReadKey();
}


Loading…
Cancel
Save