Fix optional token elision in naming patterns - #850
Open
krejko wants to merge 1 commit into
Open
Conversation
A bracket group holding more than one optional token (for example
"[{Series} {SeriesNumber}]") was never collapsed when every token inside it was
empty, so books without a series rendered a literal sentinel into their folder
and file names.
- Replace the "__EMPTY_VAR__" sentinel with U+E000. The old value contains
underscores, and "_" is part of the separator character class used during
cleanup, so the cleanup regexes partially consumed the sentinel itself.
- Resolve bracket groups before separator and slash handling so a surviving
sentinel can no longer leak a stray "/" into a rendered name.
- Handle groups containing any number of empty tokens: drop the whole group
when nothing meaningful survives, otherwise keep the group with the empty
tokens removed. This lets "[{Series} {SeriesNumber}]" disappear for a
standalone book and render as "[Radicalized]" for a series with no number.
Escape the group delimiters explicitly rather than via Regex.Escape, which
leaves "]" untouched and would close the negated character class early.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Naming patterns support optional tokens by emitting a sentinel for empty values and stripping the surrounding punctuation afterwards. That works for a bracket group holding a single token, but not for one holding several — so a pattern like
[{Series} {SeriesNumber}]leaks a literal sentinel into folder and file names for every book without a series.With
{Author}/[{Series} {SeriesNumber}] {Title} {{Narrator}} ({Year}):J.K. Rowling/[__EMPTY_VAR_] The Ickabog {Stephen Fry} (2020)J.K. Rowling/The Ickabog {Stephen Fry} (2020)Cory Doctorow/[Radicalized /] Radicalized (2019)Cory Doctorow/[Radicalized] Radicalized (2019)Two root causes:
__EMPTY_VAR__, and_is part of the separator character class used by the cleanup regexes — so cleanup partially consumed the sentinel itself, leaving__EMPTY_VAR_behind./inside the brackets.Changes
Fixed
__EMPTY_VAR__sentinel withU+E000, which shares no characters with the separator class./into a name.Added
FileNamingService_OptionalTokenElisionTestscovering all-tokens-present, empty series, empty series + narrator, series without a number, trailing optional tokens, the filename variant, and a guard that the sentinel never reaches output.Testing
dotnet testfiltered to the naming suites: 28 passed, 1 failed.The single failure is
DownloadNaming_AudiobookMetadataTests.ProcessCompletedDownload_UsesAudiobookMetadata_ForNaming, which fails identically on unmodifiedcanary— verified by stashing this change and re-running that test alone. It is pre-existing and unrelated.Existing
DownloadNaming_PatternCollapseTestsandFileNamingService_PatternSelectionTestsstill pass, so single-token groups and duplicate-component collapsing are unaffected.Notes
Delimiters are escaped explicitly rather than through
Regex.Escape, which does not escape]— building the negated class with it produces[^\[]], closing the class early. That bug was caught by the new tests.Behaviour only changes where the old output was already broken; patterns whose groups hold a single token render exactly as before.
🤖 Generated with Claude Code