Represent commands in file uniformly
This commit is contained in:
parent
004aa87153
commit
d27812b836
3 changed files with 25 additions and 73 deletions
|
|
@ -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) => ¬e.title,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn desc(&self) -> &[String] {
|
|
||||||
match self {
|
|
||||||
Self::Task(task) => &task.desc,
|
|
||||||
Self::Note(note) => ¬e.desc,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn statements(&self) -> &[Statement] {
|
|
||||||
match self {
|
|
||||||
Self::Task(task) => &task.statements,
|
|
||||||
Self::Note(note) => ¬e.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>,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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(())
|
||||||
|
|
|
||||||
|
|
@ -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> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue