diff --git a/Cargo.lock b/Cargo.lock index c51c076..ef02a81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -73,6 +73,12 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "chrono" version = "0.4.19" @@ -86,6 +92,28 @@ dependencies = [ "winapi", ] +[[package]] +name = "chrono-tz" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c01c1c607d25c71bbaa67c113d6c6b36c434744b4fd66691d711b5b1bc0c8b" +dependencies = [ + "chrono", + "chrono-tz-build", + "phf", +] + +[[package]] +name = "chrono-tz-build" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db058d493fb2f65f41861bfed7e3fe6335264a9f0f92710cab5bdf01fef09069" +dependencies = [ + "parse-zoneinfo", + "phf", + "phf_codegen", +] + [[package]] name = "clap" version = "2.33.3" @@ -125,6 +153,17 @@ dependencies = [ "typenum", ] +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "heck" version = "0.3.3" @@ -186,6 +225,15 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +[[package]] +name = "parse-zoneinfo" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" +dependencies = [ + "regex", +] + [[package]] name = "pest" version = "2.1.3" @@ -229,6 +277,51 @@ dependencies = [ "sha-1", ] +[[package]] +name = "phf" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9fc3db1018c4b59d7d582a739436478b6035138b6aecbce989fc91c3e98409f" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", + "uncased", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -271,6 +364,61 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core", +] + +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + [[package]] name = "sha-1" version = "0.8.2" @@ -283,6 +431,12 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "siphasher" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" + [[package]] name = "strsim" version = "0.8.0" @@ -370,6 +524,7 @@ version = "0.1.0" dependencies = [ "anyhow", "chrono", + "chrono-tz", "pest", "pest_derive", "structopt", @@ -388,6 +543,15 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +[[package]] +name = "uncased" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baeed7327e25054889b9bd4f975f32e5f4c5d434042d59ab6cd4142c0a76ed0" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-segmentation" version = "1.8.0" diff --git a/Cargo.toml b/Cargo.toml index 7a4ee3d..ebe71f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" [dependencies] anyhow = "1.0.45" chrono = "0.4.19" +chrono-tz = "0.6.0" pest = "2.1.3" pest_derive = "2.1.0" structopt = "0.3.25" diff --git a/src/files.rs b/src/files.rs new file mode 100644 index 0000000..392525a --- /dev/null +++ b/src/files.rs @@ -0,0 +1,59 @@ +use std::collections::HashMap; +use std::path::{Path, PathBuf}; +use std::{fs, io, result}; + +use chrono_tz::Tz; + +use crate::commands::File; +use crate::parse; + +#[derive(Debug)] +pub struct Files { + files: HashMap, + timezone: Option, +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("{0}")] + IoError(#[from] io::Error), + #[error("{0}")] + ParseError(#[from] parse::Error), +} + +pub type Result = result::Result; + +impl Files { + pub fn load(path: &Path) -> Result { + let mut new = Self { + files: HashMap::new(), + timezone: None, + }; + + new.load_file(path)?; + new.determine_timezone()?; + + Ok(new) + } + + fn load_file(&mut self, path: &Path) -> Result<()> { + let canon_path = path.canonicalize()?; + if self.files.contains_key(&canon_path) { + // We've already loaded this exact file. + return Ok(()); + } + + let content = fs::read_to_string(path)?; + let file = parse::parse(path, &content)?; + self.files.insert(canon_path, file); + + // TODO Also load all imported files + + Ok(()) + } + + fn determine_timezone(&mut self) -> Result<()> { + // TODO Implement once files can specify time zones + Ok(()) + } +} diff --git a/src/main.rs b/src/main.rs index b1f788c..1cec2d7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,12 @@ -use std::fs; use std::path::PathBuf; -use chrono::NaiveDate; use structopt::StructOpt; -use crate::eval::entries::DateRange; +use crate::files::Files; mod commands; mod eval; +mod files; mod format; mod parse; @@ -19,15 +18,7 @@ pub struct Opt { fn main() -> anyhow::Result<()> { let opt = Opt::from_args(); - let content = fs::read_to_string(&opt.file)?; - let file = parse::parse(&opt.file, &content)?; - let entries = eval::eval( - &file, - DateRange::new( - NaiveDate::from_ymd(2021, 1, 1), - NaiveDate::from_ymd(2021, 12, 31), - ), - )?; - println!("{:#?}", entries); + let files = Files::load(&opt.file)?; + println!("{:#?}", files); Ok(()) } diff --git a/src/parse.rs b/src/parse.rs index 9d9cae4..2dbe5df 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -2,7 +2,7 @@ use std::path::Path; use std::result; use chrono::NaiveDate; -use pest::error::{Error, ErrorVariant}; +use pest::error::ErrorVariant; use pest::iterators::Pair; use pest::prec_climber::{Assoc, Operator, PrecClimber}; use pest::{Parser, Span}; @@ -16,9 +16,10 @@ use crate::commands::{ #[grammar = "parse/todayfile.pest"] struct TodayfileParser; -type Result = result::Result>; +pub type Error = pest::error::Error; +pub type Result = result::Result; -fn error>(span: Span, message: S) -> Error { +fn error>(span: Span, message: S) -> Error { Error::new_from_span( ErrorVariant::CustomError { message: message.into(),