Format files properly again
I forgot to include the includes and time zone commands
This commit is contained in:
parent
d7df47eba4
commit
2c7aa78d08
5 changed files with 72 additions and 23 deletions
51
src/files.rs
51
src/files.rs
|
|
@ -11,9 +11,21 @@ pub mod commands;
|
|||
mod format;
|
||||
mod parse;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct LoadedFile {
|
||||
file: File,
|
||||
dirty: bool,
|
||||
}
|
||||
|
||||
impl LoadedFile {
|
||||
pub fn new(file: File) -> Self {
|
||||
Self { file, dirty: false }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Files {
|
||||
files: HashMap<PathBuf, File>,
|
||||
files: HashMap<PathBuf, LoadedFile>,
|
||||
timezone: Tz,
|
||||
}
|
||||
|
||||
|
|
@ -42,7 +54,7 @@ impl Files {
|
|||
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()?;
|
||||
if files.contains_key(&canon_path) {
|
||||
// We've already loaded this exact file.
|
||||
|
|
@ -53,31 +65,34 @@ impl Files {
|
|||
let file = parse::parse(path, &content)?;
|
||||
let includes = file.includes.clone();
|
||||
|
||||
files.insert(canon_path, file);
|
||||
files.insert(canon_path, LoadedFile::new(file));
|
||||
|
||||
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(())
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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 found_tz != file_tz {
|
||||
return Err(Error::TzConflict {
|
||||
file1: found_name.clone(),
|
||||
tz1: found_tz.clone(),
|
||||
file2: file.name.clone(),
|
||||
file2: file.file.name.clone(),
|
||||
tz2: file_tz.clone(),
|
||||
});
|
||||
}
|
||||
} 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> {
|
||||
Utc::now().with_timezone(&&self.timezone)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -329,7 +329,7 @@ pub enum Command {
|
|||
#[derive(Debug)]
|
||||
pub struct File {
|
||||
pub name: PathBuf,
|
||||
pub includes: Vec<PathBuf>,
|
||||
pub includes: Vec<String>,
|
||||
pub timezone: Option<String>,
|
||||
pub commands: Vec<Command>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -273,14 +273,28 @@ impl fmt::Display for Command {
|
|||
|
||||
impl fmt::Display for File {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut commands = self.commands.iter();
|
||||
if let Some(command) = commands.next() {
|
||||
write!(f, "{}", command)?;
|
||||
for command in commands {
|
||||
writeln!(f)?;
|
||||
write!(f, "{}", command)?;
|
||||
}
|
||||
let mut empty = true;
|
||||
for include in &self.includes {
|
||||
writeln!(f, "INCLUDE {}", include)?;
|
||||
empty = false;
|
||||
}
|
||||
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -706,12 +706,7 @@ fn parse_command(p: Pair<Rule>, file: &mut File) -> Result<()> {
|
|||
|
||||
let p = p.into_inner().next().unwrap();
|
||||
match p.as_rule() {
|
||||
Rule::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 parent = file.name.parent().unwrap();
|
||||
file.includes.push(parent.join(parse_include(p)));
|
||||
}
|
||||
Rule::include => file.includes.push(parse_include(p)),
|
||||
Rule::timezone => match file.timezone {
|
||||
None => file.timezone = Some(parse_timezone(p)),
|
||||
Some(_) => fail(p.as_span(), "cannot set timezone multiple times")?,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,12 @@ pub struct Opt {
|
|||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
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"));
|
||||
|
||||
files.mark_all_dirty();
|
||||
files.save()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue