Prepare eval error handling for cli arg errors
This commit is contained in:
parent
279bf4a4d1
commit
ff627b98df
8 changed files with 107 additions and 93 deletions
|
|
@ -139,7 +139,7 @@ pub fn run() {
|
||||||
let range = find_range(&opt, now);
|
let range = find_range(&opt, now);
|
||||||
|
|
||||||
if let Err(e) = run_command(&opt, &mut files, range, now) {
|
if let Err(e) = run_command(&opt, &mut files, range, now) {
|
||||||
e.print(&files);
|
e.print(&files.sources());
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
use std::result;
|
use std::result;
|
||||||
|
|
||||||
use crate::eval;
|
use crate::eval::{self, SourceInfo};
|
||||||
use crate::files::Files;
|
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
|
@ -14,9 +13,9 @@ pub enum Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
pub fn print(&self, files: &Files) {
|
pub fn print<'a>(&self, sources: &[SourceInfo<'a>]) {
|
||||||
match self {
|
match self {
|
||||||
Error::Eval(e) => e.print(files),
|
Error::Eval(e) => e.print(sources),
|
||||||
Error::NoSuchEntry(n) => eprintln!("No entry with number {}", n),
|
Error::NoSuchEntry(n) => eprintln!("No entry with number {}", n),
|
||||||
Error::NotATask(ns) => {
|
Error::NotATask(ns) => {
|
||||||
if ns.is_empty() {
|
if ns.is_empty() {
|
||||||
|
|
|
||||||
|
|
@ -216,7 +216,7 @@ impl<'a> CommandState<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::MoveWithoutSource {
|
Err(Error::MoveWithoutSource {
|
||||||
file: self.command.source.file(),
|
index: self.command.source.file(),
|
||||||
span,
|
span,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -103,13 +103,13 @@ impl DateSpec {
|
||||||
Some((start, skip, range))
|
Some((start, skip, range))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step(file: usize, from: NaiveDate, repeat: &Spanned<Delta>) -> Result<NaiveDate> {
|
fn step(index: usize, from: NaiveDate, repeat: &Spanned<Delta>) -> Result<NaiveDate> {
|
||||||
let to = repeat.value.apply_date(file, from)?;
|
let to = repeat.value.apply_date(index, from)?;
|
||||||
if to > from {
|
if to > from {
|
||||||
Ok(to)
|
Ok(to)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::RepeatDidNotMoveForwards {
|
Err(Error::RepeatDidNotMoveForwards {
|
||||||
file,
|
index,
|
||||||
span: repeat.span,
|
span: repeat.span,
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
|
|
@ -117,13 +117,13 @@ impl DateSpec {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dates(&self, file: usize, start: NaiveDate) -> Result<Dates> {
|
fn dates(&self, index: usize, start: NaiveDate) -> Result<Dates> {
|
||||||
let root = self.start_delta.apply_date(file, start)?;
|
let root = self.start_delta.apply_date(index, start)?;
|
||||||
Ok(if let Some(root_time) = self.start_time {
|
Ok(if let Some(root_time) = self.start_time {
|
||||||
let (other, other_time) = self.end_delta.apply_date_time(file, root, root_time)?;
|
let (other, other_time) = self.end_delta.apply_date_time(index, root, root_time)?;
|
||||||
Dates::new_with_time(root, root_time, other, other_time)
|
Dates::new_with_time(root, root_time, other, other_time)
|
||||||
} else {
|
} else {
|
||||||
let other = self.end_delta.apply_date(file, root)?;
|
let other = self.end_delta.apply_date(index, root)?;
|
||||||
Dates::new(root, other)
|
Dates::new(root, other)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -131,23 +131,23 @@ impl DateSpec {
|
||||||
|
|
||||||
impl<'a> CommandState<'a> {
|
impl<'a> CommandState<'a> {
|
||||||
pub fn eval_date_spec(&mut self, spec: DateSpec) -> Result<()> {
|
pub fn eval_date_spec(&mut self, spec: DateSpec) -> Result<()> {
|
||||||
let file = self.command.source.file();
|
let index = self.command.source.file();
|
||||||
if let Some(repeat) = &spec.repeat {
|
if let Some(repeat) = &spec.repeat {
|
||||||
if let Some((mut start, skip, range)) = spec.start_and_range(self) {
|
if let Some((mut start, skip, range)) = spec.start_and_range(self) {
|
||||||
if skip {
|
if skip {
|
||||||
start = DateSpec::step(file, start, repeat)?;
|
start = DateSpec::step(index, start, repeat)?;
|
||||||
}
|
}
|
||||||
while start < range.from() {
|
while start < range.from() {
|
||||||
start = DateSpec::step(file, start, repeat)?;
|
start = DateSpec::step(index, start, repeat)?;
|
||||||
}
|
}
|
||||||
while start <= range.until() {
|
while start <= range.until() {
|
||||||
let dates = spec.dates(file, start)?;
|
let dates = spec.dates(index, start)?;
|
||||||
self.add(self.kind(), Some(dates));
|
self.add(self.kind(), Some(dates));
|
||||||
start = DateSpec::step(file, start, repeat)?;
|
start = DateSpec::step(index, start, repeat)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let dates = spec.dates(file, spec.start)?;
|
let dates = spec.dates(index, spec.start)?;
|
||||||
self.add(self.kind(), Some(dates));
|
self.add(self.kind(), Some(dates));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ pub enum Var {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Var {
|
impl Var {
|
||||||
fn eval(self, file: usize, date: NaiveDate) -> Result<i64> {
|
fn eval(self, index: usize, date: NaiveDate) -> Result<i64> {
|
||||||
Ok(match self {
|
Ok(match self {
|
||||||
Var::JulianDay => date.num_days_from_ce().into(),
|
Var::JulianDay => date.num_days_from_ce().into(),
|
||||||
Var::Year => date.year().into(),
|
Var::Year => date.year().into(),
|
||||||
|
|
@ -81,7 +81,7 @@ impl Var {
|
||||||
}
|
}
|
||||||
Var::Easter(span) => {
|
Var::Easter(span) => {
|
||||||
let e = computus::gregorian(date.year()).map_err(|e| Error::Easter {
|
let e = computus::gregorian(date.year()).map_err(|e| Error::Easter {
|
||||||
file,
|
index,
|
||||||
span,
|
span,
|
||||||
date,
|
date,
|
||||||
msg: e,
|
msg: e,
|
||||||
|
|
@ -199,46 +199,46 @@ impl From<Weekday> for Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Expr {
|
impl Expr {
|
||||||
fn eval(&self, file: usize, date: NaiveDate) -> Result<i64> {
|
fn eval(&self, index: usize, date: NaiveDate) -> Result<i64> {
|
||||||
Ok(match self {
|
Ok(match self {
|
||||||
Expr::Lit(l) => *l,
|
Expr::Lit(l) => *l,
|
||||||
Expr::Var(v) => v.eval(file, date)?,
|
Expr::Var(v) => v.eval(index, date)?,
|
||||||
Expr::Neg(e) => -e.eval(file, date)?,
|
Expr::Neg(e) => -e.eval(index, date)?,
|
||||||
Expr::Add(a, b) => a.eval(file, date)? + b.eval(file, date)?,
|
Expr::Add(a, b) => a.eval(index, date)? + b.eval(index, date)?,
|
||||||
Expr::Sub(a, b) => a.eval(file, date)? - b.eval(file, date)?,
|
Expr::Sub(a, b) => a.eval(index, date)? - b.eval(index, date)?,
|
||||||
Expr::Mul(a, b) => a.eval(file, date)? * b.eval(file, date)?,
|
Expr::Mul(a, b) => a.eval(index, date)? * b.eval(index, date)?,
|
||||||
Expr::Div(a, b, span) => {
|
Expr::Div(a, b, span) => {
|
||||||
let b = b.eval(file, date)?;
|
let b = b.eval(index, date)?;
|
||||||
if b == 0 {
|
if b == 0 {
|
||||||
return Err(Error::DivByZero {
|
return Err(Error::DivByZero {
|
||||||
file,
|
index,
|
||||||
span: *span,
|
span: *span,
|
||||||
date,
|
date,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
a.eval(file, date)?.div_euclid(b)
|
a.eval(index, date)?.div_euclid(b)
|
||||||
}
|
}
|
||||||
Expr::Mod(a, b, span) => {
|
Expr::Mod(a, b, span) => {
|
||||||
let b = b.eval(file, date)?;
|
let b = b.eval(index, date)?;
|
||||||
if b == 0 {
|
if b == 0 {
|
||||||
return Err(Error::ModByZero {
|
return Err(Error::ModByZero {
|
||||||
file,
|
index,
|
||||||
span: *span,
|
span: *span,
|
||||||
date,
|
date,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
a.eval(file, date)?.rem_euclid(b)
|
a.eval(index, date)?.rem_euclid(b)
|
||||||
}
|
}
|
||||||
Expr::Eq(a, b) => b2i(a.eval(file, date)? == b.eval(file, date)?),
|
Expr::Eq(a, b) => b2i(a.eval(index, date)? == b.eval(index, date)?),
|
||||||
Expr::Neq(a, b) => b2i(a.eval(file, date)? != b.eval(file, date)?),
|
Expr::Neq(a, b) => b2i(a.eval(index, date)? != b.eval(index, date)?),
|
||||||
Expr::Lt(a, b) => b2i(a.eval(file, date)? < b.eval(file, date)?),
|
Expr::Lt(a, b) => b2i(a.eval(index, date)? < b.eval(index, date)?),
|
||||||
Expr::Lte(a, b) => b2i(a.eval(file, date)? <= b.eval(file, date)?),
|
Expr::Lte(a, b) => b2i(a.eval(index, date)? <= b.eval(index, date)?),
|
||||||
Expr::Gt(a, b) => b2i(a.eval(file, date)? > b.eval(file, date)?),
|
Expr::Gt(a, b) => b2i(a.eval(index, date)? > b.eval(index, date)?),
|
||||||
Expr::Gte(a, b) => b2i(a.eval(file, date)? >= b.eval(file, date)?),
|
Expr::Gte(a, b) => b2i(a.eval(index, date)? >= b.eval(index, date)?),
|
||||||
Expr::Not(e) => b2i(!i2b(e.eval(file, date)?)),
|
Expr::Not(e) => b2i(!i2b(e.eval(index, date)?)),
|
||||||
Expr::And(a, b) => b2i(i2b(a.eval(file, date)?) && i2b(b.eval(file, date)?)),
|
Expr::And(a, b) => b2i(i2b(a.eval(index, date)?) && i2b(b.eval(index, date)?)),
|
||||||
Expr::Or(a, b) => b2i(i2b(a.eval(file, date)?) || i2b(b.eval(file, date)?)),
|
Expr::Or(a, b) => b2i(i2b(a.eval(index, date)?) || i2b(b.eval(index, date)?)),
|
||||||
Expr::Xor(a, b) => b2i(i2b(a.eval(file, date)?) ^ i2b(b.eval(file, date)?)),
|
Expr::Xor(a, b) => b2i(i2b(a.eval(index, date)?) ^ i2b(b.eval(index, date)?)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -341,29 +341,29 @@ impl FormulaSpec {
|
||||||
s.limit_from_until(range)
|
s.limit_from_until(range)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dates(&self, file: usize, start: NaiveDate) -> Result<Dates> {
|
fn dates(&self, index: usize, start: NaiveDate) -> Result<Dates> {
|
||||||
let root = self.start_delta.apply_date(file, start)?;
|
let root = self.start_delta.apply_date(index, start)?;
|
||||||
Ok(if let Some(root_time) = self.start_time {
|
Ok(if let Some(root_time) = self.start_time {
|
||||||
let (other, other_time) = self.end_delta.apply_date_time(file, root, root_time)?;
|
let (other, other_time) = self.end_delta.apply_date_time(index, root, root_time)?;
|
||||||
Dates::new_with_time(root, root_time, other, other_time)
|
Dates::new_with_time(root, root_time, other, other_time)
|
||||||
} else {
|
} else {
|
||||||
let other = self.end_delta.apply_date(file, root)?;
|
let other = self.end_delta.apply_date(index, root)?;
|
||||||
Dates::new(root, other)
|
Dates::new(root, other)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval(&self, file: usize, date: NaiveDate) -> Result<bool> {
|
fn eval(&self, index: usize, date: NaiveDate) -> Result<bool> {
|
||||||
Ok(i2b(self.start.eval(file, date)?))
|
Ok(i2b(self.start.eval(index, date)?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CommandState<'a> {
|
impl<'a> CommandState<'a> {
|
||||||
pub fn eval_formula_spec(&mut self, spec: FormulaSpec) -> Result<()> {
|
pub fn eval_formula_spec(&mut self, spec: FormulaSpec) -> Result<()> {
|
||||||
if let Some(range) = spec.range(self) {
|
if let Some(range) = spec.range(self) {
|
||||||
let file = self.command.source.file();
|
let index = self.command.source.file();
|
||||||
for day in range.days() {
|
for day in range.days() {
|
||||||
if spec.eval(file, day)? {
|
if spec.eval(index, day)? {
|
||||||
let dates = spec.dates(file, day)?;
|
let dates = spec.dates(index, day)?;
|
||||||
self.add(self.kind(), Some(dates));
|
self.add(self.kind(), Some(dates));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ impl From<&commands::Delta> for Delta {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DeltaEval {
|
struct DeltaEval {
|
||||||
file: usize,
|
index: usize,
|
||||||
start: NaiveDate,
|
start: NaiveDate,
|
||||||
start_time: Option<Time>,
|
start_time: Option<Time>,
|
||||||
curr: NaiveDate,
|
curr: NaiveDate,
|
||||||
|
|
@ -151,9 +151,9 @@ struct DeltaEval {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeltaEval {
|
impl DeltaEval {
|
||||||
fn new(file: usize, start: NaiveDate, start_time: Option<Time>) -> Self {
|
fn new(index: usize, start: NaiveDate, start_time: Option<Time>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
file,
|
index,
|
||||||
start,
|
start,
|
||||||
start_time,
|
start_time,
|
||||||
curr: start,
|
curr: start,
|
||||||
|
|
@ -163,7 +163,7 @@ impl DeltaEval {
|
||||||
|
|
||||||
fn err_step(&self, span: Span) -> Error {
|
fn err_step(&self, span: Span) -> Error {
|
||||||
Error::DeltaInvalidStep {
|
Error::DeltaInvalidStep {
|
||||||
file: self.file,
|
index: self.index,
|
||||||
span,
|
span,
|
||||||
start: self.start,
|
start: self.start,
|
||||||
start_time: self.start_time,
|
start_time: self.start_time,
|
||||||
|
|
@ -174,7 +174,7 @@ impl DeltaEval {
|
||||||
|
|
||||||
fn err_time(&self, span: Span) -> Error {
|
fn err_time(&self, span: Span) -> Error {
|
||||||
Error::DeltaNoTime {
|
Error::DeltaNoTime {
|
||||||
file: self.file,
|
index: self.index,
|
||||||
span,
|
span,
|
||||||
start: self.start,
|
start: self.start,
|
||||||
prev: self.curr,
|
prev: self.curr,
|
||||||
|
|
@ -315,27 +315,27 @@ impl Delta {
|
||||||
|
|
||||||
fn apply(
|
fn apply(
|
||||||
&self,
|
&self,
|
||||||
file: usize,
|
index: usize,
|
||||||
start: (NaiveDate, Option<Time>),
|
start: (NaiveDate, Option<Time>),
|
||||||
) -> Result<(NaiveDate, Option<Time>)> {
|
) -> Result<(NaiveDate, Option<Time>)> {
|
||||||
let mut eval = DeltaEval::new(file, start.0, start.1);
|
let mut eval = DeltaEval::new(index, start.0, start.1);
|
||||||
for step in &self.steps {
|
for step in &self.steps {
|
||||||
eval.apply(step)?;
|
eval.apply(step)?;
|
||||||
}
|
}
|
||||||
Ok((eval.curr, eval.curr_time))
|
Ok((eval.curr, eval.curr_time))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_date(&self, file: usize, date: NaiveDate) -> Result<NaiveDate> {
|
pub fn apply_date(&self, index: usize, date: NaiveDate) -> Result<NaiveDate> {
|
||||||
Ok(self.apply(file, (date, None))?.0)
|
Ok(self.apply(index, (date, None))?.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_date_time(
|
pub fn apply_date_time(
|
||||||
&self,
|
&self,
|
||||||
file: usize,
|
index: usize,
|
||||||
date: NaiveDate,
|
date: NaiveDate,
|
||||||
time: Time,
|
time: Time,
|
||||||
) -> Result<(NaiveDate, Time)> {
|
) -> Result<(NaiveDate, Time)> {
|
||||||
let (date, time) = self.apply(file, (date, Some(time)))?;
|
let (date, time) = self.apply(index, (date, Some(time)))?;
|
||||||
Ok((date, time.expect("time was not preserved")))
|
Ok((date, time.expect("time was not preserved")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,13 @@ use std::result;
|
||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
|
|
||||||
use crate::files::primitives::{Span, Time};
|
use crate::files::primitives::{Span, Time};
|
||||||
use crate::files::Files;
|
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// A delta step resulted in an invalid date.
|
/// A delta step resulted in an invalid date.
|
||||||
#[error("delta step resulted in invalid date")]
|
#[error("delta step resulted in invalid date")]
|
||||||
DeltaInvalidStep {
|
DeltaInvalidStep {
|
||||||
file: usize,
|
index: usize,
|
||||||
span: Span,
|
span: Span,
|
||||||
start: NaiveDate,
|
start: NaiveDate,
|
||||||
start_time: Option<Time>,
|
start_time: Option<Time>,
|
||||||
|
|
@ -20,7 +19,7 @@ pub enum Error {
|
||||||
/// A time-based delta step was applied to a date without time.
|
/// A time-based delta step was applied to a date without time.
|
||||||
#[error("time-based delta step applied to date without time")]
|
#[error("time-based delta step applied to date without time")]
|
||||||
DeltaNoTime {
|
DeltaNoTime {
|
||||||
file: usize,
|
index: usize,
|
||||||
span: Span,
|
span: Span,
|
||||||
start: NaiveDate,
|
start: NaiveDate,
|
||||||
prev: NaiveDate,
|
prev: NaiveDate,
|
||||||
|
|
@ -30,7 +29,7 @@ pub enum Error {
|
||||||
/// in time (`to < from`).
|
/// in time (`to < from`).
|
||||||
#[error("repeat delta did not move forwards")]
|
#[error("repeat delta did not move forwards")]
|
||||||
RepeatDidNotMoveForwards {
|
RepeatDidNotMoveForwards {
|
||||||
file: usize,
|
index: usize,
|
||||||
span: Span,
|
span: Span,
|
||||||
from: NaiveDate,
|
from: NaiveDate,
|
||||||
to: NaiveDate,
|
to: NaiveDate,
|
||||||
|
|
@ -38,38 +37,48 @@ pub enum Error {
|
||||||
/// A `MOVE a TO b` statement was executed, but there was no entry at the
|
/// A `MOVE a TO b` statement was executed, but there was no entry at the
|
||||||
/// date `a`.
|
/// date `a`.
|
||||||
#[error("tried to move nonexisting entry")]
|
#[error("tried to move nonexisting entry")]
|
||||||
MoveWithoutSource { file: usize, span: Span },
|
MoveWithoutSource { index: usize, span: Span },
|
||||||
/// A division by zero has occurred.
|
/// A division by zero has occurred.
|
||||||
#[error("tried to divide by zero")]
|
#[error("tried to divide by zero")]
|
||||||
DivByZero {
|
DivByZero {
|
||||||
file: usize,
|
index: usize,
|
||||||
span: Span,
|
span: Span,
|
||||||
date: NaiveDate,
|
date: NaiveDate,
|
||||||
},
|
},
|
||||||
/// A modulo operation by zero has occurred.
|
/// A modulo operation by zero has occurred.
|
||||||
#[error("tried to modulo by zero")]
|
#[error("tried to modulo by zero")]
|
||||||
ModByZero {
|
ModByZero {
|
||||||
file: usize,
|
index: usize,
|
||||||
span: Span,
|
span: Span,
|
||||||
date: NaiveDate,
|
date: NaiveDate,
|
||||||
},
|
},
|
||||||
/// Easter calculation failed.
|
/// Easter calculation failed.
|
||||||
#[error("easter calculation failed")]
|
#[error("easter calculation failed")]
|
||||||
Easter {
|
Easter {
|
||||||
file: usize,
|
index: usize,
|
||||||
span: Span,
|
span: Span,
|
||||||
date: NaiveDate,
|
date: NaiveDate,
|
||||||
msg: &'static str,
|
msg: &'static str,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct SourceInfo<'a> {
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub content: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
fn print_at(files: &Files, file: &usize, span: &Span, message: String) {
|
fn print_at<'a>(sources: &[SourceInfo<'a>], index: &usize, span: &Span, message: String) {
|
||||||
use pest::error as pe;
|
use pest::error as pe;
|
||||||
let (name, content) = files.file(*file).expect("file index is valid");
|
|
||||||
let span = pest::Span::new(content, span.start, span.end).expect("span is valid");
|
let source = sources.get(*index).expect("index is valid");
|
||||||
|
let span = pest::Span::new(source.content, span.start, span.end).expect("span is valid");
|
||||||
let variant = pe::ErrorVariant::<()>::CustomError { message };
|
let variant = pe::ErrorVariant::<()>::CustomError { message };
|
||||||
let error = pe::Error::new_from_span(variant, span).with_path(&name.to_string_lossy());
|
let mut error = pe::Error::new_from_span(variant, span);
|
||||||
|
if let Some(name) = &source.name {
|
||||||
|
error = error.with_path(name);
|
||||||
|
}
|
||||||
|
|
||||||
eprintln!("{}", error);
|
eprintln!("{}", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,10 +89,10 @@ impl Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print(&self, files: &Files) {
|
pub fn print<'a>(&self, sources: &[SourceInfo<'a>]) {
|
||||||
match self {
|
match self {
|
||||||
Error::DeltaInvalidStep {
|
Error::DeltaInvalidStep {
|
||||||
file,
|
index,
|
||||||
span,
|
span,
|
||||||
start,
|
start,
|
||||||
start_time,
|
start_time,
|
||||||
|
|
@ -97,10 +106,10 @@ impl Error {
|
||||||
Self::fmt_date_time(*start, *start_time),
|
Self::fmt_date_time(*start, *start_time),
|
||||||
Self::fmt_date_time(*prev, *prev_time),
|
Self::fmt_date_time(*prev, *prev_time),
|
||||||
);
|
);
|
||||||
Self::print_at(files, file, span, msg);
|
Self::print_at(sources, index, span, msg);
|
||||||
}
|
}
|
||||||
Error::DeltaNoTime {
|
Error::DeltaNoTime {
|
||||||
file,
|
index,
|
||||||
span,
|
span,
|
||||||
start,
|
start,
|
||||||
prev,
|
prev,
|
||||||
|
|
@ -111,10 +120,10 @@ impl Error {
|
||||||
\nPrevious step: {}",
|
\nPrevious step: {}",
|
||||||
start, prev
|
start, prev
|
||||||
);
|
);
|
||||||
Self::print_at(files, file, span, msg);
|
Self::print_at(sources, index, span, msg);
|
||||||
}
|
}
|
||||||
Error::RepeatDidNotMoveForwards {
|
Error::RepeatDidNotMoveForwards {
|
||||||
file,
|
index,
|
||||||
span,
|
span,
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
|
|
@ -124,30 +133,30 @@ impl Error {
|
||||||
\nMoved from {} to {}",
|
\nMoved from {} to {}",
|
||||||
from, to
|
from, to
|
||||||
);
|
);
|
||||||
Self::print_at(files, file, span, msg);
|
Self::print_at(sources, index, span, msg);
|
||||||
}
|
}
|
||||||
Error::MoveWithoutSource { file, span } => {
|
Error::MoveWithoutSource { index, span } => {
|
||||||
let msg = "Tried to move nonexisting entry".to_string();
|
let msg = "Tried to move nonexisting entry".to_string();
|
||||||
Self::print_at(files, file, span, msg);
|
Self::print_at(sources, index, span, msg);
|
||||||
}
|
}
|
||||||
Error::DivByZero { file, span, date } => {
|
Error::DivByZero { index, span, date } => {
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"Tried to divide by zero\
|
"Tried to divide by zero\
|
||||||
\nAt date: {}",
|
\nAt date: {}",
|
||||||
date
|
date
|
||||||
);
|
);
|
||||||
Self::print_at(files, file, span, msg);
|
Self::print_at(sources, index, span, msg);
|
||||||
}
|
}
|
||||||
Error::ModByZero { file, span, date } => {
|
Error::ModByZero { index, span, date } => {
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"Tried to modulo by zero\
|
"Tried to modulo by zero\
|
||||||
\nAt date: {}",
|
\nAt date: {}",
|
||||||
date
|
date
|
||||||
);
|
);
|
||||||
Self::print_at(files, file, span, msg);
|
Self::print_at(sources, index, span, msg);
|
||||||
}
|
}
|
||||||
Error::Easter {
|
Error::Easter {
|
||||||
file,
|
index,
|
||||||
span,
|
span,
|
||||||
date,
|
date,
|
||||||
msg,
|
msg,
|
||||||
|
|
@ -158,7 +167,7 @@ impl Error {
|
||||||
\nReason: {}",
|
\nReason: {}",
|
||||||
date, msg
|
date, msg
|
||||||
);
|
);
|
||||||
Self::print_at(files, file, span, msg);
|
Self::print_at(sources, index, span, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
src/files.rs
12
src/files.rs
|
|
@ -5,6 +5,8 @@ use std::path::{Path, PathBuf};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use tzfile::Tz;
|
use tzfile::Tz;
|
||||||
|
|
||||||
|
use crate::eval::SourceInfo;
|
||||||
|
|
||||||
use self::commands::{Command, Done, File};
|
use self::commands::{Command, Done, File};
|
||||||
pub use self::error::{Error, Result};
|
pub use self::error::{Error, Result};
|
||||||
|
|
||||||
|
|
@ -164,10 +166,14 @@ impl Files {
|
||||||
&self.files[source.file].file.commands[source.command]
|
&self.files[source.file].file.commands[source.command]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn file(&self, file: usize) -> Option<(&Path, &str)> {
|
pub fn sources(&self) -> Vec<SourceInfo<'_>> {
|
||||||
self.files
|
self.files
|
||||||
.get(file)
|
.iter()
|
||||||
.map(|f| (&f.name as &Path, &f.file.contents as &str))
|
.map(|f| SourceInfo {
|
||||||
|
name: Some(f.name.to_string_lossy().to_string()),
|
||||||
|
content: &f.file.contents,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a [`Done`] statement to the task identified by `source`.
|
/// Add a [`Done`] statement to the task identified by `source`.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue