Specify default capture file

This commit is contained in:
Joscha 2022-01-14 17:53:07 +01:00
parent 039b7b73ee
commit 0b4f614af6
7 changed files with 70 additions and 6 deletions

View file

@ -5,7 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## Unreleased ## Unreleased
### Added ### Added
- `LOG` command - `LOG` and `CAPTURE` commands
- `REMIND` and `CANCEL` statements - `REMIND` and `CANCEL` statements
- `MOVE` entries to a different time - `MOVE` entries to a different time
- `today log` CLI command - `today log` CLI command

View file

@ -85,6 +85,7 @@ pub struct Files {
/// Codespan-reporting file database. /// Codespan-reporting file database.
cs_files: SimpleFiles<String, String>, cs_files: SimpleFiles<String, String>,
timezone: Option<Tz>, timezone: Option<Tz>,
capture: Option<usize>,
logs: HashMap<NaiveDate, Source>, logs: HashMap<NaiveDate, Source>,
} }
@ -132,6 +133,7 @@ impl Files {
files: vec![], files: vec![],
cs_files: SimpleFiles::new(), cs_files: SimpleFiles::new(),
timezone: None, timezone: None,
capture: None,
logs: HashMap::new(), logs: HashMap::new(),
} }
} }
@ -155,6 +157,7 @@ impl Files {
self.load_file(&mut loaded, path)?; self.load_file(&mut loaded, path)?;
self.determine_timezone()?; self.determine_timezone()?;
self.determine_capture()?;
self.collect_logs()?; self.collect_logs()?;
Ok(()) Ok(())
@ -257,6 +260,32 @@ impl Files {
Ok(()) Ok(())
} }
fn determine_capture(&mut self) -> Result<()> {
assert_eq!(self.capture, None);
let mut found: Option<Source> = None;
for command in self.commands() {
if let Command::Capture = &command.value.value {
if let Some(found) = &found {
let found_cmd = self.command(*found);
return Err(Error::MultipleCapture {
file1: found.file(),
span1: found_cmd.value.span,
file2: command.source.file(),
span2: command.value.span,
});
} else {
found = Some(command.source);
}
}
}
self.capture = found.map(|s| s.file);
Ok(())
}
fn collect_logs(&mut self) -> Result<()> { fn collect_logs(&mut self) -> Result<()> {
for command in Self::commands_of_files(&self.files) { for command in Self::commands_of_files(&self.files) {
if let Command::Log(log) = &command.value.value { if let Command::Log(log) = &command.value.value {
@ -369,6 +398,10 @@ impl Files {
.max_by_key(|(d, _)| *d) .max_by_key(|(d, _)| *d)
} }
pub fn capture(&self) -> Option<FileSource> {
self.capture.map(FileSource)
}
pub fn now(&self) -> DateTime<&Tz> { pub fn now(&self) -> DateTime<&Tz> {
if let Some(tz) = &self.timezone { if let Some(tz) = &self.timezone {
Utc::now().with_timezone(&tz) Utc::now().with_timezone(&tz)

View file

@ -271,6 +271,7 @@ pub enum Statement {
Remind(Option<Spanned<Delta>>), Remind(Option<Spanned<Delta>>),
} }
#[allow(clippy::enum_variant_names)]
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum DoneDate { pub enum DoneDate {
Date { Date {
@ -374,6 +375,7 @@ pub struct Log {
pub enum Command { pub enum Command {
Include(Spanned<String>), Include(Spanned<String>),
Timezone(Spanned<String>), Timezone(Spanned<String>),
Capture, // TODO Set capture file by template?
Task(Task), Task(Task),
Note(Note), Note(Note),
Log(Log), Log(Log),

View file

@ -114,6 +114,13 @@ pub enum Error {
span2: Span, span2: Span,
tz2: String, tz2: String,
}, },
#[error("Multiple capture commands")]
MultipleCapture {
file1: FileSource,
span1: Span,
file2: FileSource,
span2: Span,
},
#[error("Duplicate logs for {date}")] #[error("Duplicate logs for {date}")]
LogConflict { LogConflict {
file1: FileSource, file1: FileSource,
@ -179,6 +186,23 @@ impl<'a> Eprint<'a, Files> for Error {
]); ]);
Self::eprint_diagnostic(files, config, &diagnostic); Self::eprint_diagnostic(files, config, &diagnostic);
} }
Error::MultipleCapture {
file1,
span1,
file2,
span2,
} => {
let diagnostic = Diagnostic::error()
.with_message("Multiple capture commands")
.with_labels(vec![
Label::primary(*file1, span1),
Label::primary(*file2, span2),
])
.with_notes(vec![
"There must be at most one CAPTURE command.".to_string()
]);
Self::eprint_diagnostic(files, config, &diagnostic);
}
Error::LogConflict { Error::LogConflict {
file1, file1,
span1, span1,

View file

@ -302,6 +302,7 @@ impl fmt::Display for Command {
match self { match self {
Command::Include(name) => writeln!(f, "INCLUDE {}", name), Command::Include(name) => writeln!(f, "INCLUDE {}", name),
Command::Timezone(name) => writeln!(f, "TIMEZONE {}", name), Command::Timezone(name) => writeln!(f, "TIMEZONE {}", name),
Command::Capture => writeln!(f, "CAPTURE"),
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), Command::Log(log) => write!(f, "{}", log),
@ -322,8 +323,9 @@ impl File {
// Order of commands in a file: // Order of commands in a file:
// 1. Imports, sorted alphabetically // 1. Imports, sorted alphabetically
// 2. Time zone(s) // 2. Time zone(s)
// 3. Log entries, sorted by date (ascending) // 3. Captures
// 4. Tasks and notes, in original order // 4. Log entries, sorted by date (ascending)
// 5. Tasks and notes, in original order
// There should always be at most one time zone, so we don't care about // There should always be at most one time zone, so we don't care about
// their order. // their order.
@ -347,8 +349,9 @@ impl File {
commands.sort_by_key(|c| match c { commands.sort_by_key(|c| match c {
Command::Include(_) => 0, Command::Include(_) => 0,
Command::Timezone(_) => 1, Command::Timezone(_) => 1,
Command::Log(_) => 2, Command::Capture => 2,
Command::Task(_) | Command::Note(_) => 3, Command::Log(_) => 3,
Command::Task(_) | Command::Note(_) => 4,
}); });
} }

View file

@ -5,6 +5,7 @@ rest_any = { (!eol ~ ANY)* }
include = { "INCLUDE" ~ WHITESPACE ~ rest_some ~ eol } include = { "INCLUDE" ~ WHITESPACE ~ rest_some ~ eol }
timezone = { "TIMEZONE" ~ WHITESPACE ~ rest_some ~ eol } timezone = { "TIMEZONE" ~ WHITESPACE ~ rest_some ~ eol }
capture = { "CAPTURE" ~ eol }
number = @{ ASCII_DIGIT{1,9} } // Fits into an i32 number = @{ ASCII_DIGIT{1,9} } // Fits into an i32
@ -144,7 +145,7 @@ log_head = !{ "LOG" ~ datum ~ eol }
log = { log_head ~ description } log = { log_head ~ description }
empty_line = _{ WHITESPACE* ~ NEWLINE } empty_line = _{ WHITESPACE* ~ NEWLINE }
command = { include | timezone | task | note | log } command = { include | timezone | capture | task | note | log }
file = ${ SOI ~ (empty_line* ~ command)* ~ empty_line* ~ WHITESPACE* ~ EOI } file = ${ SOI ~ (empty_line* ~ command)* ~ empty_line* ~ WHITESPACE* ~ EOI }

View file

@ -826,6 +826,7 @@ fn parse_command(p: Pair<'_, Rule>) -> Result<Spanned<Command>> {
let command = match p.as_rule() { let command = match p.as_rule() {
Rule::include => Command::Include(parse_include(p)), Rule::include => Command::Include(parse_include(p)),
Rule::timezone => Command::Timezone(parse_timezone(p)), Rule::timezone => Command::Timezone(parse_timezone(p)),
Rule::capture => Command::Capture,
Rule::task => Command::Task(parse_task(p)?), Rule::task => Command::Task(parse_task(p)?),
Rule::note => Command::Note(parse_note(p)?), Rule::note => Command::Note(parse_note(p)?),
Rule::log => Command::Log(parse_log(p)?), Rule::log => Command::Log(parse_log(p)?),