format the code :)
This commit is contained in:
parent
be412d5f57
commit
a5dd196937
4 changed files with 177 additions and 57 deletions
|
@ -1,7 +1,8 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
const NOTIFICATION_TIMEOUT: u8 = 5;
|
const NOTIFICATION_TIMEOUT: u8 = 5;
|
||||||
const NOTIFICATION_BODY: &str = "<b>Playing:</b> {title} from {album} \n\n <b>Artist:</b> {artist} - {year}";
|
const NOTIFICATION_BODY: &str =
|
||||||
|
"<b>Playing:</b> {title} from {album} \n\n <b>Artist:</b> {artist} - {year}";
|
||||||
const NOTIFICATION_SUMMARY: &str = "{artist} - {title}";
|
const NOTIFICATION_SUMMARY: &str = "{artist} - {title}";
|
||||||
const NOTIFICATION_APP_NAME: &str = "C* Music Player";
|
const NOTIFICATION_APP_NAME: &str = "C* Music Player";
|
||||||
const DEFAULT_MAX_DEPTH: u8 = 3;
|
const DEFAULT_MAX_DEPTH: u8 = 3;
|
||||||
|
|
187
src/cmus/mod.rs
187
src/cmus/mod.rs
|
@ -34,7 +34,7 @@ pub enum CmusError {
|
||||||
EmptyPath,
|
EmptyPath,
|
||||||
DurationError(String),
|
DurationError(String),
|
||||||
PositionError(String),
|
PositionError(String),
|
||||||
UnknownError(String)
|
UnknownError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for CmusError {
|
impl Display for CmusError {
|
||||||
|
@ -75,21 +75,43 @@ impl FromStr for Track {
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
let mut lines = s.lines();
|
let mut lines = s.lines();
|
||||||
|
|
||||||
Ok(Track::builder().status(
|
Ok(Track::builder()
|
||||||
TrackStatus::from_str(lines.next().ok_or(CmusError::NoStatus)?.split_once(' ')
|
.status(TrackStatus::from_str(
|
||||||
.ok_or(CmusError::NoStatus)?.1)?
|
lines
|
||||||
)
|
.next()
|
||||||
.path(lines.next().ok_or(CmusError::EmptyPath)?.split_once(' ')
|
.ok_or(CmusError::NoStatus)?
|
||||||
.ok_or(CmusError::EmptyPath)?.1.to_string())
|
.split_once(' ')
|
||||||
|
.ok_or(CmusError::NoStatus)?
|
||||||
|
.1,
|
||||||
|
)?)
|
||||||
|
.path(
|
||||||
|
lines
|
||||||
|
.next()
|
||||||
|
.ok_or(CmusError::EmptyPath)?
|
||||||
|
.split_once(' ')
|
||||||
|
.ok_or(CmusError::EmptyPath)?
|
||||||
|
.1
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
.duration(
|
.duration(
|
||||||
lines.next().ok_or(CmusError::DurationError("Missing duration".to_string()))?.split_once(' ')
|
lines
|
||||||
.ok_or(CmusError::DurationError("Empty duration".to_string()))?.1.parse()
|
.next()
|
||||||
.map_err(|e: ParseIntError| CmusError::DurationError(e.to_string()))?
|
.ok_or(CmusError::DurationError("Missing duration".to_string()))?
|
||||||
|
.split_once(' ')
|
||||||
|
.ok_or(CmusError::DurationError("Empty duration".to_string()))?
|
||||||
|
.1
|
||||||
|
.parse()
|
||||||
|
.map_err(|e: ParseIntError| CmusError::DurationError(e.to_string()))?,
|
||||||
)
|
)
|
||||||
.position(
|
.position(
|
||||||
lines.next().ok_or(CmusError::PositionError("Missing position".to_string()))?.split_once(' ')
|
lines
|
||||||
.ok_or(CmusError::PositionError("Empty position".to_string()))?.1.parse()
|
.next()
|
||||||
.map_err(|e: ParseIntError| CmusError::PositionError(e.to_string()))?
|
.ok_or(CmusError::PositionError("Missing position".to_string()))?
|
||||||
|
.split_once(' ')
|
||||||
|
.ok_or(CmusError::PositionError("Empty position".to_string()))?
|
||||||
|
.1
|
||||||
|
.parse()
|
||||||
|
.map_err(|e: ParseIntError| CmusError::PositionError(e.to_string()))?,
|
||||||
)
|
)
|
||||||
.metadata(TrackMetadata::parse(lines))
|
.metadata(TrackMetadata::parse(lines))
|
||||||
.build())
|
.build())
|
||||||
|
@ -101,7 +123,7 @@ impl TrackMetadata {
|
||||||
/// This function will assume you processed the first 4 lines, and remove them from the iterator.
|
/// This function will assume you processed the first 4 lines, and remove them from the iterator.
|
||||||
///
|
///
|
||||||
/// and also assume the all tags is contained in the iterator.
|
/// and also assume the all tags is contained in the iterator.
|
||||||
fn parse<'a>(mut lines: impl Iterator<Item=&'a str>) -> Self {
|
fn parse<'a>(mut lines: impl Iterator<Item = &'a str>) -> Self {
|
||||||
let mut tags = HashMap::new();
|
let mut tags = HashMap::new();
|
||||||
|
|
||||||
while let Some(line) = lines.next() {
|
while let Some(line) = lines.next() {
|
||||||
|
@ -129,8 +151,15 @@ impl Track {
|
||||||
///
|
///
|
||||||
/// This is the title, if it exists, otherwise it's the file name without the extension.
|
/// This is the title, if it exists, otherwise it's the file name without the extension.
|
||||||
pub fn get_name(&self) -> &str {
|
pub fn get_name(&self) -> &str {
|
||||||
self.metadata.get("title").unwrap_or_else(|| self.path.split('/').last()
|
self.metadata.get("title").unwrap_or_else(|| {
|
||||||
.unwrap_or("").split_once(".").unwrap_or(("", "")).0)
|
self.path
|
||||||
|
.split('/')
|
||||||
|
.last()
|
||||||
|
.unwrap_or("")
|
||||||
|
.split_once(".")
|
||||||
|
.unwrap_or(("", ""))
|
||||||
|
.0
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,14 +169,18 @@ impl Track {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_track(query_command: &mut std::process::Command) -> Result<Track, CmusError> {
|
pub fn get_track(query_command: &mut std::process::Command) -> Result<Track, CmusError> {
|
||||||
// Just run the command, and collect the output.
|
// Just run the command, and collect the output.
|
||||||
let output = query_command.output().map_err(|e| CmusError::CmusRunningError(e.to_string()))?;
|
let output = query_command
|
||||||
|
.output()
|
||||||
|
.map_err(|e| CmusError::CmusRunningError(e.to_string()))?;
|
||||||
|
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
return Err(CmusError::CmusRunningError(String::from_utf8(output.stderr)
|
return Err(CmusError::CmusRunningError(
|
||||||
.map_err(|e| CmusError::UnknownError(e.to_string()))?));
|
String::from_utf8(output.stderr).map_err(|e| CmusError::UnknownError(e.to_string()))?,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let output = String::from_utf8(output.stdout).map_err(|e| CmusError::UnknownError(e.to_string()))?;
|
let output =
|
||||||
|
String::from_utf8(output.stdout).map_err(|e| CmusError::UnknownError(e.to_string()))?;
|
||||||
|
|
||||||
Track::from_str(&output).map_err(|e| CmusError::UnknownError(e.to_string()))
|
Track::from_str(&output).map_err(|e| CmusError::UnknownError(e.to_string()))
|
||||||
}
|
}
|
||||||
|
@ -156,7 +189,11 @@ pub fn get_track(query_command: &mut std::process::Command) -> Result<Track, Cmu
|
||||||
/// This function it should call only one time entire the program life time, So it makes sense to make it inline.
|
/// This function it should call only one time entire the program life time, So it makes sense to make it inline.
|
||||||
/// This function will return a `std::process::Command` that can be used to query cmus, you should store it in a variable :).
|
/// This function will return a `std::process::Command` that can be used to query cmus, you should store it in a variable :).
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn build_query_command(cmus_remote_bin: &str, socket_addr: &Option<String>, socket_pass: &Option<String>) -> std::process::Command {
|
pub fn build_query_command(
|
||||||
|
cmus_remote_bin: &str,
|
||||||
|
socket_addr: &Option<String>,
|
||||||
|
socket_pass: &Option<String>,
|
||||||
|
) -> std::process::Command {
|
||||||
let cmd_arr = cmus_remote_bin.split_whitespace().collect::<Vec<_>>();
|
let cmd_arr = cmus_remote_bin.split_whitespace().collect::<Vec<_>>();
|
||||||
let mut command = std::process::Command::new(cmd_arr[0]);
|
let mut command = std::process::Command::new(cmd_arr[0]);
|
||||||
|
|
||||||
|
@ -178,13 +215,13 @@ pub fn build_query_command(cmus_remote_bin: &str, socket_addr: &Option<String>,
|
||||||
command
|
command
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::assert_matches::assert_matches;
|
use std::assert_matches::assert_matches;
|
||||||
|
|
||||||
const OUTPUT_WITH_ALL_TAGS: &str = include_str!("../../tests/samples/cmus-remote-output-with-all-tags.txt");
|
const OUTPUT_WITH_ALL_TAGS: &str =
|
||||||
|
include_str!("../../tests/samples/cmus-remote-output-with-all-tags.txt");
|
||||||
|
|
||||||
const SOME_TAGS: &str = r#"tag artist Alex Goot
|
const SOME_TAGS: &str = r#"tag artist Alex Goot
|
||||||
tag album Alex Goot & Friends, Vol. 3
|
tag album Alex Goot & Friends, Vol. 3
|
||||||
|
@ -214,18 +251,48 @@ mod tests {
|
||||||
assert_eq!(track.path, "/mnt/Data/Music/FLAC/Alex Goot/Alex Goot - Alex Goot & Friends, Vol. 3/08 - Photograph.mp3");
|
assert_eq!(track.path, "/mnt/Data/Music/FLAC/Alex Goot/Alex Goot - Alex Goot & Friends, Vol. 3/08 - Photograph.mp3");
|
||||||
assert_eq!(track.duration, 284);
|
assert_eq!(track.duration, 284);
|
||||||
assert_eq!(track.position, 226);
|
assert_eq!(track.position, 226);
|
||||||
assert_eq!(track.metadata.tags.get("artist"), Some(&"Alex Goot".to_string()));
|
assert_eq!(
|
||||||
assert_eq!(track.metadata.tags.get("album"), Some(&"Alex Goot & Friends, Vol. 3".to_string()));
|
track.metadata.tags.get("artist"),
|
||||||
assert_eq!(track.metadata.tags.get("title"), Some(&"Photograph".to_string()));
|
Some(&"Alex Goot".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
track.metadata.tags.get("album"),
|
||||||
|
Some(&"Alex Goot & Friends, Vol. 3".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
track.metadata.tags.get("title"),
|
||||||
|
Some(&"Photograph".to_string())
|
||||||
|
);
|
||||||
assert_eq!(track.metadata.tags.get("date"), Some(&"2014".to_string()));
|
assert_eq!(track.metadata.tags.get("date"), Some(&"2014".to_string()));
|
||||||
assert_eq!(track.metadata.tags.get("genre"), Some(&"Pop".to_string()));
|
assert_eq!(track.metadata.tags.get("genre"), Some(&"Pop".to_string()));
|
||||||
assert_eq!(track.metadata.tags.get("discnumber"), Some(&"1".to_string()));
|
assert_eq!(
|
||||||
assert_eq!(track.metadata.tags.get("tracknumber"), Some(&"8".to_string()));
|
track.metadata.tags.get("discnumber"),
|
||||||
assert_eq!(track.metadata.tags.get("albumartist"), Some(&"Alex Goot".to_string()));
|
Some(&"1".to_string())
|
||||||
assert_eq!(track.metadata.tags.get("replaygain_track_gain"), Some(&"-9.4 dB".to_string()));
|
);
|
||||||
assert_eq!(track.metadata.tags.get("composer"), Some(&"Chad Kroeger".to_string()));
|
assert_eq!(
|
||||||
assert_eq!(track.metadata.tags.get("label"), Some(&"mudhutdigital.com".to_string()));
|
track.metadata.tags.get("tracknumber"),
|
||||||
assert_eq!(track.metadata.tags.get("publisher"), Some(&"mudhutdigital.com".to_string()));
|
Some(&"8".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
track.metadata.tags.get("albumartist"),
|
||||||
|
Some(&"Alex Goot".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
track.metadata.tags.get("replaygain_track_gain"),
|
||||||
|
Some(&"-9.4 dB".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
track.metadata.tags.get("composer"),
|
||||||
|
Some(&"Chad Kroeger".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
track.metadata.tags.get("label"),
|
||||||
|
Some(&"mudhutdigital.com".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
track.metadata.tags.get("publisher"),
|
||||||
|
Some(&"mudhutdigital.com".to_string())
|
||||||
|
);
|
||||||
assert_eq!(track.metadata.tags.get("bpm"), Some(&"146".to_string()));
|
assert_eq!(track.metadata.tags.get("bpm"), Some(&"146".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,17 +301,35 @@ mod tests {
|
||||||
let metadata = TrackMetadata::parse(SOME_TAGS.lines());
|
let metadata = TrackMetadata::parse(SOME_TAGS.lines());
|
||||||
|
|
||||||
assert_eq!(metadata.tags.get("artist"), Some(&"Alex Goot".to_string()));
|
assert_eq!(metadata.tags.get("artist"), Some(&"Alex Goot".to_string()));
|
||||||
assert_eq!(metadata.tags.get("album"), Some(&"Alex Goot & Friends, Vol. 3".to_string()));
|
assert_eq!(
|
||||||
|
metadata.tags.get("album"),
|
||||||
|
Some(&"Alex Goot & Friends, Vol. 3".to_string())
|
||||||
|
);
|
||||||
assert_eq!(metadata.tags.get("title"), Some(&"Photograph".to_string()));
|
assert_eq!(metadata.tags.get("title"), Some(&"Photograph".to_string()));
|
||||||
assert_eq!(metadata.tags.get("date"), Some(&"2014".to_string()));
|
assert_eq!(metadata.tags.get("date"), Some(&"2014".to_string()));
|
||||||
assert_eq!(metadata.tags.get("genre"), Some(&"Pop".to_string()));
|
assert_eq!(metadata.tags.get("genre"), Some(&"Pop".to_string()));
|
||||||
assert_eq!(metadata.tags.get("discnumber"), Some(&"1".to_string()));
|
assert_eq!(metadata.tags.get("discnumber"), Some(&"1".to_string()));
|
||||||
assert_eq!(metadata.tags.get("tracknumber"), Some(&"8".to_string()));
|
assert_eq!(metadata.tags.get("tracknumber"), Some(&"8".to_string()));
|
||||||
assert_eq!(metadata.tags.get("albumartist"), Some(&"Alex Goot".to_string()));
|
assert_eq!(
|
||||||
assert_eq!(metadata.tags.get("replaygain_track_gain"), Some(&"-9.4 dB".to_string()));
|
metadata.tags.get("albumartist"),
|
||||||
assert_eq!(metadata.tags.get("composer"), Some(&"Chad Kroeger".to_string()));
|
Some(&"Alex Goot".to_string())
|
||||||
assert_eq!(metadata.tags.get("label"), Some(&"mudhutdigital.com".to_string()));
|
);
|
||||||
assert_eq!(metadata.tags.get("publisher"), Some(&"mudhutdigital.com".to_string()));
|
assert_eq!(
|
||||||
|
metadata.tags.get("replaygain_track_gain"),
|
||||||
|
Some(&"-9.4 dB".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
metadata.tags.get("composer"),
|
||||||
|
Some(&"Chad Kroeger".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
metadata.tags.get("label"),
|
||||||
|
Some(&"mudhutdigital.com".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
metadata.tags.get("publisher"),
|
||||||
|
Some(&"mudhutdigital.com".to_string())
|
||||||
|
);
|
||||||
assert_eq!(metadata.tags.get("bpm"), Some(&"146".to_string()));
|
assert_eq!(metadata.tags.get("bpm"), Some(&"146".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,18 +343,29 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build_the_query_command_with_custom_socket_and_no_pass() {
|
fn test_build_the_query_command_with_custom_socket_and_no_pass() {
|
||||||
let command = build_query_command("cmus-remote", &Some("/tmp/cmus-socket".to_string()), &None);
|
let command =
|
||||||
|
build_query_command("cmus-remote", &Some("/tmp/cmus-socket".to_string()), &None);
|
||||||
|
|
||||||
assert_eq!(command.get_program(), "cmus-remote");
|
assert_eq!(command.get_program(), "cmus-remote");
|
||||||
assert_eq!(command.get_args().collect::<Vec<_>>(), &["--server", "/tmp/cmus-socket", "-Q"]);
|
assert_eq!(
|
||||||
|
command.get_args().collect::<Vec<_>>(),
|
||||||
|
&["--server", "/tmp/cmus-socket", "-Q"]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build_the_query_command_with_custom_socket_and_pass() {
|
fn test_build_the_query_command_with_custom_socket_and_pass() {
|
||||||
let command = build_query_command("cmus-remote", &Some("/tmp/cmus-socket".to_string()), &Some("pass".to_string()));
|
let command = build_query_command(
|
||||||
|
"cmus-remote",
|
||||||
|
&Some("/tmp/cmus-socket".to_string()),
|
||||||
|
&Some("pass".to_string()),
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(command.get_program(), "cmus-remote");
|
assert_eq!(command.get_program(), "cmus-remote");
|
||||||
assert_eq!(command.get_args().collect::<Vec<_>>(), &["--server", "/tmp/cmus-socket", "--passwd", "pass", "-Q"]);
|
assert_eq!(
|
||||||
|
command.get_args().collect::<Vec<_>>(),
|
||||||
|
&["--server", "/tmp/cmus-socket", "--passwd", "pass", "-Q"]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -277,6 +373,9 @@ mod tests {
|
||||||
let command = build_query_command("flatpak run io.github.cmus.cmus", &None, &None);
|
let command = build_query_command("flatpak run io.github.cmus.cmus", &None, &None);
|
||||||
|
|
||||||
assert_eq!(command.get_program(), "flatpak");
|
assert_eq!(command.get_program(), "flatpak");
|
||||||
assert_eq!(command.get_args().collect::<Vec<_>>(), &["run", "io.github.cmus.cmus", "-Q"]);
|
assert_eq!(
|
||||||
|
command.get_args().collect::<Vec<_>>(),
|
||||||
|
&["run", "io.github.cmus.cmus", "-Q"]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,11 @@ fn main() {
|
||||||
|
|
||||||
// Build the command, or use the default. (to speed up the main loop, because we don't need to build it every time)
|
// Build the command, or use the default. (to speed up the main loop, because we don't need to build it every time)
|
||||||
let mut query_command = cmus::build_query_command(
|
let mut query_command = cmus::build_query_command(
|
||||||
&args.cmus_remote_bin_path.unwrap_or("cmus-remote".to_string()).as_str(),
|
&args
|
||||||
&args.cmus_socket_address, &args.cmus_socket_password);
|
.cmus_remote_bin_path
|
||||||
|
.unwrap_or("cmus-remote".to_string())
|
||||||
|
.as_str(),
|
||||||
|
&args.cmus_socket_address,
|
||||||
|
&args.cmus_socket_password,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
35
src/utils.rs
35
src/utils.rs
|
@ -1,10 +1,14 @@
|
||||||
use std::path::Path;
|
|
||||||
use crate::cmus;
|
use crate::cmus;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
/// Search in the track directory for the cover image or the lyrics(depending on the `regx`).
|
/// Search in the track directory for the cover image or the lyrics(depending on the `regx`).
|
||||||
/// If the cover image or the lyrics is not found, search in the parent directory, and so on, until the max depth is reached.
|
/// If the cover image or the lyrics is not found, search in the parent directory, and so on, until the max depth is reached.
|
||||||
/// If the cover image or the lyrics is not found, return `None`.
|
/// If the cover image or the lyrics is not found, return `None`.
|
||||||
pub fn search_for(search_directory: &str, max_depth: u8, regx: &[&str]) -> std::io::Result<Option<String>> {
|
pub fn search_for(
|
||||||
|
search_directory: &str,
|
||||||
|
max_depth: u8,
|
||||||
|
regx: &[&str],
|
||||||
|
) -> std::io::Result<Option<String>> {
|
||||||
// Search in the track directory.
|
// Search in the track directory.
|
||||||
for entry in std::fs::read_dir(search_directory)? {
|
for entry in std::fs::read_dir(search_directory)? {
|
||||||
if let Ok(entry) = entry {
|
if let Ok(entry) = entry {
|
||||||
|
@ -24,7 +28,8 @@ pub fn search_for(search_directory: &str, max_depth: u8, regx: &[&str]) -> std::
|
||||||
// If the max depth is reached, return `None`.
|
// If the max depth is reached, return `None`.
|
||||||
if max_depth == 0 {
|
if max_depth == 0 {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
} else { // If the max depth is not reached, search in the parent directory (recursively).
|
} else {
|
||||||
|
// If the max depth is not reached, search in the parent directory (recursively).
|
||||||
let Some(parent) = Path::new(search_directory).parent() else { return Ok(None); };
|
let Some(parent) = Path::new(search_directory).parent() else { return Ok(None); };
|
||||||
let Some(parent) = parent.to_str() else { return Ok(None); };
|
let Some(parent) = parent.to_str() else { return Ok(None); };
|
||||||
search_for(parent, max_depth - 1, regx)
|
search_for(parent, max_depth - 1, regx)
|
||||||
|
@ -41,11 +46,15 @@ pub fn process_template_placeholders(template: &String, track: &cmus::Track) ->
|
||||||
for c in template.chars() {
|
for c in template.chars() {
|
||||||
if c == '{' {
|
if c == '{' {
|
||||||
key = String::new();
|
key = String::new();
|
||||||
} else if c == '}' { // Replace the key with their matching value if exists, if not replace with the empty string.
|
} else if c == '}' {
|
||||||
processed = processed.replace(&format!("{{{}}}", key), match key.as_str() {
|
// Replace the key with their matching value if exists, if not replace with the empty string.
|
||||||
"title" => track.get_name(),
|
processed = processed.replace(
|
||||||
_ => track.metadata.get(&key).unwrap_or(""),
|
&format!("{{{}}}", key),
|
||||||
});
|
match key.as_str() {
|
||||||
|
"title" => track.get_name(),
|
||||||
|
_ => track.metadata.get(&key).unwrap_or(""),
|
||||||
|
},
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
key.push(c);
|
key.push(c);
|
||||||
}
|
}
|
||||||
|
@ -67,7 +76,10 @@ mod tests {
|
||||||
impl TestContext for TestContextWithFullTrack {
|
impl TestContext for TestContextWithFullTrack {
|
||||||
fn setup() -> Self {
|
fn setup() -> Self {
|
||||||
Self {
|
Self {
|
||||||
track: cmus::Track::from_str(include_str!("../tests/samples/cmus-remote-output-with-all-tags.txt")).unwrap()
|
track: cmus::Track::from_str(include_str!(
|
||||||
|
"../tests/samples/cmus-remote-output-with-all-tags.txt"
|
||||||
|
))
|
||||||
|
.unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,6 +90,9 @@ mod tests {
|
||||||
let cover_path_template = String::from("{title}/{artist}/{album}/{tracknumber}");
|
let cover_path_template = String::from("{title}/{artist}/{album}/{tracknumber}");
|
||||||
let cover_path = process_template_placeholders(&cover_path_template, &ctx.track);
|
let cover_path = process_template_placeholders(&cover_path_template, &ctx.track);
|
||||||
|
|
||||||
assert_eq!(cover_path, "Photograph/Alex Goot/Alex Goot & Friends, Vol. 3/8");
|
assert_eq!(
|
||||||
|
cover_path,
|
||||||
|
"Photograph/Alex Goot/Alex Goot & Friends, Vol. 3/8"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue