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 NameListFormat : IListFormat { public static string Formatter(ITemplateTag _, IEnumerable? names, string formatString, CultureInfo? culture) => names is null ? string.Empty : IListFormat.Join(formatString, Sort(names, formatString, ContributorDto.FormatReplacements), culture); private static IEnumerable Sort(IEnumerable entries, string formatString, Dictionary> formatReplacements) { var sortMatch = SortRegex().Match(formatString); if (!sortMatch.Success) return entries; IOrderedEnumerable? ordered = null; foreach (Match m in SortTokenizer().Matches(sortMatch.Groups["pattern"].Value)) { // Dictionary is case-insensitive, no ToUpper needed if (!formatReplacements.TryGetValue(m.Groups["token"].Value, out var selector)) continue; ordered = ordered is null // ReSharper disable once PossibleMultipleEnumeration ? entries.OrderBy(selector) : ordered.ThenBy(selector); } return ordered ?? entries; } private const string Token = @"(?:[TFMLS]|ID)"; /// Sort must have at least one of the token labels T, F, M, L, S or ID.Add multiple tokens to sort by multiple fields. Spaces may be used to separate tokens. [GeneratedRegex($@"[Ss]ort\(\s*(?i:(?(?:{Token}\s*?)+))\s*\)")] private static partial Regex SortRegex(); [GeneratedRegex($@"\G(?{Token})\s*", RegexOptions.IgnoreCase)] private static partial Regex SortTokenizer(); /// Format must have at least one of the string {T}, {F}, {M}, {L}, {S}, or {ID} [GeneratedRegex($@"[Ff]ormat\((.*?\{{{Token}(?::.*?)?\}}.*?)\)")] public static partial Regex FormatRegex(); }