From 5e47dddd4cdfa07e0fb1321c6d72521b191d52a6 Mon Sep 17 00:00:00 2001 From: Joscha Date: Wed, 5 Jan 2022 02:59:03 +0100 Subject: [PATCH] Make error formatting more generic Now, some errors are generic over the FileId type, meaning I can now pretty-print command line argument errors as well as normal errors with the same machinery. This is accomplished via the Eprint trait, whose generics are a tad complex but probably still fine. --- src/cli.rs | 22 +++++++++---------- src/error.rs | 28 ++++++++++++++++++++++++ src/eval/error.rs | 38 +++++++++++++++------------------ src/files.rs | 53 ++++++++++++++++++++++++++++++++++------------ src/files/error.rs | 28 ++++++++++++------------ src/main.rs | 1 + 6 files changed, 111 insertions(+), 59 deletions(-) create mode 100644 src/error.rs diff --git a/src/cli.rs b/src/cli.rs index 2decacf..10b4e36 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -3,9 +3,11 @@ use std::str::FromStr; use std::{process, result}; use chrono::{NaiveDate, NaiveDateTime}; +use codespan_reporting::files::SimpleFile; use directories::ProjectDirs; use structopt::StructOpt; +use crate::error; // use crate::eval::{DateRange, Entry, EntryMode, SourceInfo}; use crate::files::arguments::Range; use crate::files::{self, Files}; @@ -72,8 +74,6 @@ fn load_files(opt: &Opt, files: &mut Files) -> result::Result<(), files::Error> files.load(&file) } -/* - fn find_now(opt: &Opt, files: &Files) -> NaiveDateTime { let now = files.now().naive_local(); if let Some(date) = opt.date { @@ -83,6 +83,8 @@ fn find_now(opt: &Opt, files: &Files) -> NaiveDateTime { } } +/* + fn find_entries(files: &Files, range: DateRange) -> Result> { Ok(files.eval(EntryMode::Relevant, range)?) } @@ -136,24 +138,20 @@ pub fn run() { let mut files = Files::new(); if let Err(e) = load_files(&opt, &mut files) { - e.print(&files); + error::eprint_error(&files, &e); process::exit(1); } - /* - let now = find_now(&opt, &files); // Kinda ugly, but it can stay for now (until it grows at least). let range = match Range::from_str(&opt.range) { - Ok(range) => match range.eval(0, now.date()) { + Ok(range) => match range.eval((), now.date()) { Ok(range) => range, Err(e) => { eprintln!("Failed to evaluate --range:"); - e.print(&[SourceInfo { - name: Some("--range".to_string()), - content: &opt.range, - }]); + let file = SimpleFile::new("--range", &opt.range); + error::eprint_error(&file, &e); process::exit(1) } }, @@ -163,6 +161,8 @@ pub fn run() { } }; + /* + if let Err(e) = run_command(&opt, &mut files, range, now) { e.print(&files.sources()); process::exit(1); @@ -171,7 +171,7 @@ pub fn run() { */ if let Err(e) = files.save() { - e.print(&files); + error::eprint_error(&files, &e); process::exit(1); } } diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..89e85e7 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,28 @@ +use codespan_reporting::diagnostic::Diagnostic; +use codespan_reporting::files::Files; +use codespan_reporting::term::{self, Config}; +use termcolor::StandardStream; + +pub trait Eprint<'a, F: Files<'a>> { + fn eprint_diagnostic<'f: 'a>( + files: &'f F, + config: &Config, + diagnostic: &Diagnostic, + ) { + let mut out = StandardStream::stderr(termcolor::ColorChoice::Auto); + if let Err(e) = term::emit(&mut out, config, files, diagnostic) { + panic!("Error while reporting error: {}", e); + } + } + + fn eprint<'f: 'a>(&self, files: &'f F, config: &Config); +} + +pub fn eprint_error<'a, 'f: 'a, F, E>(files: &'f F, e: &E) +where + F: Files<'a>, + E: Eprint<'a, F>, +{ + let config = Config::default(); + e.eprint(files, &config); +} diff --git a/src/eval/error.rs b/src/eval/error.rs index 16062b9..4e5bd45 100644 --- a/src/eval/error.rs +++ b/src/eval/error.rs @@ -1,8 +1,10 @@ use chrono::NaiveDate; use codespan_reporting::diagnostic::{Diagnostic, Label}; +use codespan_reporting::files::Files; +use codespan_reporting::term::Config; +use crate::error::Eprint; use crate::files::primitives::{Span, Time}; -use crate::files::{FileSource, Files}; #[derive(Debug, thiserror::Error)] pub enum Error { @@ -76,15 +78,17 @@ pub enum Error { }, } -impl Error { +impl Error { fn fmt_date_time(date: NaiveDate, time: Option