Represent commands in file uniformly

This commit is contained in:
Joscha 2022-01-02 00:42:06 +01:00
parent 004aa87153
commit d27812b836
3 changed files with 25 additions and 73 deletions

View file

@ -345,38 +345,15 @@ pub struct Log {
#[derive(Debug)] #[derive(Debug)]
pub enum Command { pub enum Command {
Include(String),
Timezone(String),
Task(Task), Task(Task),
Note(Note), Note(Note),
} Log(Log),
impl Command {
pub fn title(&self) -> &str {
match self {
Self::Task(task) => &task.title,
Self::Note(note) => &note.title,
}
}
pub fn desc(&self) -> &[String] {
match self {
Self::Task(task) => &task.desc,
Self::Note(note) => &note.desc,
}
}
pub fn statements(&self) -> &[Statement] {
match self {
Self::Task(task) => &task.statements,
Self::Note(note) => &note.statements,
}
}
} }
#[derive(Debug)] #[derive(Debug)]
pub struct File { pub struct File {
pub contents: String, pub contents: String,
pub includes: Vec<String>,
pub timezone: Option<String>,
pub logs: Vec<Log>,
pub commands: Vec<Command>, pub commands: Vec<Command>,
} }

View file

@ -300,8 +300,11 @@ impl fmt::Display for Note {
impl fmt::Display for Command { impl fmt::Display for Command {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Command::Include(name) => writeln!(f, "INCLUDE {}", name),
Command::Timezone(name) => writeln!(f, "TIMEZONE {}", name),
Command::Task(task) => write!(f, "{}", task), Command::Task(task) => write!(f, "{}", task),
Command::Note(note) => write!(f, "{}", note), Command::Note(note) => write!(f, "{}", note),
Command::Log(log) => write!(f, "{}", log),
} }
} }
} }
@ -316,33 +319,17 @@ impl fmt::Display for Log {
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 empty = true; for i in 0..self.commands.len() {
let curr = &self.commands[i];
let next = self.commands.get(i + 1);
// TODO Sort includes alphabetically write!(f, "{}", curr)?;
for include in &self.includes {
writeln!(f, "INCLUDE {}", include)?;
empty = false;
}
if let Some(tz) = &self.timezone { match (curr, next) {
if !empty { (Command::Include(_), Some(Command::Include(_))) => {}
writeln!(f)?; (_, None) => {}
_ => writeln!(f)?,
} }
writeln!(f, "TIMEZONE {}", tz)?;
empty = false;
}
// TODO Sort logs from old to new
for log in &self.logs {
writeln!(f, "{}", log)?;
}
for command in &self.commands {
if !empty {
writeln!(f)?;
}
write!(f, "{}", command)?;
empty = false;
} }
Ok(()) Ok(())

View file

@ -812,46 +812,34 @@ fn parse_log(p: Pair<'_, Rule>) -> Result<Log> {
Ok(Log { date, desc }) Ok(Log { date, desc })
} }
fn parse_command(p: Pair<'_, Rule>, file: &mut File) -> Result<()> { fn parse_command(p: Pair<'_, Rule>) -> Result<Command> {
assert_eq!(p.as_rule(), Rule::command); assert_eq!(p.as_rule(), Rule::command);
let p = p.into_inner().next().unwrap(); let p = p.into_inner().next().unwrap();
match p.as_rule() { Ok(match p.as_rule() {
Rule::include => file.includes.push(parse_include(p)), Rule::include => Command::Include(parse_include(p)),
Rule::timezone => match file.timezone { Rule::timezone => Command::Timezone(parse_timezone(p)),
None => file.timezone = Some(parse_timezone(p)), Rule::task => Command::Task(parse_task(p)?),
Some(_) => fail(p.as_span(), "cannot set timezone multiple times")?, Rule::note => Command::Note(parse_note(p)?),
}, Rule::log => Command::Log(parse_log(p)?),
Rule::task => file.commands.push(Command::Task(parse_task(p)?)),
Rule::note => file.commands.push(Command::Note(parse_note(p)?)),
Rule::log => file.logs.push(parse_log(p)?),
_ => unreachable!(), _ => unreachable!(),
} })
Ok(())
} }
pub fn parse_file(p: Pair<'_, Rule>, contents: String) -> Result<File> { pub fn parse_file(p: Pair<'_, Rule>, contents: String) -> Result<File> {
assert_eq!(p.as_rule(), Rule::file); assert_eq!(p.as_rule(), Rule::file);
let mut file = File { let mut commands = vec![];
contents,
includes: vec![],
timezone: None,
logs: vec![],
commands: vec![],
};
for p in p.into_inner() { for p in p.into_inner() {
// For some reason, the EOI in `file` always gets captured // For some reason, the EOI in `file` always gets captured
if p.as_rule() == Rule::EOI { if p.as_rule() == Rule::EOI {
break; break;
} }
parse_command(p, &mut file)?; commands.push(parse_command(p)?);
} }
Ok(file) Ok(File { contents, commands })
} }
pub fn parse(path: &Path, input: &str) -> Result<File> { pub fn parse(path: &Path, input: &str) -> Result<File> {