first commit
This commit is contained in:
125
Cli/CliArgs.cs
Normal file
125
Cli/CliArgs.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
namespace HanaToolbox.Cli;
|
||||
|
||||
/// <summary>
|
||||
/// Parsed result from the CLI argument array.
|
||||
/// Lightweight, AOT-safe, zero external dependencies.
|
||||
/// </summary>
|
||||
public sealed class CliArgs
|
||||
{
|
||||
public string Command { get; init; } = string.Empty; // e.g. "backup", "cron"
|
||||
public string SubCommand { get; init; } = string.Empty; // e.g. "setup" for "cron setup"
|
||||
public List<string> Positional { get; init; } = []; // non-flag arguments
|
||||
|
||||
public bool Verbose { get; init; }
|
||||
public string Sid { get; init; } = string.Empty;
|
||||
public bool Compress { get; init; }
|
||||
public int Threads { get; init; }
|
||||
public bool Replace { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Parses raw args into a CliArgs instance.
|
||||
///
|
||||
/// Global options: -v | --verbose
|
||||
/// --sid <SID>
|
||||
///
|
||||
/// Command-local options are also parsed here for simplicity (they are
|
||||
/// silently ignored when not applicable to the active command).
|
||||
///
|
||||
/// Usage examples:
|
||||
/// hanatoolbox backup --verbose --sid NDB
|
||||
/// hanatoolbox export MYSCHEMA /hana/backup -c -t 4
|
||||
/// hanatoolbox import-rename SRC DST /path --replace
|
||||
/// hanatoolbox cron setup
|
||||
/// </summary>
|
||||
public static CliArgs Parse(string[] args)
|
||||
{
|
||||
var positional = new List<string>();
|
||||
var verbose = false;
|
||||
var sid = string.Empty;
|
||||
var compress = false;
|
||||
var threads = 0;
|
||||
var replace = false;
|
||||
|
||||
var command = string.Empty;
|
||||
var subCommand = string.Empty;
|
||||
|
||||
int i = 0;
|
||||
|
||||
// First token that is not a flag is the command
|
||||
// second non-flag token after that may be the subcommand (for "cron setup")
|
||||
while (i < args.Length)
|
||||
{
|
||||
var a = args[i];
|
||||
|
||||
switch (a)
|
||||
{
|
||||
case "-v" or "--verbose":
|
||||
verbose = true;
|
||||
i++;
|
||||
break;
|
||||
|
||||
case "--sid" when i + 1 < args.Length:
|
||||
sid = args[++i];
|
||||
i++;
|
||||
break;
|
||||
|
||||
case "-c" or "--compress":
|
||||
compress = true;
|
||||
i++;
|
||||
break;
|
||||
|
||||
case "--replace":
|
||||
replace = true;
|
||||
i++;
|
||||
break;
|
||||
|
||||
case "-t" or "--threads" when i + 1 < args.Length:
|
||||
int.TryParse(args[++i], out threads);
|
||||
i++;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!a.StartsWith('-'))
|
||||
{
|
||||
if (string.IsNullOrEmpty(command))
|
||||
command = a;
|
||||
else if (string.IsNullOrEmpty(subCommand) && positional.Count == 0)
|
||||
// Peek: is this a known subcommand for the current command?
|
||||
subCommand = MaybeSubCommand(command, a) ? a : AddPositional(positional, a);
|
||||
else
|
||||
positional.Add(a);
|
||||
}
|
||||
// Unknown flag — silently skip
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new CliArgs
|
||||
{
|
||||
Command = command,
|
||||
SubCommand = subCommand,
|
||||
Positional = positional,
|
||||
Verbose = verbose,
|
||||
Sid = sid,
|
||||
Compress = compress,
|
||||
Threads = threads,
|
||||
Replace = replace,
|
||||
};
|
||||
}
|
||||
|
||||
// ── Helpers ───────────────────────────────────────────────────────────────
|
||||
|
||||
private static bool MaybeSubCommand(string command, string token) =>
|
||||
command == "cron" && token == "setup";
|
||||
|
||||
private static string AddPositional(List<string> list, string value)
|
||||
{
|
||||
list.Add(value);
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>Gets positional arg at index, or empty string if not present.</summary>
|
||||
public string Pos(int index) =>
|
||||
index < Positional.Count ? Positional[index] : string.Empty;
|
||||
}
|
||||
Reference in New Issue
Block a user