diff options
Diffstat (limited to '')
| -rw-r--r-- | pkgs/by-name/mp/mpdpopm/src/bin/mpdpopm.rs | 106 |
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, } } |
