using CommandLine; using Dinah.Core; using FileManager; using LibationFileManager; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading.Tasks; #nullable enable namespace LibationCli.Options; [Verb("get-setting", HelpText = "List current settings files and their locations.")] internal class GetSettingOptions : OptionsBase { [Option('l', "listEnumValues", HelpText = "List all value possibilities of enum types")] public bool ListEnumValues { get; set; } [Option('b', "bare", HelpText = "Print bare list without table decoration")] public bool Bare { get; set; } [Value(0, MetaName = "[setting names]", HelpText = "Optional names of settings to get.")] public IEnumerable? SettingNames { get; set; } protected override Task ProcessAsync() { var configs = GetConfigOptions(); if (SettingNames?.Any() is true) { //Operate over listed settings foreach (var item in SettingNames.ExceptBy(configs.Select(c => c.Name), c => c, StringComparer.OrdinalIgnoreCase)) { Console.Error.WriteLine($"Unknown Setting Name: {item}"); } var validSettings = configs.IntersectBy(SettingNames, a => a.Name, StringComparer.OrdinalIgnoreCase); if (ListEnumValues) { foreach (var item in validSettings.Where(s => !s.SettingType.IsEnum)) { Console.Error.WriteLine($"Setting '{item.Name}' is not an enum type"); } PrintEnumValues(validSettings.Where(s => s.SettingType.IsEnum)); } else { PrintConfigOption(validSettings); } } else { //Operate over all settings if (ListEnumValues) { PrintEnumValues(configs); } else { PrintConfigOption(configs); } } return Task.CompletedTask; } private void PrintConfigOption(IEnumerable options) { if (Bare) { foreach (var option in options) { Console.WriteLine($"{option.Name}={option.Value}"); } } else { Console.Out.DrawTable(options, new(), o => o.Name, o => o.Value, o => o.Type); } } private void PrintEnumValues(IEnumerable options) { foreach (var item in options.Where(s => s.SettingType.IsEnum)) { var enumValues = Enum.GetNames(item.SettingType); if (Bare) { Console.WriteLine(string.Join(Environment.NewLine, enumValues.Select(e => $"{item.Name}.{e}"))); } else { Console.Out.DrawTable(enumValues, new TextTableOptions(), new ColumnDef(item.Name, t => t)); } } } private ConfigOption[] GetConfigOptions() { var configs = GetConfigurationProperties().Where(o=> o.PropertyType != typeof(ReplacementCharacters)).Select(p => new ConfigOption(p)); var replacements = GetConfigurationProperties().SingleOrDefault(o => o.PropertyType == typeof(ReplacementCharacters))?.GetValue(Configuration.Instance) as ReplacementCharacters; if (replacements is not null) { //Don't reorder after concat to keep replacements grouped together at the bottom configs = configs.Concat(replacements.Replacements.Select(r => new ConfigOption(r))); } return configs.ToArray(); } private record EnumOption(string EnumOptionValue); private record ConfigOption { public string Name { get; } public string Type { get; } public Type SettingType { get; } public string Value { get; } public ConfigOption(PropertyInfo propertyInfo) { Name = propertyInfo.Name; SettingType = propertyInfo.PropertyType; Type = GetTypeString(SettingType); Value = propertyInfo.GetValue(Configuration.Instance)?.ToString() is not string value ? "[null]" : SettingType == typeof(string) || SettingType == typeof(LongPath) ? value.SurroundWithQuotes() : value; } public ConfigOption(Replacement replacement) { Name = GetReplacementName(replacement); SettingType = typeof(string); Type = GetTypeString(SettingType); Value = replacement.ReplacementString.SurroundWithQuotes(); } private static string GetTypeString(Type type) => type.IsEnum ? $"{type.Name} (enum)": type.Name; } }