diff options
author | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2025-06-16 10:20:40 +0200 |
---|---|---|
committer | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2025-06-16 10:20:40 +0200 |
commit | 8b644e4e0e058a003984c02d48e829de437145c6 (patch) | |
tree | 0e6574f82c20e580a0335427a16eb2c429cef973 /crates | |
parent | feat(yt/videos/list): Replace the nucleo matcher with a simple `contains` (diff) | |
download | yt-8b644e4e0e058a003984c02d48e829de437145c6.zip |
feat(yt/select/split): Make sorting configurable
I also moved that to a separate subcommand, as we would otherwise have too many `requires`/`conflicts_with` statements.
Diffstat (limited to 'crates')
-rw-r--r-- | crates/yt/src/cli.rs | 65 | ||||
-rw-r--r-- | crates/yt/src/main.rs | 13 | ||||
-rw-r--r-- | crates/yt/src/select/cmds/mod.rs | 2 | ||||
-rw-r--r-- | crates/yt/src/select/mod.rs | 29 |
4 files changed, 90 insertions, 19 deletions
diff --git a/crates/yt/src/cli.rs b/crates/yt/src/cli.rs index 634e422..73a857b 100644 --- a/crates/yt/src/cli.rs +++ b/crates/yt/src/cli.rs @@ -9,12 +9,16 @@ // You should have received a copy of the License along with this program. // If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>. -use std::{path::PathBuf, str::FromStr}; +use std::{ + fmt::{self, Display, Formatter}, + path::PathBuf, + str::FromStr, +}; use anyhow::Context; use bytes::Bytes; use chrono::NaiveDate; -use clap::{ArgAction, Args, Parser, Subcommand}; +use clap::{ArgAction, Args, Parser, Subcommand, ValueEnum}; use url::Url; use crate::{ @@ -294,6 +298,43 @@ impl FromStr for OptionalPublisher { } } +#[derive(Default, ValueEnum, Clone, Copy, Debug)] +pub enum SelectSplitSortKey { + /// Sort by the name of the publisher. + #[default] + Publisher, + + /// Sort by the number of unselected videos per publisher. + Videos, +} +impl Display for SelectSplitSortKey { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + SelectSplitSortKey::Publisher => f.write_str("publisher"), + SelectSplitSortKey::Videos => f.write_str("videos"), + } + } +} + +#[derive(Default, ValueEnum, Clone, Copy, Debug)] +pub enum SelectSplitSortMode { + /// Sort in ascending order (small -> big) + #[default] + Asc, + + /// Sort in descending order (big -> small) + Desc, +} + +impl Display for SelectSplitSortMode { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + SelectSplitSortMode::Asc => f.write_str("asc"), + SelectSplitSortMode::Desc => f.write_str("desc"), + } + } +} + #[derive(Subcommand, Clone, Debug)] // NOTE: Keep this in sync with the [`constants::HELP_STR`] constant. <2024-08-20> // NOTE: Also keep this in sync with the `tree-sitter-yts/grammar.js`. <2024-11-04> @@ -304,15 +345,26 @@ pub enum SelectCommand { #[arg(long, short)] done: bool, - /// Generate a directory, where each file contains only one subscription. - #[arg(long, short, conflicts_with = "use_last_selection")] - split: bool, - /// Use the last selection file (useful if you've spend time on it and want to get it again) #[arg(long, short, conflicts_with = "done")] use_last_selection: bool, }, + /// Generate a directory, where each file contains only one subscription. + Split { + /// Include done (watched, dropped) videos + #[arg(long, short)] + done: bool, + + /// Which key to use for sorting. + #[arg(default_value_t)] + sort_key: SelectSplitSortKey, + + /// Which mode to use for sorting. + #[arg(default_value_t)] + sort_mode: SelectSplitSortMode, + }, + /// Add a video to the database /// /// This optionally supports to add a playlist. @@ -371,7 +423,6 @@ impl Default for SelectCommand { Self::File { done: false, use_last_selection: false, - split: false, } } } diff --git a/crates/yt/src/main.rs b/crates/yt/src/main.rs index 930d269..dd23d9f 100644 --- a/crates/yt/src/main.rs +++ b/crates/yt/src/main.rs @@ -115,14 +115,13 @@ async fn main() -> Result<()> { SelectCommand::File { done, use_last_selection, - split, + } => Box::pin(select::select_file(&app, done, use_last_selection)).await?, + SelectCommand::Split { + done, + sort_key, + sort_mode, } => { - if split { - assert!(!use_last_selection); - Box::pin(select::select_split(&app, done)).await? - } else { - Box::pin(select::select_file(&app, done, use_last_selection)).await? - } + Box::pin(select::select_split(&app, done, sort_key, sort_mode)).await? } _ => Box::pin(handle_select_cmd(&app, cmd, None)).await?, } diff --git a/crates/yt/src/select/cmds/mod.rs b/crates/yt/src/select/cmds/mod.rs index aabcd3d..f97b04b 100644 --- a/crates/yt/src/select/cmds/mod.rs +++ b/crates/yt/src/select/cmds/mod.rs @@ -76,7 +76,7 @@ pub async fn handle_select_cmd( firefox.arg(url.as_str()); let _handle = firefox.spawn().context("Failed to run firefox")?; } - SelectCommand::File { .. } => unreachable!("This should have been filtered out"), + SelectCommand::File { .. } | SelectCommand::Split { .. } => unreachable!("This should have been filtered out"), } Ok(()) } diff --git a/crates/yt/src/select/mod.rs b/crates/yt/src/select/mod.rs index 668ab02..a361fed 100644 --- a/crates/yt/src/select/mod.rs +++ b/crates/yt/src/select/mod.rs @@ -21,7 +21,7 @@ use std::{ use crate::{ app::App, - cli::CliArgs, + cli::{CliArgs, SelectSplitSortKey, SelectSplitSortMode}, constants::HELP_STR, storage::video_database::{Video, VideoStatusMarker, get}, unreachable::Unreachable, @@ -39,7 +39,12 @@ use tokio::process::Command; pub mod cmds; pub mod selection_file; -pub async fn select_split(app: &App, done: bool) -> Result<()> { +pub async fn select_split( + app: &App, + done: bool, + sort_key: SelectSplitSortKey, + sort_mode: SelectSplitSortMode, +) -> Result<()> { let temp_dir = Builder::new() .prefix("yt_video_select-") .rand_bytes(6) @@ -69,8 +74,24 @@ pub async fn select_split(app: &App, done: bool) -> Result<()> { let author_map = { let mut temp_vec: Vec<_> = author_map.into_iter().collect(); - // PERFORMANCE: The clone here should not be neeed. <2025-06-15> - temp_vec.sort_by_key(|(name, _)| name.to_owned()); + match sort_key { + SelectSplitSortKey::Publisher => { + // PERFORMANCE: The clone here should not be neeed. <2025-06-15> + temp_vec.sort_by_key(|(name, _): &(String, Vec<Video>)| name.to_owned()) + } + SelectSplitSortKey::Videos => { + temp_vec.sort_by_key(|(_, videos): &(String, Vec<Video>)| videos.len()) + } + }; + + match sort_mode { + SelectSplitSortMode::Asc => { + // Std's default mode is ascending. + } + SelectSplitSortMode::Desc => { + temp_vec.reverse(); + } + } temp_vec }; |