about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-06-16 10:20:40 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-06-16 10:20:40 +0200
commit8b644e4e0e058a003984c02d48e829de437145c6 (patch)
tree0e6574f82c20e580a0335427a16eb2c429cef973
parentfeat(yt/videos/list): Replace the nucleo matcher with a simple `contains` (diff)
downloadyt-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 '')
-rw-r--r--crates/yt/src/cli.rs65
-rw-r--r--crates/yt/src/main.rs13
-rw-r--r--crates/yt/src/select/cmds/mod.rs2
-rw-r--r--crates/yt/src/select/mod.rs29
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
     };