#nullable enable using System; using System.Collections.Generic; using System.Linq; using System.Threading; using Cysharp.Threading.Tasks; namespace ShrinkCommand { public enum ShrinkCommandSourceKind { Any = 0, ConsoleOnly = 1, NonConsoleOnly = 2 } public interface IShrinkCommandSource { string SourceId { get; } string DisplayName { get; } bool IsConsole { get; } bool HasPermission(string permission); UniTask WriteLineAsync(string message, CancellationToken cancellationToken = default); } public sealed class ShrinkCommandExecutionResult { public bool IsSuccess { get; private set; } public string Message { get; private set; } = string.Empty; public static ShrinkCommandExecutionResult Success(string message = "") { return new ShrinkCommandExecutionResult { IsSuccess = true, Message = message ?? string.Empty }; } public static ShrinkCommandExecutionResult Failure(string message) { return new ShrinkCommandExecutionResult { IsSuccess = false, Message = message ?? string.Empty }; } } public sealed class ShrinkCommandDescriptor { public string Path { get; set; } = string.Empty; public IReadOnlyList Aliases { get; set; } = Array.Empty(); public string Description { get; set; } = string.Empty; public string Permission { get; set; } = string.Empty; public ShrinkCommandSourceKind SourceKind { get; set; } public bool Hidden { get; set; } public IReadOnlyList GetAllPaths() { if (Aliases == null || Aliases.Count == 0) return new[] { Path }; return new[] { Path }.Concat(Aliases).ToArray(); } } public sealed class ShrinkCommandRegistration { public string Path { get; set; } = string.Empty; public string[] Aliases { get; set; } = Array.Empty(); public string Description { get; set; } = string.Empty; public string Permission { get; set; } = string.Empty; public ShrinkCommandSourceKind SourceKind { get; set; } = ShrinkCommandSourceKind.Any; public bool Hidden { get; set; } public Func> Handler { get; set; } = _ => UniTask.FromResult(ShrinkCommandExecutionResult.Success()); } public sealed class ShrinkCommandContext { private readonly IReadOnlyDictionary _arguments; internal ShrinkCommandContext( ShrinkCommandService service, IShrinkCommandSource source, ShrinkCommandDescriptor command, string rawInput, IReadOnlyDictionary arguments, CancellationToken cancellationToken) { Service = service; Source = source; Command = command; RawInput = rawInput ?? string.Empty; _arguments = arguments ?? new Dictionary(StringComparer.OrdinalIgnoreCase); CancellationToken = cancellationToken; } public ShrinkCommandService Service { get; } public IShrinkCommandSource Source { get; } public ShrinkCommandDescriptor Command { get; } public string RawInput { get; } public CancellationToken CancellationToken { get; } public IReadOnlyDictionary Arguments => _arguments; public string GetArgument(string name, string fallback = "") { if (string.IsNullOrWhiteSpace(name)) return fallback; return _arguments.TryGetValue(name.Trim(), out var value) ? value : fallback; } public UniTask ReplyAsync(string message) { return Source.WriteLineAsync(message ?? string.Empty, CancellationToken); } } public sealed class ShrinkCommandExecutingInfo { public ShrinkCommandService Service { get; set; } = null!; public IShrinkCommandSource Source { get; set; } = null!; public ShrinkCommandDescriptor Command { get; set; } = null!; public string RawInput { get; set; } = string.Empty; public IReadOnlyDictionary Arguments { get; set; } = new Dictionary(StringComparer.OrdinalIgnoreCase); } public sealed class ShrinkCommandExecutedInfo { public ShrinkCommandService Service { get; set; } = null!; public IShrinkCommandSource Source { get; set; } = null!; public ShrinkCommandDescriptor? Command { get; set; } public string RawInput { get; set; } = string.Empty; public IReadOnlyDictionary Arguments { get; set; } = new Dictionary(StringComparer.OrdinalIgnoreCase); public ShrinkCommandExecutionResult Result { get; set; } = ShrinkCommandExecutionResult.Success(); } }