Files
RTCSync/RTCSync.cli/Options/OptionDispatcher.cs
T
2026-06-25 12:19:29 +03:00

146 lines
4.7 KiB
C#

namespace RTCSync.Options;
public class OptionDispatcher
{
private readonly Dictionary<string, IOption> _registredOptions = new();
public void Register(IOption option)
{
foreach (var optionName in option.OptionNames)
{
_registredOptions[optionName] = option;
}
}
public void Execute(string[] args)
{
if (args.Length == 0)
{
PrintHelp();
return;
}
var flag = args[0];
if (!_registredOptions.TryGetValue(flag, out var command))
{
Console.WriteLine($"Неизвестный параметр: {flag}");
PrintHelp();
return;
}
// Парсим все остальные аргументы как опции
var commandArgs = ParseArguments(args.Skip(1).ToArray());
command.Execute(commandArgs);
}
private static OptionArgs ParseArguments(string[] args)
{
var optionValues = new Dictionary<string, string>();
for (var i = 0; i < args.Length; i++)
{
if (!args[i].StartsWith("--"))
{
optionValues.Add("unnamed", args[i]);
continue;
}
optionValues[args[i]] = args[i + 1];
i++;
}
return new OptionArgs
{
OptionValues = optionValues,
Arguments = []
};
}
private static void PrintOption(string optionLine, string description)
{
var terminalWidth = Console.WindowWidth;
// Console.WriteLine(terminalWidth);
// for (var i = 0; i < terminalWidth; i++)
// Console.Write("_");
// Console.WriteLine();
const int columnWidth = 44;
var descriptionWidth = terminalWidth - columnWidth;
// Если название опции слишком длиное, перенести описание на следующую строку
if (optionLine.Length > columnWidth)
{
Console.WriteLine(optionLine);
var lines = SplitText(description, descriptionWidth);
foreach (var line in lines)
{
Console.WriteLine($"{new string(' ', 2)}{line}");
}
return;
}
var formatted = optionLine.PadRight(columnWidth);
var descLines = SplitText(description, descriptionWidth);
// Первая строка с опцией и началом описания
Console.WriteLine($"{formatted}{descLines[0]}");
// Остальные строки описания с выравниванием
for (var i = 1; i < descLines.Count; i++)
{
Console.WriteLine($"{new string(' ', columnWidth)}{descLines[i]}");
}
Console.WriteLine();
}
private static List<string> SplitText(string text, int maxWidth)
{
var lines = new List<string>();
if (maxWidth < 1) return [text];
var words = text.Split(' ');
var current = "";
foreach (var word in words)
{
if ((current + word + " ").Length <= maxWidth)
{
current += word + " ";
}
else
{
if (!string.IsNullOrEmpty(current))
lines.Add(current.TrimEnd());
current = word + " ";
}
}
if (!string.IsNullOrEmpty(current))
lines.Add(current.TrimEnd());
return lines.Count > 0 ? lines : [text];
}
private void PrintHelp()
{
Console.WriteLine("RTCSync - утилита для работы с часами реального времени DS3231, подключенными по шине I^2C через CH431. Требует winusb драйвер.\n");
Console.WriteLine("Использование: RTCSync.cli.exe <параметр> [опции]\n");
Console.WriteLine("Параметры:");
foreach (var cmd in _registredOptions.Values.Distinct())
{
var optionNames = cmd.OptionNames.Aggregate((current, next) => current + ", " + next);
var optionLine = $" {optionNames} {cmd.OptionValues}";
PrintOption(optionLine, cmd.Description);
// Console.WriteLine($" {cmd.OptionNames.Aggregate((current, next) => current + $" {cmd.OptionValues}, " + next + $" {cmd.OptionValues}"), -54} {cmd.Description}");
}
Console.WriteLine("\nПримеры:");
Console.WriteLine(" RTCSync.cli.exe --set-time");
Console.WriteLine(" RTCSync.cli.exe -s");
Console.WriteLine(" RTCSync.cli.exe --set-time 0");
Console.WriteLine(" RTCSync.cli.exe -s 0");
}
}