refactor(core): centralize formatting logic
Move formatting logic to a new `format` module and update `main.rs` and `persistence` to use it. - Create `src/format.rs` with shared formatting functions. - Update `src/main.rs` to include the `format` module. - Refactor `src/persistence/mod.rs` to use the new `display_text` logic via `GridLayout` . Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
This commit is contained in:
50
src/format.rs
Normal file
50
src/format.rs
Normal file
@ -0,0 +1,50 @@
|
||||
use crate::model::cell::CellValue;
|
||||
|
||||
/// Format a CellValue for display with number formatting options.
|
||||
pub fn format_value(v: Option<&CellValue>, comma: bool, decimals: u8) -> String {
|
||||
match v {
|
||||
Some(CellValue::Number(n)) => format_f64(*n, comma, decimals),
|
||||
Some(CellValue::Text(s)) => s.clone(),
|
||||
None => String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a number format string like ",.0" into (use_commas, decimal_places).
|
||||
pub fn parse_number_format(fmt: &str) -> (bool, u8) {
|
||||
let comma = fmt.contains(',');
|
||||
let decimals = fmt
|
||||
.rfind('.')
|
||||
.and_then(|i| fmt[i + 1..].parse::<u8>().ok())
|
||||
.unwrap_or(0);
|
||||
(comma, decimals)
|
||||
}
|
||||
|
||||
/// Format an f64 with optional comma grouping and decimal places.
|
||||
pub fn format_f64(n: f64, comma: bool, decimals: u8) -> String {
|
||||
let formatted = format!("{:.prec$}", n, prec = decimals as usize);
|
||||
if !comma {
|
||||
return formatted;
|
||||
}
|
||||
let (int_part, dec_part) = if let Some(dot) = formatted.find('.') {
|
||||
(&formatted[..dot], Some(&formatted[dot..]))
|
||||
} else {
|
||||
(&formatted[..], None)
|
||||
};
|
||||
let is_neg = int_part.starts_with('-');
|
||||
let digits = if is_neg { &int_part[1..] } else { int_part };
|
||||
let mut result = String::new();
|
||||
for (idx, c) in digits.chars().rev().enumerate() {
|
||||
if idx > 0 && idx % 3 == 0 {
|
||||
result.push(',');
|
||||
}
|
||||
result.push(c);
|
||||
}
|
||||
if is_neg {
|
||||
result.push('-');
|
||||
}
|
||||
let mut out: String = result.chars().rev().collect();
|
||||
if let Some(dec) = dec_part {
|
||||
out.push_str(dec);
|
||||
}
|
||||
out
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
mod command;
|
||||
mod draw;
|
||||
mod format;
|
||||
mod formula;
|
||||
mod import;
|
||||
mod model;
|
||||
|
||||
@ -458,17 +458,7 @@ pub fn export_csv(model: &Model, view_name: &str, path: &Path) -> Result<()> {
|
||||
out.push(',');
|
||||
}
|
||||
let row_values: Vec<String> = (0..layout.col_count())
|
||||
.map(|ci| {
|
||||
if layout.is_records_mode() {
|
||||
layout.records_display(ri, ci).unwrap_or_default()
|
||||
} else {
|
||||
layout
|
||||
.cell_key(ri, ci)
|
||||
.and_then(|key| model.evaluate_aggregated(&key, &layout.none_cats))
|
||||
.map(|v| v.to_string())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
})
|
||||
.map(|ci| layout.display_text(model, ri, ci, false, 0))
|
||||
.collect();
|
||||
out.push_str(&row_values.join(","));
|
||||
out.push('\n');
|
||||
|
||||
Reference in New Issue
Block a user