using System; using FileManager.NamingTemplate; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text.RegularExpressions; namespace LibationFileManager.Templates; internal partial class StringListFormat : IListFormat { public static IEnumerable Formatter(ITemplateTag _, IEnumerable? entries, string? formatString, CultureInfo? culture) => entries is null ? [] : IListFormat.FormattedList(formatString, Sort(entries, formatString, StringDto.FormatReplacements), culture); public static string? Finalizer(ITemplateTag _, IEnumerable? entries, CultureInfo? culture) => IListFormat.Join(entries, culture); private static IEnumerable Sort(IEnumerable entries, string? formatString, Dictionary> formatReplacements) { var pattern = formatString is null ? null : SortRegex().Match(formatString).ResolveValue("pattern"); if (pattern is null) return entries; IOrderedEnumerable? ordered = null; foreach (Match m in SortTokenizer().Matches(pattern)) { // Dictionary is case-insensitive, no ToUpper needed if (!formatReplacements.TryGetValue(m.Groups["token"].Value, out var selector)) continue; ordered = m.Groups["descending"].Success ? ordered is null // ReSharper disable once PossibleMultipleEnumeration ? entries.OrderByDescending(selector) : ordered.ThenByDescending(selector) : ordered is null // ReSharper disable once PossibleMultipleEnumeration ? entries.OrderBy(selector) : ordered.ThenBy(selector); } return ordered ?? entries; } private const string Token = "S"; /// Sort must have the token label S. Use lower case for descending direction. [GeneratedRegex($@"[Ss]ort\(\s*(?i:(?(?:{Token}\s*?)+))\s*\)")] private static partial Regex SortRegex(); [GeneratedRegex($@"\G(?{Token})(?(?-i:(?<=\G\P{{Lu}}+)))?\s*", RegexOptions.IgnoreCase)] private static partial Regex SortTokenizer(); /// Format must have the string {S} (optionally with formatting like {S:u}) [GeneratedRegex($@"[Ff]ormat\((?.*?\{{{Token}(?::.*?)?\}}.*?)\)")] public static partial Regex FormatRegex(); }