From d2cb14b49bc60458a799ee3a27dff667ab4f03fd Mon Sep 17 00:00:00 2001 From: CodeConscious <50596087+codeconscious@users.noreply.github.com> Date: Sat, 15 Nov 2025 10:54:24 +0900 Subject: [PATCH 1/6] Upgrade projects to .NET 10 --- src/AudioTagger.Console/AudioTagger.Console.csproj | 4 ++-- src/AudioTagger.Library/AudioTagger.Library.csproj | 2 +- src/AudioTagger.Tests/AudioTagger.Tests.csproj | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/AudioTagger.Console/AudioTagger.Console.csproj b/src/AudioTagger.Console/AudioTagger.Console.csproj index 57574a5..b309ab8 100644 --- a/src/AudioTagger.Console/AudioTagger.Console.csproj +++ b/src/AudioTagger.Console/AudioTagger.Console.csproj @@ -1,7 +1,7 @@ Exe - net9.0 + net10.0 disable enable Audiotagger.Console @@ -30,4 +30,4 @@ - \ No newline at end of file + diff --git a/src/AudioTagger.Library/AudioTagger.Library.csproj b/src/AudioTagger.Library/AudioTagger.Library.csproj index a97d22d..ffe86e8 100644 --- a/src/AudioTagger.Library/AudioTagger.Library.csproj +++ b/src/AudioTagger.Library/AudioTagger.Library.csproj @@ -1,6 +1,6 @@ - net9.0 + net10.0 disable enable diff --git a/src/AudioTagger.Tests/AudioTagger.Tests.csproj b/src/AudioTagger.Tests/AudioTagger.Tests.csproj index a68b25e..7901c85 100644 --- a/src/AudioTagger.Tests/AudioTagger.Tests.csproj +++ b/src/AudioTagger.Tests/AudioTagger.Tests.csproj @@ -1,6 +1,6 @@ - net9.0 + net10.0 disable enable false From d8b613ce1471dafa0821d90f535980d8f07ca7af Mon Sep 17 00:00:00 2001 From: CodeConscious <50596087+codeconscious@users.noreply.github.com> Date: Sat, 15 Nov 2025 11:06:48 +0900 Subject: [PATCH 2/6] Use extension members --- src/AudioTagger.Console/Extensions.cs | 37 ++++++++++++--------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/src/AudioTagger.Console/Extensions.cs b/src/AudioTagger.Console/Extensions.cs index 3f1338f..453e354 100644 --- a/src/AudioTagger.Console/Extensions.cs +++ b/src/AudioTagger.Console/Extensions.cs @@ -2,27 +2,24 @@ namespace AudioTagger.Console; public static class Extensions { - /// - /// Determines whether a collection is empty. - /// - public static bool None(this IEnumerable collection) => - !collection.Any(); + extension(IEnumerable collection) + { + public bool None() => + !collection.Any(); - /// - /// Determines whether no elements of a sequence satisfy a given condition. - /// - public static bool None(this IEnumerable collection, Func predicate) => - !collection.Any(predicate); + public bool None(Func predicate) => + !collection.Any(predicate); + } - /// - /// Returns a bool indicating whether a string is not null and has text (true) or not. - /// - public static bool HasText(this string? str) => !string.IsNullOrWhiteSpace(str); + extension(string? str) + { + public bool HasText() => !string.IsNullOrWhiteSpace(str); - public static string? TextOrNull(this string? text) => - text switch - { - null or { Length: 0 } => null, - _ => text - }; + public string? TextOrNull() => + str switch + { + null or { Length: 0 } => null, + _ => str + }; + } } From 13bdd16d623187f2b642c69293be38e2f6368539 Mon Sep 17 00:00:00 2001 From: CodeConscious <50596087+codeconscious@users.noreply.github.com> Date: Sat, 15 Nov 2025 11:14:52 +0900 Subject: [PATCH 3/6] Various tweaks --- src/AudioTagger.Console/GetUserInput.cs | 7 ++++--- src/AudioTagger.Console/MediaFilePathInfo.cs | 2 +- src/AudioTagger.Console/MediaFileViewer.cs | 6 +++--- src/AudioTagger.Console/Operations/TagViewer.cs | 2 +- src/AudioTagger.Console/Program.cs | 7 ++++--- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/AudioTagger.Console/GetUserInput.cs b/src/AudioTagger.Console/GetUserInput.cs index 8715528..36e684a 100644 --- a/src/AudioTagger.Console/GetUserInput.cs +++ b/src/AudioTagger.Console/GetUserInput.cs @@ -26,9 +26,10 @@ public static class ResponseHandler /// /// Ask the user a question that they can answer with a single keystroke. /// - private static UserResponse AskUserQuestion(IReadOnlyList question, - IReadOnlyList allowedResponses, - IPrinter printer) + private static UserResponse AskUserQuestion( + IReadOnlyList question, + IReadOnlyList allowedResponses, + IPrinter printer) { if (question.None()) { diff --git a/src/AudioTagger.Console/MediaFilePathInfo.cs b/src/AudioTagger.Console/MediaFilePathInfo.cs index 1def957..015dac4 100644 --- a/src/AudioTagger.Console/MediaFilePathInfo.cs +++ b/src/AudioTagger.Console/MediaFilePathInfo.cs @@ -1,7 +1,7 @@ namespace AudioTagger.Console; /// -/// Contains all of the path information for a specific MediaFile. +/// Contains all the path information for a specific MediaFile. /// internal sealed class MediaFilePathInfo { diff --git a/src/AudioTagger.Console/MediaFileViewer.cs b/src/AudioTagger.Console/MediaFileViewer.cs index 6cd996c..92b4a00 100644 --- a/src/AudioTagger.Console/MediaFileViewer.cs +++ b/src/AudioTagger.Console/MediaFileViewer.cs @@ -5,7 +5,7 @@ namespace AudioTagger.Console; public sealed class MediaFileViewer { - public void PrintFileDetails(MediaFile file) + public static void PrintFileDetails(MediaFile file) { // TODO: Handle colors more gracefully. string TagNameFormatter(string s) => "[grey]" + s + "[/]"; @@ -30,7 +30,7 @@ public void PrintFileDetails(MediaFile file) table.AddRow(TagNameFormatter("Year"), file.Year.ToString()); table.AddRow(TagNameFormatter("Duration"), file.Duration.ToString("m\\:ss")); - int genreCount = file.Genres.Length; + var genreCount = file.Genres.Length; table.AddRow(TagNameFormatter("Genres"), file.Genres.Join().EscapeMarkup() + (genreCount > 1 ? $" ({genreCount})" : string.Empty)); @@ -82,7 +82,7 @@ public static TableRow PrintFileSummary(MediaFile file) file.ReplayGainTrack.ToString(CultureInfo.InvariantCulture) }; - IEnumerable markups = rows.Select(r => new Markup(r)); + var markups = rows.Select(r => new Markup(r)); return new TableRow(markups); } diff --git a/src/AudioTagger.Console/Operations/TagViewer.cs b/src/AudioTagger.Console/Operations/TagViewer.cs index f6abe36..1aab503 100644 --- a/src/AudioTagger.Console/Operations/TagViewer.cs +++ b/src/AudioTagger.Console/Operations/TagViewer.cs @@ -17,7 +17,7 @@ public void Start(IReadOnlyCollection mediaFiles, { //printer.Print(OutputLine.GetTagPrintedLines(mediaFile)); var viewer = new MediaFileViewer(); - viewer.PrintFileDetails(mediaFile); + MediaFileViewer.PrintFileDetails(mediaFile); #if _WINDOWS if (mediaFile.AlbumArt.Length > 0) diff --git a/src/AudioTagger.Console/Program.cs b/src/AudioTagger.Console/Program.cs index ab8f978..8098e92 100644 --- a/src/AudioTagger.Console/Program.cs +++ b/src/AudioTagger.Console/Program.cs @@ -97,6 +97,7 @@ private static void ProcessPath( } ImmutableArray fileNames = fileNameResult.Value; + if (fileNames.IsEmpty) { printer.Warning($"No files were found in \"{path}\"."); @@ -107,8 +108,8 @@ private static void ProcessPath( var (mediaFiles, tagReadErrors) = ReadTagsShowingProgress(fileNames); - int successes = fileNames.Length - tagReadErrors.Count; - printer.Print($"Tags of {successes:#,##0} files read in {watch.ElapsedFriendly}."); + var successCount = fileNames.Length - tagReadErrors.Count; + printer.Print($"Tags of {successCount:#,##0} files read in {watch.ElapsedFriendly}."); if (tagReadErrors.Count != 0) { @@ -213,7 +214,7 @@ private static void PrintInstructions(IPrinter printer) private static (ImmutableList Valid, ImmutableList Invalid) CheckPaths( ICollection paths) { - if (paths.Any() != true) + if (paths.Count == 0) { return new ([], []); } From d240d38b751c0820626a2f4fe43d4e589b04316b Mon Sep 17 00:00:00 2001 From: CodeConscious <50596087+codeconscious@users.noreply.github.com> Date: Sat, 15 Nov 2025 11:27:54 +0900 Subject: [PATCH 4/6] Various tweaks to Operations --- .../Operations/MediaFileRenamer.cs | 15 +++------- .../Operations/TagDuplicateFinder.cs | 8 ++--- .../Operations/TagUpdater.cs | 4 +-- .../Operations/TagUpdaterMultiple.cs | 16 +++------- .../Operations/TagUpdaterSingle.cs | 29 +++++-------------- .../Operations/TagViewer.cs | 2 +- 6 files changed, 23 insertions(+), 51 deletions(-) diff --git a/src/AudioTagger.Console/Operations/MediaFileRenamer.cs b/src/AudioTagger.Console/Operations/MediaFileRenamer.cs index 8c7a634..56ee715 100644 --- a/src/AudioTagger.Console/Operations/MediaFileRenamer.cs +++ b/src/AudioTagger.Console/Operations/MediaFileRenamer.cs @@ -281,20 +281,15 @@ private static bool RenameSingleFile( return shouldCancel; - /// - /// Generates and returns a new filename by replacing placeholders within the rename - /// pattern (e.g., `%ALBUM%`) with actual tag data from the `MediaFile`. - /// + // Generates and returns a new filename by replacing placeholders within the rename + // pattern (e.g., `%ALBUM%`) with actual tag data from the `MediaFile`. static string GenerateFileName( MediaFile file, ICollection fileTagNames, string renamePattern) { StringBuilder workingFileName = - fileTagNames.Aggregate( - new StringBuilder(renamePattern), - (workingName, tagName) => ReplacePlaceholders(workingName, tagName) - ); + fileTagNames.Aggregate(new StringBuilder(renamePattern), ReplacePlaceholders); var ext = Path.GetExtension(file.FileNameOnly); var unsanitizedName = workingFileName + ext; @@ -333,9 +328,7 @@ StringBuilder ReplacePlaceholders(StringBuilder workingName, string tagName) } } - /// - /// Generates and returns a directory name for a file given its tags. Never returns null. - /// + // Generates and returns a directory name for a file given its tags. Never returns null. static string GenerateSafeDirectoryName(MediaFile file) { if (MediaFile.HasAnyValues(file.AlbumArtists)) diff --git a/src/AudioTagger.Console/Operations/TagDuplicateFinder.cs b/src/AudioTagger.Console/Operations/TagDuplicateFinder.cs index d37f821..1b4395a 100644 --- a/src/AudioTagger.Console/Operations/TagDuplicateFinder.cs +++ b/src/AudioTagger.Console/Operations/TagDuplicateFinder.cs @@ -39,7 +39,7 @@ public void Start( string artistLabel = PluralizeTerm(artistReplacements.Count); printer.Print($"Found {artistReplacements.Count} artist replacement {artistLabel}."); - var titleReplacements = settings.Duplicates?.TitleReplacements ?? []; + var titleReplacements = settings.Duplicates.TitleReplacements ?? []; string titleLabel = PluralizeTerm(titleReplacements.Count); printer.Print($"Found {titleReplacements.Count} title replacement {titleLabel}."); @@ -64,9 +64,9 @@ public void Start( printer.Print($"Found {groupCount} duplicate {groupLabel} in {watch.ElapsedFriendly}."); PrintResults(duplicateGroups, printer); - string? searchFor = settings.Duplicates?.PathSearchFor?.TextOrNull(); - string? replaceWith = settings.Duplicates?.PathReplaceWith?.TextOrNull(); - string? saveDir = settings?.Duplicates?.SavePlaylistDirectory; + string? searchFor = settings.Duplicates.PathSearchFor?.TextOrNull(); + string? replaceWith = settings.Duplicates.PathReplaceWith?.TextOrNull(); + string? saveDir = settings.Duplicates.SavePlaylistDirectory; CreatePlaylistFile(duplicateGroups, saveDir, (searchFor, replaceWith), printer); } diff --git a/src/AudioTagger.Console/Operations/TagUpdater.cs b/src/AudioTagger.Console/Operations/TagUpdater.cs index fe67fde..496e553 100644 --- a/src/AudioTagger.Console/Operations/TagUpdater.cs +++ b/src/AudioTagger.Console/Operations/TagUpdater.cs @@ -77,11 +77,11 @@ private static bool UpdateTags( return shouldCancel; } - IEnumerable? matchedTags = match.Groups + IEnumerable matchedTags = match.Groups .OfType() .Where(g => g.Success); - if (matchedTags.Any() != true) + if (!matchedTags.Any()) { printer.Print($"Could not parse data for filename \"{mediaFile.FileNameOnly}.\"", ResultType.Failure); diff --git a/src/AudioTagger.Console/Operations/TagUpdaterMultiple.cs b/src/AudioTagger.Console/Operations/TagUpdaterMultiple.cs index cd08928..dd9ab8e 100644 --- a/src/AudioTagger.Console/Operations/TagUpdaterMultiple.cs +++ b/src/AudioTagger.Console/Operations/TagUpdaterMultiple.cs @@ -175,7 +175,7 @@ private static void UpdateTags(MediaFile mediaFile, string sanitizedTitle = tagValue.Trim().Normalize() .Replace("___", " ") .Replace("__", " "); - mediaFile.Title = GetUpdatedValue(mediaFile.Title, + mediaFile.Title = GetUpdatedTagValue(mediaFile.Title, sanitizedTitle, updateType, false); @@ -208,7 +208,7 @@ private static void UpdateTags(MediaFile mediaFile, string sanitizedAlbum = tagValue.Trim().Normalize() .Replace("___", " ") .Replace("__", " "); - mediaFile.Album = GetUpdatedValue(mediaFile.Album, + mediaFile.Album = GetUpdatedTagValue(mediaFile.Album, sanitizedAlbum, updateType, false); @@ -231,7 +231,7 @@ private static void UpdateTags(MediaFile mediaFile, mediaFile.TrackNo = ushort.Parse(tagValue); break; case "comment": - mediaFile.Comments = GetUpdatedValue(mediaFile.Comments, tagValue, updateType, true); + mediaFile.Comments = GetUpdatedTagValue(mediaFile.Comments, tagValue, updateType, true); break; default: throw new InvalidOperationException($"Unsupported tag \"{tagName}\" could not be processed."); @@ -239,15 +239,7 @@ private static void UpdateTags(MediaFile mediaFile, mediaFile.SaveUpdates(); - /// - /// Returns the new, updated value for a tag. - /// - /// The original value to be modified. - /// The text to be added. - /// - /// Whether or not to add line breaks between the new and old text. - /// - static string GetUpdatedValue(string currentValue, string newValue, TagUpdateType updateType, bool useNewLines) + static string GetUpdatedTagValue(string currentValue, string newValue, TagUpdateType updateType, bool useNewLines) { string divider = useNewLines ? Environment.NewLine + Environment.NewLine : string.Empty; return updateType switch diff --git a/src/AudioTagger.Console/Operations/TagUpdaterSingle.cs b/src/AudioTagger.Console/Operations/TagUpdaterSingle.cs index 390c1c1..5dba98c 100644 --- a/src/AudioTagger.Console/Operations/TagUpdaterSingle.cs +++ b/src/AudioTagger.Console/Operations/TagUpdaterSingle.cs @@ -138,7 +138,7 @@ private static void UpdateTags(MediaFile mediaFile, string sanitizedTitle = tagValue.Trim().Normalize() .Replace("___", " ") .Replace("__", " "); - mediaFile.Title = GetUpdatedValue(mediaFile.Title, + mediaFile.Title = GetUpdatedTagValue(mediaFile.Title, sanitizedTitle, updateType, false); @@ -155,7 +155,7 @@ private static void UpdateTags(MediaFile mediaFile, StringSplitOptions.TrimEntries) .Select(a => a.Normalize()) .ToArray(); - mediaFile.AlbumArtists = GetUpdatedValues(mediaFile.AlbumArtists, + mediaFile.AlbumArtists = GetUpdatedTagValues(mediaFile.AlbumArtists, sanitizedAlbumArtists, updateType); break; @@ -171,7 +171,7 @@ private static void UpdateTags(MediaFile mediaFile, StringSplitOptions.TrimEntries) .Select(a => a.Normalize()) .ToArray(); - mediaFile.Artists = GetUpdatedValues(mediaFile.Artists, + mediaFile.Artists = GetUpdatedTagValues(mediaFile.Artists, sanitizedArtists, updateType); break; @@ -179,7 +179,7 @@ private static void UpdateTags(MediaFile mediaFile, string sanitizedAlbum = tagValue.Trim().Normalize() .Replace("___", " ") .Replace("__", " "); - mediaFile.Album = GetUpdatedValue(mediaFile.Album, + mediaFile.Album = GetUpdatedTagValue(mediaFile.Album, sanitizedAlbum, updateType, false); @@ -196,7 +196,7 @@ private static void UpdateTags(MediaFile mediaFile, StringSplitOptions.TrimEntries) .Select(g => g.Normalize()) .ToArray(); - mediaFile.Genres = GetUpdatedValues(mediaFile.Genres, + mediaFile.Genres = GetUpdatedTagValues(mediaFile.Genres, sanitizedGenres, updateType); break; @@ -207,7 +207,7 @@ private static void UpdateTags(MediaFile mediaFile, mediaFile.TrackNo = ushort.Parse(tagValue); break; case "comment": - mediaFile.Comments = GetUpdatedValue(mediaFile.Comments, tagValue, updateType, true); + mediaFile.Comments = GetUpdatedTagValue(mediaFile.Comments, tagValue, updateType, true); break; default: throw new InvalidOperationException($"Unsupported tag \"{tagName}\" could not be processed."); @@ -215,14 +215,7 @@ private static void UpdateTags(MediaFile mediaFile, mediaFile.SaveUpdates(); - /// - /// Returns the new, updated value for a tag. - /// - /// The original value to be modified. - /// The text to be added. - /// - /// Whether or not to add line breaks between the new and old text. - static string GetUpdatedValue( + static string GetUpdatedTagValue( string currentValue, string newValue, TagUpdateType updateType, @@ -242,13 +235,7 @@ static string GetUpdatedValue( }; } - /// - /// Returns the new, updated values for a tag as a collection. - /// - /// The original values to be modified. - /// The new text to be added. - /// - static string[] GetUpdatedValues( + static string[] GetUpdatedTagValues( string[] currentValues, string[] newValues, TagUpdateType updateType) diff --git a/src/AudioTagger.Console/Operations/TagViewer.cs b/src/AudioTagger.Console/Operations/TagViewer.cs index 1aab503..aa2e58c 100644 --- a/src/AudioTagger.Console/Operations/TagViewer.cs +++ b/src/AudioTagger.Console/Operations/TagViewer.cs @@ -16,7 +16,7 @@ public void Start(IReadOnlyCollection mediaFiles, try { //printer.Print(OutputLine.GetTagPrintedLines(mediaFile)); - var viewer = new MediaFileViewer(); + // var viewer = new MediaFileViewer(); MediaFileViewer.PrintFileDetails(mediaFile); #if _WINDOWS From 71d117fb475fe142a7a6b6e828c0b64a1d919be8 Mon Sep 17 00:00:00 2001 From: CodeConscious <50596087+codeconscious@users.noreply.github.com> Date: Sat, 15 Nov 2025 20:42:17 +0900 Subject: [PATCH 5/6] Library project tweaks --- README.md | 42 +++++++------- .../MediaFiles/MediaFileExtensionMethods.cs | 55 ++++++++++--------- src/AudioTagger.Library/UpdatableFields.cs | 1 - 3 files changed, 49 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index bbf36cf..20284e8 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Additionally, your original audio files will be modified during selected operati ## Requirements -- [.NET 9 runtime](https://dotnet.microsoft.com/en-us/download/dotnet/9.0) +- [.NET 10 runtime](https://dotnet.microsoft.com/en-us/download/dotnet/10.0) - `settings.json` (See below) ## Running @@ -36,24 +36,24 @@ dotnet run -- -r ~/Downloads/Audio/ ## Flags -| Flags | Description +| Flags | Description | |---|---| -| -v, --view | View full tag data. -| -vs, --view-summary | View a summary of tag data. -| -u, --update | Update tag data using filename patterns from the settings. -| -u1, --update-single | Update a single tag in multiple files to a single, manually-specified value. -| -ug, --update-genres | Update the genres in all files automatically using the CSV specified in the settings. -| -um, --update-multiple | Update a single tag in multiple files with multiple values. -| -uy, --update-year | Update the year using media files' own dates of creation. (Must do before other updates, lest the creation date be modified by those updates.) -| -urt, --reverse-track-numbers | Reverse the track numbers of the given files. -| -uea, --extract-artwork | Extracts artwork from directory files if they have the same artist and album, then deletes the artwork from the files containing it. -| -ura, --remove-artwork | Removes artwork from files. (File size is not reduced, as padding remains.) -| -rt, --rewrite-tags | Rewrites file tags. (Can be helping in reducing padding, such as from removed artwork.) -| -r, --rename | Rename and reorganize files into folders based on tag data. -| -d, --duplicates | List tracks with identical artists and titles. No files are modified or deleted. -| -s, --stats | Display file statistics based on tag data. -| -g, --genres | Save the primary genre for each artist to a genre file. -| -p, --parse | Get a single tag value by parsing the data of another (generally Comments). +| -v, --view | View full tag data. | +| -vs, --view-summary | View a summary of tag data. | +| -u, --update | Update tag data using filename patterns from the settings. | +| -u1, --update-single | Update a single tag in multiple files to a single, manually-specified value. | +| -ug, --update-genres | Update the genres in all files automatically using the CSV specified in the settings. | +| -um, --update-multiple | Update a single tag in multiple files with multiple values. | +| -uy, --update-year | Update the year using media files' own dates of creation. (Must do before other updates, lest the creation date be modified by those updates.) | +| -urt, --reverse-track-numbers | Reverse the track numbers of the given files. | +| -uea, --extract-artwork | Extracts artwork from directory files if they have the same artist and album, then deletes the artwork from the files containing it. | +| -ura, --remove-artwork | Removes artwork from files. (File size is not reduced, as padding remains.) | +| -rt, --rewrite-tags | Rewrites file tags. (Can be helping in reducing padding, such as from removed artwork.) | +| -r, --rename | Rename and reorganize files into folders based on tag data. | +| -d, --duplicates | List tracks with identical artists and titles. No files are modified or deleted. | +| -s, --stats | Display file statistics based on tag data. | +| -g, --genres | Save the primary genre for each artist to a genre file. | +| -p, --parse | Get a single tag value by parsing the data of another (generally Comments). | Passing no arguments will also display these instructions. @@ -72,7 +72,7 @@ A sample settings file, which can you copy and paste if you wish, follows: "(?:(?.+) ≡ )?(?.+?)(?: ?\\[(?\\d{4})\\])? = (?\\d+) [–-] (?.+?) [–-] (?.+)(?=\\.(?:m4a|opus))", "(?:(?<albumArtists>.+) ≡ )?(?<album>.+?)(?: ?\\[(?<year>\\d{4})\\])? = (?<trackNo>\\d{1,3}) [–-] (?<title>.+)(?=\\.(?:m4a|opus))", "(?:(?<albumArtists>.+) ≡ )(?<album>.+?)(?: ?\\[(?<year>\\d{4})\\])? = (?<artists>.+?) [–-] (?<title>.+)(?=\\.(?:m4a|opus))", - "(?:(?<albumArtists>.+) ≡ )?(?<album>.+?)(?: ?\\[(?<year>\\d{4})\\])? = (?<title>.+)(?=\\.(?:m4a|opus))", ] + "(?:(?<albumArtists>.+) ≡ )?(?<album>.+?)(?: ?\\[(?<year>\\d{4})\\])? = (?<title>.+)(?=\\.(?:m4a|opus))" ] }, "renaming": { "useAlbumDirectories": true, @@ -99,7 +99,7 @@ A sample settings file, which can you copy and paste if you wish, follows: "exclusions": [ { "artist": "Artist Name" }, { "title": "Track Title" }, - { "artist": "Artist Name", "title": "Track Title" }, + { "artist": "Artist Name", "title": "Track Title" } ], "artistReplacements": [ " ", @@ -131,7 +131,7 @@ A sample settings file, which can you copy and paste if you wish, follows: ":", ":" ] - }, + } } ``` diff --git a/src/AudioTagger.Library/MediaFiles/MediaFileExtensionMethods.cs b/src/AudioTagger.Library/MediaFiles/MediaFileExtensionMethods.cs index eb80b65..6d72ef7 100644 --- a/src/AudioTagger.Library/MediaFiles/MediaFileExtensionMethods.cs +++ b/src/AudioTagger.Library/MediaFiles/MediaFileExtensionMethods.cs @@ -2,39 +2,40 @@ namespace AudioTagger.Library.MediaFiles; public static class MediaFileExtensionMethods { - /// <summary> - /// Joins a collection into one string using a specified separator string. - /// </summary> - /// <param name="collection"></param> - /// <param name="separator"></param> - /// <returns>A joined string. Never returns null.</returns> - public static string Join(this IEnumerable<string> collection, string separator = "; ") + extension(IEnumerable<string> first) { - return string.Join(separator, collection); - } + /// <summary> + /// Joins a collection into one string using a specified separator string. + /// </summary> + /// <param name="separator"></param> + /// <returns>A joined string. Never returns null.</returns> + public string Join(string separator = "; ") + { + return string.Join(separator, first); + } - /// <summary> - /// Joins two collections into one formatted string. If their contents differ, then both will be included - /// with the second collection placed within parentheses after the first collection. - /// </summary> - /// <param name="first">This collection is given priority.</param> - /// <param name="second">This collection will not be added if it is identical to the primary one.</param> - /// <param name="separator">Applies to each collection separately.</param> - /// <returns>A combined string. Never returns null. Example: "first1; first2 (second1; second2)"</returns> - public static string JoinWith(this IEnumerable<string> first, IEnumerable<string> second, string separator = "; ") - { - string Joiner(IEnumerable<string> collection) => string.Join(separator, collection); + /// <summary> + /// Joins two collections into one formatted string. If their contents differ, then both will be included + /// with the second collection placed within parentheses after the first collection. + /// </summary> + /// <param name="second">This collection will not be added if it is identical to the primary one.</param> + /// <param name="separator">Applies to each collection separately.</param> + /// <returns>A combined string. Never returns null. Example: "first1; first2 (second1; second2)"</returns> + public string JoinWith(IEnumerable<string> second, string separator = "; ") + { + string Joiner(IEnumerable<string> collection1) => string.Join(separator, collection1); - if (first?.Any() != true) - return Joiner(second); + if (!first.Any()) + return Joiner(second); - if (second?.Any() != true) - return Joiner(first); + if (!second.Any()) + return Joiner(first); - if (first.Count() != second.Count()) - return $"{Joiner(first)} ({Joiner(second)})"; + if (first.Count() != second.Count()) + return $"{Joiner(first)} ({Joiner(second)})"; - return Joiner(first); // Identical collections of equal length, so only print the first. + return Joiner(first); // Identical collections of equal length, so only print the first. + } } /// <summary> diff --git a/src/AudioTagger.Library/UpdatableFields.cs b/src/AudioTagger.Library/UpdatableFields.cs index 856aee0..87df93d 100644 --- a/src/AudioTagger.Library/UpdatableFields.cs +++ b/src/AudioTagger.Library/UpdatableFields.cs @@ -20,7 +20,6 @@ public sealed class UpdatableFields /// Constructor that reads matched regex group names and /// maps the data to the correct tag name property. /// </summary> - /// <param name="matchedGroups"></param> public UpdatableFields( IEnumerable<Group> matchedGroups, IDictionary<string, string> artistsWithGenres) From 0ac94c153132c1f5d6c33fc12ac65db370aabd5c Mon Sep 17 00:00:00 2001 From: CodeConscious <50596087+codeconscious@users.noreply.github.com> Date: Tue, 27 Jan 2026 19:54:07 +0900 Subject: [PATCH 6/6] Remove unneeded code --- src/AudioTagger.Console/Operations/TagViewer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/AudioTagger.Console/Operations/TagViewer.cs b/src/AudioTagger.Console/Operations/TagViewer.cs index aa2e58c..be7c27f 100644 --- a/src/AudioTagger.Console/Operations/TagViewer.cs +++ b/src/AudioTagger.Console/Operations/TagViewer.cs @@ -15,8 +15,6 @@ public void Start(IReadOnlyCollection<MediaFile> mediaFiles, { try { - //printer.Print(OutputLine.GetTagPrintedLines(mediaFile)); - // var viewer = new MediaFileViewer(); MediaFileViewer.PrintFileDetails(mediaFile); #if _WINDOWS