Format files properly again

I forgot to include the includes and time zone commands
This commit is contained in:
Joscha 2021-11-22 10:20:17 +00:00
parent d7df47eba4
commit 2c7aa78d08
5 changed files with 72 additions and 23 deletions

View file

@ -11,9 +11,21 @@ pub mod commands;
mod format; mod format;
mod parse; mod parse;
#[derive(Debug)]
struct LoadedFile {
file: File,
dirty: bool,
}
impl LoadedFile {
pub fn new(file: File) -> Self {
Self { file, dirty: false }
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct Files { pub struct Files {
files: HashMap<PathBuf, File>, files: HashMap<PathBuf, LoadedFile>,
timezone: Tz, timezone: Tz,
} }
@ -42,7 +54,7 @@ impl Files {
Ok(Self { files, timezone }) Ok(Self { files, timezone })
} }
fn load_file(files: &mut HashMap<PathBuf, File>, path: &Path) -> Result<()> { fn load_file(files: &mut HashMap<PathBuf, LoadedFile>, path: &Path) -> Result<()> {
let canon_path = path.canonicalize()?; let canon_path = path.canonicalize()?;
if files.contains_key(&canon_path) { if files.contains_key(&canon_path) {
// We've already loaded this exact file. // We've already loaded this exact file.
@ -53,31 +65,34 @@ impl Files {
let file = parse::parse(path, &content)?; let file = parse::parse(path, &content)?;
let includes = file.includes.clone(); let includes = file.includes.clone();
files.insert(canon_path, file); files.insert(canon_path, LoadedFile::new(file));
for include in includes { for include in includes {
Self::load_file(files, &include)?; // Since we've successfully opened the file, its name can't be the
// root directory or empty string and must thus have a parent.
let include_path = path.parent().unwrap().join(include);
Self::load_file(files, &include_path)?;
} }
Ok(()) Ok(())
} }
fn determine_timezone(files: &HashMap<PathBuf, File>) -> Result<Tz> { fn determine_timezone(files: &HashMap<PathBuf, LoadedFile>) -> Result<Tz> {
let mut found: Option<(PathBuf, String)> = None; let mut found: Option<(PathBuf, String)> = None;
for file in files.values() { for file in files.values() {
if let Some(file_tz) = &file.timezone { if let Some(file_tz) = &file.file.timezone {
if let Some((found_name, found_tz)) = &found { if let Some((found_name, found_tz)) = &found {
if found_tz != file_tz { if found_tz != file_tz {
return Err(Error::TzConflict { return Err(Error::TzConflict {
file1: found_name.clone(), file1: found_name.clone(),
tz1: found_tz.clone(), tz1: found_tz.clone(),
file2: file.name.clone(), file2: file.file.name.clone(),
tz2: file_tz.clone(), tz2: file_tz.clone(),
}); });
} }
} else { } else {
found = Some((file.name.clone(), file_tz.clone())); found = Some((file.file.name.clone(), file_tz.clone()));
} }
} }
} }
@ -89,6 +104,26 @@ impl Files {
}) })
} }
pub fn save(&self) -> Result<()> {
for (path, file) in &self.files {
if file.dirty {
Self::save_file(path, &file.file)?;
}
}
Ok(())
}
fn save_file(path: &Path, file: &File) -> Result<()> {
fs::write(path, &format!("{}", file))?;
Ok(())
}
pub fn mark_all_dirty(&mut self) {
for (_, file) in self.files.iter_mut() {
file.dirty = true;
}
}
pub fn now(&self) -> DateTime<&Tz> { pub fn now(&self) -> DateTime<&Tz> {
Utc::now().with_timezone(&&self.timezone) Utc::now().with_timezone(&&self.timezone)
} }

View file

@ -329,7 +329,7 @@ pub enum Command {
#[derive(Debug)] #[derive(Debug)]
pub struct File { pub struct File {
pub name: PathBuf, pub name: PathBuf,
pub includes: Vec<PathBuf>, pub includes: Vec<String>,
pub timezone: Option<String>, pub timezone: Option<String>,
pub commands: Vec<Command>, pub commands: Vec<Command>,
} }

View file

@ -273,14 +273,28 @@ impl fmt::Display for Command {
impl fmt::Display for File { impl fmt::Display for File {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut commands = self.commands.iter(); let mut empty = true;
if let Some(command) = commands.next() { for include in &self.includes {
write!(f, "{}", command)?; writeln!(f, "INCLUDE {}", include)?;
for command in commands { empty = false;
writeln!(f)?;
write!(f, "{}", command)?;
}
} }
if let Some(tz) = &self.timezone {
if !empty {
writeln!(f)?;
}
writeln!(f, "TIMEZONE {}", tz)?;
empty = false;
}
for command in &self.commands {
if !empty {
writeln!(f)?;
}
write!(f, "{}", command)?;
empty = false;
}
Ok(()) Ok(())
} }
} }

View file

@ -706,12 +706,7 @@ fn parse_command(p: Pair<Rule>, file: &mut File) -> Result<()> {
let p = p.into_inner().next().unwrap(); let p = p.into_inner().next().unwrap();
match p.as_rule() { match p.as_rule() {
Rule::include => { Rule::include => file.includes.push(parse_include(p)),
// Since we've successfully opened the file, its name can't be the
// root directory or empty string and must thus have a parent.
let parent = file.name.parent().unwrap();
file.includes.push(parent.join(parse_include(p)));
}
Rule::timezone => match file.timezone { Rule::timezone => match file.timezone {
None => file.timezone = Some(parse_timezone(p)), None => file.timezone = Some(parse_timezone(p)),
Some(_) => fail(p.as_span(), "cannot set timezone multiple times")?, Some(_) => fail(p.as_span(), "cannot set timezone multiple times")?,

View file

@ -15,7 +15,12 @@ pub struct Opt {
fn main() -> anyhow::Result<()> { fn main() -> anyhow::Result<()> {
let opt = Opt::from_args(); let opt = Opt::from_args();
let files = Files::load(&opt.file)?;
let mut files = Files::load(&opt.file)?;
println!("{}", files.now().format("%F %T %Z")); println!("{}", files.now().format("%F %T %Z"));
files.mark_all_dirty();
files.save()?;
Ok(()) Ok(())
} }