about summary refs log tree commit diff stats
path: root/pkgs/by-name/mp/mpdpopm/src/bin
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--pkgs/by-name/mp/mpdpopm/src/bin/mpdpopm.rs106
1 files changed, 41 insertions, 65 deletions
diff --git a/pkgs/by-name/mp/mpdpopm/src/bin/mpdpopm.rs b/pkgs/by-name/mp/mpdpopm/src/bin/mpdpopm.rs
index d9d607d5..82272aeb 100644
--- a/pkgs/by-name/mp/mpdpopm/src/bin/mpdpopm.rs
+++ b/pkgs/by-name/mp/mpdpopm/src/bin/mpdpopm.rs
@@ -27,8 +27,10 @@
 //! for `mppopmd`. Run `mppopm --help` for detailed usage.
 
 use mpdpopm::{
-    clients::{Client, PlayerStatus, quote},
+    clients::{Client, PlayerStatus},
     config::{self, Config},
+    filters::ExpressionParser,
+    filters_ast::{FilterStickerNames, evaluate},
     storage::{last_played, play_count, rating_count},
 };
 
@@ -263,28 +265,34 @@ async fn get_playlists(client: &mut Client) -> Result<()> {
 }
 
 /// Add songs selected by filter to the queue
-async fn findadd(client: &mut Client, chan: &str, filter: &str, case: bool) -> Result<()> {
-    let qfilter = quote(filter);
-    debug!("findadd: got ``{}'', quoted to ``{}''.", filter, qfilter);
-    let cmd = format!("{} {}", if case { "findadd" } else { "searchadd" }, qfilter);
-    client.send_message(chan, &cmd).await?;
-    Ok(())
-}
+async fn searchadd(client: &mut Client, filter: &str, case_sensitive: bool) -> Result<()> {
+    let ast = match ExpressionParser::new().parse(filter) {
+        Ok(ast) => ast,
+        Err(err) => {
+            bail!("Failed to parse filter: `{}`", err)
+        }
+    };
 
-/// Send an arbitrary command
-async fn send_command(client: &mut Client, chan: &str, args: Vec<String>) -> Result<()> {
-    client
-        .send_message(
-            chan,
-            args.iter()
-                .map(String::as_str)
-                .map(quote)
-                .collect::<Vec<String>>()
-                .join(" ")
-                .as_str(),
-        )
-        .await?;
-    Ok(())
+    debug!("ast: {:#?}", ast);
+
+    let mut results = Vec::new();
+    for song in evaluate(&ast, case_sensitive, client, &FilterStickerNames::default())
+        .await
+        .context("Failed to evaluate filter")?
+    {
+        let out = client.add(&song).await;
+
+        if out.is_ok() {
+            eprintln!("Added: `{}`", song)
+        }
+
+        results.push(out);
+    }
+
+    match results.into_iter().collect::<Result<Vec<()>>>() {
+        Ok(_) => Ok(()),
+        Err(err) => Err(err),
+    }
 }
 
 /// `mppopmd' client
@@ -442,34 +450,7 @@ enum SubCommand {
         command: PlaylistsCommand,
     },
 
-    /// search case-sensitively for songs matching matching a filter and add them to the queue
-    ///
-    /// This command extends the MPD command `findadd' (which will search the MPD database) to allow
-    /// searches on attributes managed by mpdpopm: rating, playcount & last played time.
-    ///
-    /// The MPD `findadd' <https://www.musicpd.org/doc/html/protocol.html#command-findadd> will search the
-    /// MPD database for songs that match a given filter & add them to the play queue. The filter syntax is
-    /// documented here <https://www.musicpd.org/doc/html/protocol.html#filter-syntax>.
-    ///
-    /// This command adds three new terms on which you can filter: rating, playcount & lastplayed. Each is
-    /// expressed as an unsigned integer, with zero interpreted as "not set". For instance:
-    ///
-    ///     mppopm findadd "(rating > 128)"
-    ///
-    /// Will add all songs in the library with a rating sticker > 128 to the play queue.
-    ///
-    /// mppopm also introduces OR clauses (MPD only supports AND), so that:
-    ///
-    ///     mppopm findadd "((rating > 128) AND (artist =~ \"pogues\"))"
-    ///
-    /// will add all songs whose artist tag matches the regexp "pogues" with a rating greater than
-    /// 128.
-    ///
-    /// `findadd' is case-sensitive; for case-insensitive searching see the `searchadd' command.
-    #[clap(verbatim_doc_comment)]
-    Findadd { filter: String },
-
-    /// search case-insensitively for songs matching matching a filter and add them to the queue
+    /// search for songs matching matching a filter and add them to the queue
     ///
     /// This command extends the MPD command `searchadd' (which will search the MPD database) to allow
     /// searches on attributes managed by mpdpopm: rating, playcount & last played time.
@@ -491,14 +472,14 @@ enum SubCommand {
     ///
     /// will add all songs whose artist tag matches the regexp "pogues" with a rating greater than
     /// 128.
-    ///
-    /// `searchadd' is case-insensitive; for case-sensitive searching see the `findadd' command.
     #[clap(verbatim_doc_comment)]
-    Searchadd { filter: String },
+    Searchadd {
+        filter: String,
 
-    /// Send a command to mpd.
-    #[clap(verbatim_doc_comment)]
-    SendCommand { args: Vec<String> },
+        /// Respect the casing, when performing the filter evaluation.
+        #[arg(short, long, default_value_t = true)]
+        case_sensitive: bool,
+    },
 }
 
 #[tokio::main]
@@ -584,14 +565,9 @@ async fn main() -> Result<()> {
         SubCommand::Playlists { command } => match command {
             PlaylistsCommand::Get {} => get_playlists(&mut client).await,
         },
-        SubCommand::Findadd { filter } => {
-            findadd(&mut client, &config.commands_chan, &filter, true).await
-        }
-        SubCommand::Searchadd { filter } => {
-            findadd(&mut client, &config.commands_chan, &filter, false).await
-        }
-        SubCommand::SendCommand { args } => {
-            send_command(&mut client, &config.commands_chan, args).await
-        }
+        SubCommand::Searchadd {
+            filter,
+            case_sensitive,
+        } => searchadd(&mut client, &filter, case_sensitive).await,
     }
 }