Specify default capture file
This commit is contained in:
parent
039b7b73ee
commit
0b4f614af6
7 changed files with 70 additions and 6 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
33
src/files.rs
33
src/files.rs
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)?),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue