From f8085bce7c840cc5e49c99b43c7dbc0ba605ca2d Mon Sep 17 00:00:00 2001 From: djairoh Date: Tue, 11 Jun 2024 01:59:25 +0200 Subject: [PATCH] feat: customizable placeholder strings as metadata_field option --- src/print_text.rs | 51 ++++++++++++++++++++++++------------------- src/structs/config.rs | 36 ++++++++++++++++++++++-------- src/update_message.rs | 17 +++++---------- 3 files changed, 62 insertions(+), 42 deletions(-) diff --git a/src/print_text.rs b/src/print_text.rs index 9016efb..d22f8dd 100644 --- a/src/print_text.rs +++ b/src/print_text.rs @@ -1,5 +1,5 @@ //! This file deals with formatting and outputting to stdout. -use log::{error, info}; +use log::error; use std::collections::HashMap; use string_builder::Builder; @@ -85,30 +85,37 @@ fn append_prefix(b: &mut Builder, data: &Data) { /// data: Data struct containing the field-text HashMap. fn append_fields(b: &mut Builder, cfg: &Config, data: &Data) { let mut idx = 0; - let len = data.field_text.len() as i32; for field in &cfg.metadata_fields { - if let Some(string) = data.field_text.get(&field.field) { - idx += 1; - - if cfg.escape_chars { - let s: &String = &string - .chars() - .map(|x| match x { - '&' => "&".to_owned(), - _ => x.to_string(), - }) - .collect(); - - b.append(field.format.replace("{}", s.as_str())); - } else { - b.append(field.format.replace("{}", string.as_str())); - } - if idx < len { - b.append(cfg.metadata_separator.as_str()) - }; + // setup (string, fmt) to contain placeholder or data, if extant. + let f = data.field_text.get(&field.field); + let (string, fmt) = if f.is_some() { + (f.unwrap(), &field.format) + } else if field.placeholder.len() != 0 { + (&field.field, &field.placeholder) } else { - info!("failed to get {} value!", field.field); + continue; + }; + + // insert separator in front of non-empty non-first field. + if idx > 0 { + b.append(cfg.metadata_separator.as_str()) + }; + idx += 1; + + // FIXME: extract to its' own function. + if cfg.escape_chars { + let s: &String = &string + .chars() + .map(|x| match x { + '&' => "&".to_owned(), + _ => x.to_string(), + }) + .collect(); + + b.append(fmt.replace("{}", s.as_str())); + } else { + b.append(fmt.replace("{}", string)); } } } diff --git a/src/structs/config.rs b/src/structs/config.rs index 411baf9..4d7281f 100644 --- a/src/structs/config.rs +++ b/src/structs/config.rs @@ -12,6 +12,8 @@ pub struct Field { pub num_chars: u32, /// Formatting to apply. (the value "{}" is substituted with the actual string) pub format: String, + /// Placeholder string to insert when the field is empty. (the value "{}" is substituted with the actual string). + pub placeholder: String, } impl Field { @@ -19,15 +21,17 @@ impl Field { /// input: /// field: name of the field /// num_chars: maximum length of the field - /// format: what formatting to apply to the field + /// format: what formatting to apply to the field + /// placeholder: the placeholder string to use /// /// returns: /// a new Field with the given parameters. - fn new(field: String, num_chars: u32, format: String) -> Self { + fn new(field: String, num_chars: u32, format: String, placeholder: String) -> Self { Field { field, num_chars, format, + placeholder, } } @@ -36,15 +40,29 @@ impl Field { /// field: name of the field /// num_chars: maximum length of the field /// format: (optional), formatting to apply. + /// placeholder: (optional), what placeholder to use. /// /// returns: /// a new Field with the given parameters. - pub fn constructor(field: &str, num_chars: u32, format: Option) -> Self { - if let Some(format) = format { - Self::new(field.to_owned(), num_chars, format) + pub fn constructor( + field: &str, + num_chars: u32, + format: Option, + placeholder: Option, + ) -> Self { + let fmt = if format.is_some() { + format.unwrap() } else { - Self::new(field.to_owned(), num_chars, "{}".to_owned()) - } + "{}".to_owned() + }; + + let place = if placeholder.is_some() { + placeholder.unwrap() + } else { + "No {}".to_owned() + }; + + Self::new(field.to_owned(), num_chars, fmt, place) } } @@ -241,8 +259,8 @@ impl Config { /// It contains the "title" and "artist" fields, with 40 and 20 maximum characters respectively. fn default_metadata_fields() -> Vec { vec![ - Field::constructor("xesam:title", 40, None), - Field::constructor("xesam:artist", 20, None), + Field::constructor("xesam:title", 40, None, None), + Field::constructor("xesam:artist", 20, None, None), ] } diff --git a/src/update_message.rs b/src/update_message.rs index 9259608..355c8b2 100644 --- a/src/update_message.rs +++ b/src/update_message.rs @@ -109,19 +109,14 @@ pub fn update_message(cfg: &Config, data: &mut Data, ratings: &Vec) { key, value_to_string(value, cfg.array_separator) ); - data.field_text - .insert(key.to_owned(), value_to_string(value, cfg.array_separator)) - } - None => { - trace!("update_messages: field {} has no value!", key); - if field.field.eq("bs:isFavorite") { - data.field_text.remove(key); - continue; - } data.field_text.insert( key.to_owned(), - format!("No {}", key.trim_start_matches("xesam:")), - ) + value_to_string(value, cfg.array_separator), + ); + } + None => { + trace!("update_messages: field {} has no value", key); + data.field_text.remove(key); } }; }