Process the settings place holders in the template

This commit is contained in:
Anas Elgarhy 2023-02-21 04:41:12 +02:00
parent cb164f962a
commit 5488404fb3
No known key found for this signature in database
GPG key ID: 0501802A1D496528
5 changed files with 129 additions and 25 deletions

50
Cargo.lock generated
View file

@ -233,6 +233,7 @@ dependencies = [
"log", "log",
"lrc", "lrc",
"notify-rust", "notify-rust",
"parse-display",
"pretty_env_logger", "pretty_env_logger",
"regex", "regex",
"serde", "serde",
@ -1138,6 +1139,32 @@ dependencies = [
"windows-sys 0.45.0", "windows-sys 0.45.0",
] ]
[[package]]
name = "parse-display"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f96cc033d72896bb9a2c239a14e1141c3e2eae6d649e7c10ef4e598d66bc86c"
dependencies = [
"once_cell",
"parse-display-derive",
"regex",
]
[[package]]
name = "parse-display-derive"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5587062be441f3d868f7c4c9d13c67f286b03aa679d7f8176ef80bf2ee79e5d"
dependencies = [
"once_cell",
"proc-macro2",
"quote",
"regex",
"regex-syntax",
"structmeta",
"syn",
]
[[package]] [[package]]
name = "pin-project" name = "pin-project"
version = "1.0.12" version = "1.0.12"
@ -1524,6 +1551,29 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "structmeta"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bd9c2155aa89fb2c2cb87d99a610c689e7c47099b3e9f1c8a8f53faf4e3d2e3"
dependencies = [
"proc-macro2",
"quote",
"structmeta-derive",
"syn",
]
[[package]]
name = "structmeta-derive"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bafede0d0a2f21910f36d47b1558caae3076ed80f6f3ad0fc85a91e6ba7e5938"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "strum" name = "strum"
version = "0.22.0" version = "0.22.0"

View file

@ -16,6 +16,7 @@ typed-builder = "0.12.0"
log = { version = "0.4.17", optional = true } log = { version = "0.4.17", optional = true }
pretty_env_logger = { version = "0.4.0", optional = true } pretty_env_logger = { version = "0.4.0", optional = true }
thiserror = "1.0.38" thiserror = "1.0.38"
parse-display = "0.8.0"
[dependencies.clap] [dependencies.clap]
version = "4.1.4" version = "4.1.4"

View file

@ -5,6 +5,7 @@ pub mod query;
use crate::cmus::query::CmusQueryResponse; use crate::cmus::query::CmusQueryResponse;
#[cfg(feature = "debug")] #[cfg(feature = "debug")]
use log::{debug, info}; use log::{debug, info};
use parse_display::Display;
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt::Debug; use std::fmt::Debug;
use std::num::ParseIntError; use std::num::ParseIntError;
@ -14,6 +15,27 @@ use typed_builder::TypedBuilder;
pub trait TemplateProcessor { pub trait TemplateProcessor {
fn process(&self, template: &String) -> String; fn process(&self, template: &String) -> String;
fn get_keys(template: &String) -> Vec<String> {
let mut keys = Vec::new(); // Just a buffer to store the keys.
let mut key = String::new(); // Just a buffer to build the key.
for c in template.chars() {
if c == '{' {
key = String::new();
} else if c == '}' {
#[cfg(feature = "debug")]
debug!("Found key: {}", key);
keys.push(key.clone());
} else {
key.push(c);
}
}
#[cfg(feature = "debug")]
debug!("Found keys: {:?}", keys);
keys
}
} }
#[derive(Debug, PartialEq, Default, Clone)] #[derive(Debug, PartialEq, Default, Clone)]
@ -21,7 +43,7 @@ pub struct TrackMetadata {
tags: HashMap<String, String>, tags: HashMap<String, String>,
} }
#[derive(Debug, PartialEq, Default, Clone)] #[derive(Display, Debug, PartialEq, Default, Clone)]
pub enum TrackStatus { pub enum TrackStatus {
Playing, Playing,
Paused, Paused,
@ -72,26 +94,19 @@ impl TemplateProcessor for Track {
} }
let mut processed = template.clone(); let mut processed = template.clone();
let mut key = String::new(); // Just a buffer to store the key. Self::get_keys(template).iter().for_each(|key| {
#[cfg(feature = "debug")]
for c in template.chars() { debug!("Replacing the placeholder {{{key}}} with its matching value.");
if c == '{' { // Replace the key with their matching value if exists, if not replace with the empty string.
key = String::new(); let status = self.status.to_string();
} else if c == '}' { if let Some(value) = match key.as_str() {
#[cfg(feature = "debug")] "status" => Some(status.as_str()),
debug!("Replacing the placeholder {{{key}}} with its matching value."); "title" => Some(self.get_name()),
// Replace the key with their matching value if exists, if not replace with the empty string. _ => self.metadata.get(&key),
processed = processed.replace( } {
&format!("{{{}}}", key), processed = processed.replace(&format!("{{{key}}}"), value);
match key.as_str() {
"title" => self.get_name(),
_ => self.metadata.get(&key).unwrap_or(""),
},
);
} else {
key.push(c);
} }
} });
#[cfg(feature = "debug")] #[cfg(feature = "debug")]
debug!("Processed template: {processed}"); debug!("Processed template: {processed}");

View file

@ -1,6 +1,8 @@
use crate::cmus::CmusError; use crate::cmus::{CmusError, TemplateProcessor};
#[cfg(feature = "debug")] #[cfg(feature = "debug")]
use log::{debug, info}; use log::{debug, info};
use parse_display::Display;
use std::fmt::{Display, Formatter};
use std::num::ParseIntError; use std::num::ParseIntError;
use std::str::FromStr; use std::str::FromStr;
@ -13,7 +15,7 @@ pub struct PlayerSettings {
pub volume: Volume, pub volume: Volume,
} }
#[derive(Debug, PartialEq, Default, Clone)] #[derive(Display, Debug, PartialEq, Default, Clone)]
pub enum Shuffle { pub enum Shuffle {
#[default] #[default]
Off, Off,
@ -27,7 +29,7 @@ pub struct Volume {
pub right: u8, pub right: u8,
} }
#[derive(Debug, PartialEq, Default, Clone)] #[derive(Display, Debug, PartialEq, Default, Clone)]
pub enum AAAMode { pub enum AAAMode {
#[default] #[default]
All, All,
@ -35,6 +37,42 @@ pub enum AAAMode {
Artist, Artist,
} }
impl TemplateProcessor for PlayerSettings {
fn process(&self, template: &String) -> String {
#[cfg(feature = "debug")]
{
info!("Processing template: {}", template);
debug!("Processing template with player settings: {:?}", self);
}
let mut processed = template.clone();
Self::get_keys(template).iter().for_each(|key| {
let value = match key.as_str() {
"repeat" => self.repeat.to_string(),
"repeat_current" => self.repeat_current.to_string(),
"shuffle" => self.shuffle.to_string(),
"aaa_mode" => self.aaa_mode.to_string(),
"volume_left" => self.volume.left.to_string(),
"volume_right" => self.volume.right.to_string(),
"volume" => {
if self.volume.left == self.volume.right {
self.volume.left.to_string()
} else {
format!("{}:{}", self.volume.left, self.volume.right)
}
}
_ => "".to_string(),
};
processed = processed.replace(&format!("{{{key}}}"), &value);
});
#[cfg(feature = "debug")]
info!("Processed template: {}", processed);
processed
}
}
impl FromStr for AAAMode { impl FromStr for AAAMode {
type Err = CmusError; type Err = CmusError;
@ -165,7 +203,7 @@ mod tests {
volume: Volume { volume: Volume {
left: 46, left: 46,
right: 46, right: 46,
} },
}) })
); );
} }

View file

@ -1,9 +1,9 @@
#![feature(assert_matches)] #![feature(assert_matches)]
use crate::cmus::TemplateProcessor;
#[cfg(feature = "debug")] #[cfg(feature = "debug")]
use log::{debug, info}; use log::{debug, info};
use std::path::Path; use std::path::Path;
use crate::cmus::TemplateProcessor;
pub mod cmus; pub mod cmus;
pub mod notification; pub mod notification;