fix: fixed a bug where incorrect characters are replaced from the format string
This commit is contained in:
parent
d34e842f3e
commit
2ea0e57338
|
|
@ -1,15 +1,17 @@
|
||||||
//! This file deals with formatting and outputting to stdout.
|
//! This file deals with formatting and outputting to stdout.
|
||||||
|
use log::{error, info};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use log::{info, error};
|
|
||||||
use string_builder::Builder;
|
use string_builder::Builder;
|
||||||
use dyn_fmt::AsStrFormatExt;
|
|
||||||
|
|
||||||
use crate::structs::{config::{Field, Config}, data::Data};
|
use crate::structs::{
|
||||||
|
config::{Config, Field},
|
||||||
|
data::Data,
|
||||||
|
};
|
||||||
|
|
||||||
/// This function finds the last whitespace in a string and returns its' index.
|
/// This function finds the last whitespace in a string and returns its' index.
|
||||||
/// If there is no whitespace it returns usize::MAX instead.
|
/// If there is no whitespace it returns usize::MAX instead.
|
||||||
fn fuzzy_cutoff(str: &str) -> usize {
|
fn fuzzy_cutoff(str: &str) -> usize {
|
||||||
str.rfind(char::is_whitespace).unwrap_or_else( || usize::MAX)
|
str.rfind(char::is_whitespace).unwrap_or_else(|| usize::MAX)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function helps deal with non-UTF8 strings.
|
/// This function helps deal with non-UTF8 strings.
|
||||||
|
|
@ -23,16 +25,16 @@ fn fuzzy_cutoff(str: &str) -> usize {
|
||||||
/// Returns:
|
/// Returns:
|
||||||
/// usize indicatheing the index of the character boundary nearest max_len.
|
/// usize indicatheing the index of the character boundary nearest max_len.
|
||||||
fn get_char_boundary(str: &str, max_len: usize) -> usize {
|
fn get_char_boundary(str: &str, max_len: usize) -> usize {
|
||||||
match max_len > str.len() || str.is_char_boundary(max_len) {
|
match max_len > str.len() || str.is_char_boundary(max_len) {
|
||||||
true => max_len,
|
true => max_len,
|
||||||
false => {
|
false => {
|
||||||
let mut idx = max_len;
|
let mut idx = max_len;
|
||||||
while !str.is_char_boundary(idx) {
|
while !str.is_char_boundary(idx) {
|
||||||
idx -= 1;
|
idx -= 1;
|
||||||
}
|
}
|
||||||
idx
|
idx
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function applies truncation to each string in the given hashmap, as dictated by the values in the given Fields.
|
/// This function applies truncation to each string in the given hashmap, as dictated by the values in the given Fields.
|
||||||
|
|
@ -43,18 +45,25 @@ fn get_char_boundary(str: &str, max_len: usize) -> usize {
|
||||||
/// brk: Optional, character to insert when a string is truncated.
|
/// brk: Optional, character to insert when a string is truncated.
|
||||||
/// fuzzy: Whether to apply the fuzzy truncation function or not.
|
/// fuzzy: Whether to apply the fuzzy truncation function or not.
|
||||||
/// strings: Hashmap containing the strings to be truncated. Key values should match with the names of the Fields Vec.
|
/// strings: Hashmap containing the strings to be truncated. Key values should match with the names of the Fields Vec.
|
||||||
fn cutoff(fields: &Vec<Field>, brk: Option<char>, fuzzy: bool, strings: &mut HashMap<String, String>) {
|
fn cutoff(
|
||||||
for field in fields {
|
fields: &Vec<Field>,
|
||||||
if let Some(str) = strings.get_mut(&field.field) {
|
brk: Option<char>,
|
||||||
if str.len() >= field.num_chars as usize {
|
fuzzy: bool,
|
||||||
str.truncate(get_char_boundary(str, field.num_chars as usize));
|
strings: &mut HashMap<String, String>,
|
||||||
if fuzzy {str.truncate(fuzzy_cutoff(str))}
|
) {
|
||||||
if let Some(c) = brk {
|
for field in fields {
|
||||||
str.push(c);
|
if let Some(str) = strings.get_mut(&field.field) {
|
||||||
|
if str.len() >= field.num_chars as usize {
|
||||||
|
str.truncate(get_char_boundary(str, field.num_chars as usize));
|
||||||
|
if fuzzy {
|
||||||
|
str.truncate(fuzzy_cutoff(str))
|
||||||
|
}
|
||||||
|
if let Some(c) = brk {
|
||||||
|
str.push(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function appends the prefix character to the given string builder.
|
/// This function appends the prefix character to the given string builder.
|
||||||
|
|
@ -63,8 +72,8 @@ fn cutoff(fields: &Vec<Field>, brk: Option<char>, fuzzy: bool, strings: &mut Has
|
||||||
/// b: mutable String builder to append to.
|
/// b: mutable String builder to append to.
|
||||||
/// data: Data struct containing the current prefix character.
|
/// data: Data struct containing the current prefix character.
|
||||||
fn append_prefix(b: &mut Builder, data: &Data) {
|
fn append_prefix(b: &mut Builder, data: &Data) {
|
||||||
b.append(data.prefix);
|
b.append(data.prefix);
|
||||||
b.append(" ");
|
b.append(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function appends each field in the Data.field_text Hashmap to the given String builder.
|
/// This function appends each field in the Data.field_text Hashmap to the given String builder.
|
||||||
|
|
@ -75,29 +84,33 @@ fn append_prefix(b: &mut Builder, data: &Data) {
|
||||||
/// cfg: Config struct for the program.
|
/// cfg: Config struct for the program.
|
||||||
/// data: Data struct containing the field-text HashMap.
|
/// data: Data struct containing the field-text HashMap.
|
||||||
fn append_fields(b: &mut Builder, cfg: &Config, data: &Data) {
|
fn append_fields(b: &mut Builder, cfg: &Config, data: &Data) {
|
||||||
let mut idx = 0;
|
let mut idx = 0;
|
||||||
let len = data.field_text.len() as i32;
|
let len = data.field_text.len() as i32;
|
||||||
|
|
||||||
for field in &cfg.metadata_fields {
|
for field in &cfg.metadata_fields {
|
||||||
if let Some(string) = data.field_text.get(&field.field) {
|
if let Some(string) = data.field_text.get(&field.field) {
|
||||||
idx += 1;
|
idx += 1;
|
||||||
|
|
||||||
if cfg.escape_chars {
|
if cfg.escape_chars {
|
||||||
let s: &String = &string.chars()
|
let s: &String = &string
|
||||||
.map(|x| match x {
|
.chars()
|
||||||
'&' => "&".to_owned(),
|
.map(|x| match x {
|
||||||
_ => x.to_string(),
|
'&' => "&".to_owned(),
|
||||||
}).collect();
|
_ => x.to_string(),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
b.append(field.format.format(&[s.as_str()]));
|
b.append(field.format.replace("{}", s.as_str()));
|
||||||
} else {
|
} else {
|
||||||
b.append(field.format.format(&[string.as_str()]));
|
b.append(field.format.replace("{}", string.as_str()));
|
||||||
}
|
}
|
||||||
if idx < len {b.append(cfg.metadata_separator.as_str())};
|
if idx < len {
|
||||||
} else {
|
b.append(cfg.metadata_separator.as_str())
|
||||||
info!("failed to get {} value!", field.field);
|
};
|
||||||
|
} else {
|
||||||
|
info!("failed to get {} value!", field.field);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This higher level function formats and appends the entire output to a string builder.
|
/// This higher level function formats and appends the entire output to a string builder.
|
||||||
|
|
@ -109,17 +122,17 @@ fn append_fields(b: &mut Builder, cfg: &Config, data: &Data) {
|
||||||
/// Returns:
|
/// Returns:
|
||||||
/// String to be outputted.
|
/// String to be outputted.
|
||||||
fn build_string(cfg: &Config, data: &Data) -> String {
|
fn build_string(cfg: &Config, data: &Data) -> String {
|
||||||
let mut b = Builder::default();
|
let mut b = Builder::default();
|
||||||
|
|
||||||
if cfg.render_prefix {
|
if cfg.render_prefix {
|
||||||
append_prefix(&mut b, data);
|
append_prefix(&mut b, data);
|
||||||
}
|
}
|
||||||
append_fields(&mut b, cfg, data);
|
append_fields(&mut b, cfg, data);
|
||||||
|
|
||||||
b.string().unwrap_or_else(|e| {
|
b.string().unwrap_or_else(|e| {
|
||||||
error!("{e}");
|
error!("{e}");
|
||||||
"Failed to unwrap string!".to_owned()
|
"Failed to unwrap string!".to_owned()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This higher level function calls the appropriate string building function depending on a few settings:
|
/// This higher level function calls the appropriate string building function depending on a few settings:
|
||||||
|
|
@ -131,10 +144,18 @@ fn build_string(cfg: &Config, data: &Data) -> String {
|
||||||
/// cfg: Config struct for the program.
|
/// cfg: Config struct for the program.
|
||||||
/// data: mutable Data struct containing the state of the program.
|
/// data: mutable Data struct containing the state of the program.
|
||||||
pub fn print_text(cfg: &Config, data: &mut Data) {
|
pub fn print_text(cfg: &Config, data: &mut Data) {
|
||||||
if (cfg.hide_output && data.current_player.is_none()) || data.field_text.is_empty() || cfg.metadata_fields.is_empty() {
|
if (cfg.hide_output && data.current_player.is_none())
|
||||||
println!("");
|
|| data.field_text.is_empty()
|
||||||
} else {
|
|| cfg.metadata_fields.is_empty()
|
||||||
cutoff(&cfg.metadata_fields, cfg.break_character, cfg.fuzzy, &mut data.field_text);
|
{
|
||||||
println!("{}", build_string(cfg, data));
|
println!("");
|
||||||
}
|
} else {
|
||||||
|
cutoff(
|
||||||
|
&cfg.metadata_fields,
|
||||||
|
cfg.break_character,
|
||||||
|
cfg.fuzzy,
|
||||||
|
&mut data.field_text,
|
||||||
|
);
|
||||||
|
println!("{}", build_string(cfg, data));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue