@@ -19,6 +19,7 @@ use crate::util;
1919use crate :: Config ;
2020use crate :: TaggedFile ;
2121use itertools:: Itertools ;
22+ use regex:: { Regex , RegexBuilder } ;
2223use std:: borrow:: Cow ;
2324use std:: collections:: HashMap ;
2425
@@ -117,6 +118,23 @@ fn find_most_common_tag_value<'a>(
117118 MostCommonItem :: find ( tracks. filter_map ( |tagged_file| tagged_file. first_tag_value ( key) ) )
118119}
119120
121+ /// Strip disc suffix from the end of the `Cow` string.
122+ fn strip_disc_suffix < ' a > ( title : Cow < ' a , str > , pattern : & Regex ) -> Cow < ' a , str > {
123+ match pattern. find ( & title) {
124+ Some ( m) => {
125+ let start = m. start ( ) ;
126+ match title {
127+ Cow :: Borrowed ( s) => Cow :: Borrowed ( & s[ ..start] ) ,
128+ Cow :: Owned ( mut s) => {
129+ s. truncate ( start) ;
130+ Cow :: Owned ( s)
131+ }
132+ }
133+ }
134+ None => title,
135+ }
136+ }
137+
120138/// A collection of tracks on the local disk.
121139#[ derive( Debug ) ]
122140pub struct TaggedFileCollection {
@@ -342,7 +360,19 @@ impl FromIterator<TaggedFile> for TaggedFileCollection {
342360
343361impl ReleaseLike for TaggedFileCollection {
344362 fn release_title ( & self ) -> Option < Cow < ' _ , str > > {
345- self . find_consensual_tag_value ( & TagKey :: Album )
363+ let disc_pattern = RegexBuilder :: new ( r"\s*[(\[-]\s*(?:CD|Disc)\s*\d+\s*[)\]]?\s*$" )
364+ . case_insensitive ( true )
365+ . build ( )
366+ . unwrap ( ) ;
367+
368+ MostCommonItem :: find (
369+ self . media
370+ . iter ( )
371+ . flat_map ( |media| media. tracks . iter ( ) )
372+ . filter_map ( |tagged_file| tagged_file. first_tag_value ( & TagKey :: Album ) )
373+ . map ( |title| strip_disc_suffix ( title, & disc_pattern) ) ,
374+ )
375+ . and_then ( MostCommonItem :: into_concensus)
346376 }
347377
348378 fn release_artist ( & self ) -> Option < Cow < ' _ , str > > {
0 commit comments