Fix ingredient parsing to be less obnoxious
This commit is contained in:
parent
7025ee9e3a
commit
63860cd05a
|
@ -131,10 +131,7 @@ fn prepare_grocery_list(ingredients: &Vec<(Ingredient, Vec<String>)>) -> Result<
|
|||
)?;
|
||||
writeln!(out)?; // leave an empty line
|
||||
for (ingredient, recipes) in ingredients {
|
||||
writeln!(out, "- [ ] {}", ingredient)?;
|
||||
for recipe in recipes {
|
||||
writeln!(out, " * {}", recipe)?;
|
||||
}
|
||||
writeln!(out, "- [ ] {} ({})", ingredient, recipes.join(", "))?;
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
|
|
|
@ -159,7 +159,7 @@ impl<'de> serde::de::Visitor<'de> for IngredientVisitor {
|
|||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
use std::cmp::min;
|
||||
use std::cmp::{max, min};
|
||||
|
||||
let quantity_regex_start: regex::Regex =
|
||||
regex::Regex::new(r"^(?P<v>[0-9,\.]+)\s*(?P<u>\w+)?\s+(?P<i>.*)").unwrap();
|
||||
|
@ -170,20 +170,26 @@ impl<'de> serde::de::Visitor<'de> for IngredientVisitor {
|
|||
.captures(value)
|
||||
.or_else(|| quantity_regex_end.captures(value))
|
||||
{
|
||||
let v = captures.name("v").unwrap().as_str();
|
||||
let vm = captures.name("v").unwrap();
|
||||
let v = vm.as_str();
|
||||
let um = captures.name("u");
|
||||
let u = um.map(|u| u.as_str()).unwrap_or("");
|
||||
let im = captures.name("i").unwrap();
|
||||
let i = im.as_str();
|
||||
|
||||
let (amount, unit) = Self::parse_quantity(v, u)?;
|
||||
let (mut amount, unit) = Self::parse_quantity(v, u)?;
|
||||
let name = match unit {
|
||||
Unit::None => {
|
||||
// pick the longest string including what was recognized by the regex as the possible unit
|
||||
let start = um
|
||||
.map(|um| min(um.start(), im.start()))
|
||||
.unwrap_or_else(|| im.start());
|
||||
&value[start..im.end()]
|
||||
let range = um
|
||||
.map(|um| min(um.start(), im.start())..max(um.end(), im.end()))
|
||||
.unwrap_or_else(|| im.start()..im.end());
|
||||
|
||||
if range.start <= vm.start() && range.end >= vm.end() {
|
||||
amount = 1.0; // e.g. for "Parsley, 5 leaves" -> Ingredient { 1, no unit, 'Parsley, 5 leaves' }
|
||||
}
|
||||
|
||||
&value[range]
|
||||
}
|
||||
_ => i,
|
||||
}
|
||||
|
@ -218,7 +224,7 @@ impl IngredientVisitor {
|
|||
v = v / 1000.0;
|
||||
Unit::Kilogram
|
||||
}
|
||||
"hg" => {
|
||||
"hg" | "etto" | "etti" => {
|
||||
v = v / 10.0;
|
||||
Unit::Kilogram
|
||||
}
|
||||
|
@ -231,15 +237,15 @@ impl IngredientVisitor {
|
|||
v = v / 100.0;
|
||||
Unit::Liter
|
||||
}
|
||||
"ml" => {
|
||||
"ml" | "cc" => {
|
||||
v = v / 1000.0;
|
||||
Unit::Liter
|
||||
}
|
||||
"tl" => {
|
||||
"tl" | "cucchiaino" | "cucchiaini" => {
|
||||
v = v / 1000.0 * 5.0;
|
||||
Unit::Liter
|
||||
}
|
||||
"el" => {
|
||||
"el" | "cucchiaio" | "cucchiai" => {
|
||||
v = v / 1000.0 * 15.0;
|
||||
Unit::Liter
|
||||
}
|
||||
|
@ -260,12 +266,19 @@ impl IngredientVisitor {
|
|||
|
||||
impl core::fmt::Display for Ingredient {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
const PRECISION: u32 = 3;
|
||||
const ROUNDING_EXP: f64 = 10isize.pow(PRECISION) as f64;
|
||||
|
||||
write!(
|
||||
f,
|
||||
"{amount:.3}{unit} {name}",
|
||||
"{amount}{pad}{unit} {name}",
|
||||
name = self.name,
|
||||
amount = self.amount,
|
||||
unit = self.unit
|
||||
amount = (self.amount * ROUNDING_EXP).round() / ROUNDING_EXP,
|
||||
pad = match self.unit {
|
||||
Unit::None => "",
|
||||
_ => " ",
|
||||
},
|
||||
unit = self.unit,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue