mirror of
https://github.com/tiffany352/rink-rs
synced 2024-11-10 13:44:15 +00:00
Suggest typo corrections
This commit is contained in:
parent
ce39db8e7d
commit
b537e0a8c5
3 changed files with 38 additions and 5 deletions
|
@ -19,6 +19,7 @@ gpl = []
|
|||
[dependencies]
|
||||
rust-gmp = "0.3.2"
|
||||
chrono = "0.2.25"
|
||||
strsim = "0.5.1"
|
||||
chrono-humanize = { version = "0.0.6", optional = true }
|
||||
linefeed = { version = "0.1.4", optional = true }
|
||||
irc = { version = "0.11.3", optional = true }
|
||||
|
|
41
src/eval.rs
41
src/eval.rs
|
@ -337,6 +337,39 @@ impl Context {
|
|||
(recip, String::from_utf8(buf).unwrap())
|
||||
}
|
||||
|
||||
fn typo_dym<'a>(&'a self, what: &str) -> Option<&'a str> {
|
||||
use strsim::jaro_winkler;
|
||||
|
||||
let mut best = None;
|
||||
{
|
||||
let mut try = |x: &'a str| {
|
||||
let score = jaro_winkler(x, what);
|
||||
let better = best.as_ref().map(|&(s, _v)| score > s).unwrap_or(true);
|
||||
if better {
|
||||
best = Some((score, x));
|
||||
}
|
||||
};
|
||||
|
||||
for k in &self.dimensions {
|
||||
try(&**k.0);
|
||||
}
|
||||
for (k, _v) in &self.units {
|
||||
try(&**k);
|
||||
}
|
||||
for (_u, k) in &self.quantities {
|
||||
try(&**k);
|
||||
}
|
||||
}
|
||||
best.and_then(|(s, v)| if s > 0.8 { Some(v) } else { None })
|
||||
}
|
||||
|
||||
fn unknown_unit_err(&self, name: &str) -> String {
|
||||
match self.typo_dym(name) {
|
||||
Some(x) => format!("Unknown unit {}, did you mean {}?", name, x),
|
||||
None => format!("Unknown unit {}", name)
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluates an expression to compute its value, *excluding* `->`
|
||||
/// conversions.
|
||||
pub fn eval(&self, expr: &Expr) -> Result<Value, String> {
|
||||
|
@ -371,7 +404,8 @@ impl Context {
|
|||
|
||||
match *expr {
|
||||
Expr::Unit(ref name) if name == "now" => Ok(Value::DateTime(date::now())),
|
||||
Expr::Unit(ref name) => self.lookup(name).ok_or(format!("Unknown unit {}", name)).map(Value::Number),
|
||||
Expr::Unit(ref name) =>
|
||||
self.lookup(name).ok_or_else(|| self.unknown_unit_err(name)).map(Value::Number),
|
||||
Expr::Quote(ref name) => Ok(Value::Number(Number::one_unit(Dim::new(&**name)))),
|
||||
Expr::Const(ref num, ref frac, ref exp) =>
|
||||
Number::from_parts(
|
||||
|
@ -661,10 +695,7 @@ impl Context {
|
|||
top.show(self), list))
|
||||
};
|
||||
let units = try!(list.iter().map(|x| {
|
||||
match self.lookup(x) {
|
||||
Some(x) => Ok(x),
|
||||
None => Err(format!("Unit {} does not exist", x))
|
||||
}
|
||||
self.lookup(x).ok_or_else(|| self.unknown_unit_err(x))
|
||||
}).collect::<Result<Vec<Number>, _>>());
|
||||
{
|
||||
let first = try!(units.first().ok_or(format!("Expected non-empty unit list")));
|
||||
|
|
|
@ -32,6 +32,7 @@ println!("{}", one_line(&mut ctx, "kWh / year -> W").unwrap());
|
|||
|
||||
extern crate gmp;
|
||||
extern crate chrono;
|
||||
extern crate strsim;
|
||||
#[cfg(feature = "chrono-humanize")]
|
||||
extern crate chrono_humanize;
|
||||
#[cfg(feature = "sandbox")]
|
||||
|
|
Loading…
Reference in a new issue