From aef9c43c70d36ebb60385f4ac1a24c11a6ee202d Mon Sep 17 00:00:00 2001 From: euzu Date: Fri, 27 Sep 2024 14:45:52 +0200 Subject: [PATCH] added sorting based on sequence --- CHANGELOG.md | 1 + README.md | 1 + src/model/config.rs | 1 + src/processing/playlist_processor.rs | 40 +++++++++++++++++++++++++--- 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08306c6b5..25a27230c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog # 2.0.5(2024-09-xx) - input url supports now scheme `file://...` (which is not necessary because file paths are supported). Gzip files are also supported. +- sort takes now a sequence for channel values which has higher priority than sort order # 2.0.4(2024-09-19) * if Content type of file download is not set in header, the gzip encoding is checked through magic header. diff --git a/README.md b/README.md index 3c073a98d..9a04b5b08 100644 --- a/README.md +++ b/README.md @@ -335,6 +335,7 @@ is a list of sort configurations for groups. Each configuration has 3 top level - `field` can be `group`, `title`, `name` or `url`. - `group_pattern` is a regular expression like `'^TR.:\s?(.*)'` which is matched against group title. - `order` can be `asc` or `desc` +- `sequence` _optional_ is a list of field values (based on `field`) which are used to sort based on index. The `order` is ignored for this entries. The pattern should be selected taking into account the processing sequence. diff --git a/src/model/config.rs b/src/model/config.rs index 0c4fb6943..cfdfbf5e6 100644 --- a/src/model/config.rs +++ b/src/model/config.rs @@ -198,6 +198,7 @@ pub(crate) struct ConfigSortChannel { pub group_pattern: String, // match against group title pub order: SortOrder, + pub sequence: Option>, #[serde(skip_serializing, skip_deserializing)] pub re: Option, } diff --git a/src/processing/playlist_processor.rs b/src/processing/playlist_processor.rs index 7687fff4e..57cffdb51 100644 --- a/src/processing/playlist_processor.rs +++ b/src/processing/playlist_processor.rs @@ -68,10 +68,42 @@ fn playlistitem_comparator(a: &PlaylistItem, b: &PlaylistItem, channel_sort: &Co let raw_value_b = get_field_value(b, &channel_sort.field); let value_a = if match_as_ascii { Rc::new(unidecode(&raw_value_a)) } else { raw_value_a }; let value_b = if match_as_ascii { Rc::new(unidecode(&raw_value_b)) } else { raw_value_b }; - let ordering = value_a.partial_cmp(&value_b).unwrap(); - match channel_sort.order { - Asc => ordering, - Desc => ordering.reverse() + match &channel_sort.sequence { + Some(custom_order) => { + // Check indices in the custom order vector + let index_a = custom_order.iter().position(|s| s == value_a.as_ref()); + let index_b = custom_order.iter().position(|s| s == value_b.as_ref()); + + match (index_a, index_b) { + (Some(idx_a), Some(idx_b)) => { + // Both items found in custom order, compare indices + idx_a.cmp(&idx_b) + } + (Some(_), None) => { + // Only 'a' found in custom order, it comes first + Ordering::Less + } + (None, Some(_)) => { + // Only 'b' found in custom order, it comes first + Ordering::Greater + } + (None, None) => { + // Neither found, fall back to default ordering + let ordering = value_a.partial_cmp(&value_b).unwrap(); + match channel_sort.order { + Asc => ordering, + Desc => ordering.reverse(), + } + } + } + }, + None => { + let ordering = value_a.partial_cmp(&value_b).unwrap(); + match channel_sort.order { + Asc => ordering, + Desc => ordering.reverse() + } + } } }