Adapt cli code to changes

This commit is contained in:
Joscha 2022-01-06 18:04:34 +01:00
parent 5e47dddd4c
commit 3f5e06b113
10 changed files with 101 additions and 90 deletions

View file

@ -7,20 +7,19 @@ use codespan_reporting::files::SimpleFile;
use directories::ProjectDirs; use directories::ProjectDirs;
use structopt::StructOpt; use structopt::StructOpt;
use crate::error; use crate::eval::{DateRange, Entry, EntryMode};
// use crate::eval::{DateRange, Entry, EntryMode, SourceInfo};
use crate::files::arguments::Range; use crate::files::arguments::Range;
use crate::files::{self, Files}; use crate::files::{self, FileSource, Files};
// use self::error::Result; use self::error::Error;
// use self::layout::line::LineLayout; use self::layout::line::LineLayout;
// mod cancel; mod cancel;
// mod done; mod done;
// mod error; mod error;
// mod layout; mod layout;
// mod print; mod print;
// mod show; mod show;
#[derive(Debug, StructOpt)] #[derive(Debug, StructOpt)]
pub struct Opt { pub struct Opt {
@ -83,9 +82,7 @@ fn find_now(opt: &Opt, files: &Files) -> NaiveDateTime {
} }
} }
/* fn find_entries(files: &Files, range: DateRange) -> Result<Vec<Entry>, Error<FileSource>> {
fn find_entries(files: &Files, range: DateRange) -> Result<Vec<Entry>> {
Ok(files.eval(EntryMode::Relevant, range)?) Ok(files.eval(EntryMode::Relevant, range)?)
} }
@ -98,7 +95,12 @@ fn find_layout(
layout::layout(files, entries, range, now) layout::layout(files, entries, range, now)
} }
fn run_command(opt: &Opt, files: &mut Files, range: DateRange, now: NaiveDateTime) -> Result<()> { fn run_command(
opt: &Opt,
files: &mut Files,
range: DateRange,
now: NaiveDateTime,
) -> Result<(), Error<FileSource>> {
match &opt.command { match &opt.command {
None => { None => {
let entries = find_entries(files, range)?; let entries = find_entries(files, range)?;
@ -131,14 +133,12 @@ fn run_command(opt: &Opt, files: &mut Files, range: DateRange, now: NaiveDateTim
Ok(()) Ok(())
} }
*/
pub fn run() { pub fn run() {
let opt = Opt::from_args(); let opt = Opt::from_args();
let mut files = Files::new(); let mut files = Files::new();
if let Err(e) = load_files(&opt, &mut files) { if let Err(e) = load_files(&opt, &mut files) {
error::eprint_error(&files, &e); crate::error::eprint_error(&files, &e);
process::exit(1); process::exit(1);
} }
@ -151,7 +151,7 @@ pub fn run() {
Err(e) => { Err(e) => {
eprintln!("Failed to evaluate --range:"); eprintln!("Failed to evaluate --range:");
let file = SimpleFile::new("--range", &opt.range); let file = SimpleFile::new("--range", &opt.range);
error::eprint_error(&file, &e); crate::error::eprint_error(&file, &e);
process::exit(1) process::exit(1)
} }
}, },
@ -161,17 +161,13 @@ pub fn run() {
} }
}; };
/*
if let Err(e) = run_command(&opt, &mut files, range, now) { if let Err(e) = run_command(&opt, &mut files, range, now) {
e.print(&files.sources()); crate::error::eprint_error(&files, &e);
process::exit(1); process::exit(1);
} }
*/
if let Err(e) = files.save() { if let Err(e) = files.save() {
error::eprint_error(&files, &e); crate::error::eprint_error(&files, &e);
process::exit(1); process::exit(1);
} }
} }

View file

@ -6,16 +6,16 @@ use crate::eval::Entry;
use crate::files::commands::{Done, DoneKind}; use crate::files::commands::{Done, DoneKind};
use crate::files::Files; use crate::files::Files;
use super::error::{Error, Result}; use super::error::Error;
use super::layout::line::LineLayout; use super::layout::line::LineLayout;
pub fn cancel( pub fn cancel<S>(
files: &mut Files, files: &mut Files,
entries: &[Entry], entries: &[Entry],
layout: &LineLayout, layout: &LineLayout,
numbers: &[usize], numbers: &[usize],
now: NaiveDateTime, now: NaiveDateTime,
) -> Result<()> { ) -> Result<(), Error<S>> {
let mut not_tasks = vec![]; let mut not_tasks = vec![];
for &number in numbers { for &number in numbers {
let entry = &entries[layout.look_up_number(number)?]; let entry = &entries[layout.look_up_number(number)?];

View file

@ -6,16 +6,16 @@ use crate::eval::Entry;
use crate::files::commands::{Done, DoneKind}; use crate::files::commands::{Done, DoneKind};
use crate::files::Files; use crate::files::Files;
use super::error::{Error, Result}; use super::error::Error;
use super::layout::line::LineLayout; use super::layout::line::LineLayout;
pub fn done( pub fn done<S>(
files: &mut Files, files: &mut Files,
entries: &[Entry], entries: &[Entry],
layout: &LineLayout, layout: &LineLayout,
numbers: &[usize], numbers: &[usize],
now: NaiveDateTime, now: NaiveDateTime,
) -> Result<()> { ) -> Result<(), Error<S>> {
let mut not_tasks = vec![]; let mut not_tasks = vec![];
for &number in numbers { for &number in numbers {
let entry = &entries[layout.look_up_number(number)?]; let entry = &entries[layout.look_up_number(number)?];

View file

@ -1,21 +1,25 @@
use std::result; use std::result;
use crate::eval::{self, SourceInfo}; use codespan_reporting::files::Files;
use codespan_reporting::term::Config;
use crate::error::Eprint;
use crate::eval;
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum Error { pub enum Error<S> {
#[error("{0}")] #[error("{0}")]
Eval(#[from] eval::Error), Eval(#[from] eval::Error<S>),
#[error("No entry with number {0}")] #[error("No entry with number {0}")]
NoSuchEntry(usize), NoSuchEntry(usize),
#[error("Not a task")] #[error("Not a task")]
NotATask(Vec<usize>), NotATask(Vec<usize>),
} }
impl Error { impl<'a, F: Files<'a>> Eprint<'a, F> for Error<F::FileId> {
pub fn print<'a>(&self, sources: &[SourceInfo<'a>]) { fn eprint<'f: 'a>(&self, files: &'f F, config: &Config) {
match self { match self {
Error::Eval(e) => e.print(sources), Error::Eval(e) => e.eprint(files, config),
Error::NoSuchEntry(n) => eprintln!("No entry with number {}", n), Error::NoSuchEntry(n) => eprintln!("No entry with number {}", n),
Error::NotATask(ns) => { Error::NotATask(ns) => {
if ns.is_empty() { if ns.is_empty() {
@ -30,5 +34,3 @@ impl Error {
} }
} }
} }
pub type Result<T> = result::Result<T, Error>;

View file

@ -8,7 +8,6 @@ use std::collections::HashMap;
use chrono::{NaiveDate, NaiveDateTime}; use chrono::{NaiveDate, NaiveDateTime};
use crate::eval::{DateRange, Dates, Entry, EntryKind}; use crate::eval::{DateRange, Dates, Entry, EntryKind};
use crate::files::commands::Command;
use crate::files::primitives::Time; use crate::files::primitives::Time;
use crate::files::Files; use crate::files::Files;
@ -51,15 +50,10 @@ impl DayLayout {
pub fn layout(&mut self, files: &Files, entries: &[Entry]) { pub fn layout(&mut self, files: &Files, entries: &[Entry]) {
self.insert(self.today, DayEntry::Now(self.time)); self.insert(self.today, DayEntry::Now(self.time));
let mut commands = entries let mut entries = entries.iter().enumerate().collect::<Vec<_>>();
.iter() Self::sort_entries(&mut entries);
.enumerate()
.map(|(i, e)| (i, e, files.command(e.source)))
.collect::<Vec<_>>();
Self::sort_entries(&mut commands); for (index, entry) in entries {
for (index, entry, _) in commands {
self.layout_entry(index, entry); self.layout_entry(index, entry);
} }
@ -196,7 +190,7 @@ impl DayLayout {
} }
} }
fn sort_entries(entries: &mut Vec<(usize, &Entry, &Command)>) { fn sort_entries(entries: &mut Vec<(usize, &Entry)>) {
// Entries should be sorted by these factors, in descending order of // Entries should be sorted by these factors, in descending order of
// significance: // significance:
// 1. Their start date, if any // 1. Their start date, if any
@ -205,10 +199,10 @@ impl DayLayout {
// 4. Their title // 4. Their title
// 4. // 4.
entries.sort_by_key(|(_, _, c)| c.title()); entries.sort_by_key(|(_, e)| &e.title);
// 3. // 3.
entries.sort_by_key(|(_, e, _)| match e.kind { entries.sort_by_key(|(_, e)| match e.kind {
EntryKind::Task => 0, EntryKind::Task => 0,
EntryKind::TaskDone(_) | EntryKind::TaskCanceled(_) => 1, EntryKind::TaskDone(_) | EntryKind::TaskCanceled(_) => 1,
EntryKind::Birthday(_) => 2, EntryKind::Birthday(_) => 2,
@ -216,14 +210,14 @@ impl DayLayout {
}); });
// 2. // 2.
entries.sort_by(|(_, e1, _), (_, e2, _)| { entries.sort_by(|(_, e1), (_, e2)| {
let d1 = e1.dates.map(|d| d.sorted().other_with_time()); let d1 = e1.dates.map(|d| d.sorted().other_with_time());
let d2 = e2.dates.map(|d| d.sorted().other_with_time()); let d2 = e2.dates.map(|d| d.sorted().other_with_time());
d2.cmp(&d1) // Inverse comparison d2.cmp(&d1) // Inverse comparison
}); });
// 1. // 1.
entries.sort_by_key(|(_, e, _)| e.dates.map(|d| d.sorted().root_with_time())); entries.sort_by_key(|(_, e)| e.dates.map(|d| d.sorted().root_with_time()));
} }
fn sort_day(day: &mut Vec<DayEntry>) { fn sort_day(day: &mut Vec<DayEntry>) {

View file

@ -11,7 +11,7 @@ use crate::eval::{Entry, EntryKind};
use crate::files::primitives::Time; use crate::files::primitives::Time;
use crate::files::Files; use crate::files::Files;
use super::super::error::{Error, Result}; use super::super::error::Error;
use super::day::{DayEntry, DayLayout}; use super::day::{DayEntry, DayLayout};
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -145,7 +145,7 @@ impl LineLayout {
&self.lines &self.lines
} }
pub fn look_up_number(&self, number: usize) -> Result<usize> { pub fn look_up_number<S>(&self, number: usize) -> Result<usize, Error<S>> {
self.numbers self.numbers
.iter() .iter()
.filter(|(_, n)| **n == number) .filter(|(_, n)| **n == number)
@ -253,10 +253,10 @@ impl LineLayout {
} }
fn entry_title(files: &Files, entry: &Entry) -> String { fn entry_title(files: &Files, entry: &Entry) -> String {
let command = files.command(entry.source); let command = files.command(entry.source).command;
match entry.kind { match entry.kind {
EntryKind::Birthday(Some(age)) => format!("{} ({})", command.title(), age), EntryKind::Birthday(Some(age)) => format!("{} ({})", entry.title, age),
_ => command.title().to_string(), _ => entry.title.clone(),
} }
} }

View file

@ -1,32 +1,18 @@
use crate::eval::{Entry, EntryKind}; use crate::eval::{Entry, EntryKind};
use crate::files::Files; use crate::files::Files;
use super::error::Result; use super::error::Error;
use super::layout::line::LineLayout; use super::layout::line::LineLayout;
fn show_entry(files: &Files, entry: &Entry) { fn show_entry(files: &Files, entry: &Entry) {
let command = files.command(entry.source); let command = files.command(entry.source);
match entry.kind { let kind = match entry.kind {
EntryKind::Task => println!("TASK {}", command.title()), EntryKind::Task | EntryKind::TaskDone(_) | EntryKind::TaskCanceled(_) => "TASK",
EntryKind::TaskDone(when) => { EntryKind::Note => "NOTE",
println!("DONE {}", command.title()); EntryKind::Birthday(_) => "BIRTHDAY",
println!("DONE AT {}", when); };
} println!("{} {}", kind, entry.title);
EntryKind::TaskCanceled(when) => {
println!("CANCELED {}", command.title());
println!("CANCELED AT {}", when);
}
EntryKind::Note => println!("NOTE {}", command.title()),
EntryKind::Birthday(Some(age)) => {
println!("BIRTHDAY {}", command.title());
println!("AGE {}", age);
}
EntryKind::Birthday(None) => {
println!("BIRTHDAY {}", command.title());
println!("AGE UNKNOWN");
}
}
if let Some(dates) = entry.dates { if let Some(dates) = entry.dates {
println!("DATE {}", dates.sorted()); println!("DATE {}", dates.sorted());
@ -34,17 +20,25 @@ fn show_entry(files: &Files, entry: &Entry) {
println!("NO DATE"); println!("NO DATE");
} }
for line in command.desc() { match entry.kind {
println!("# {}", line); EntryKind::TaskDone(when) => println!("DONE {}", when),
EntryKind::TaskCanceled(when) => println!("CANCELED {}", when),
EntryKind::Birthday(Some(age)) => println!("AGE {}", age),
_ => {}
}
println!("FROM COMMAND");
for line in format!("{}", command.command).lines() {
println!("| {}", line);
} }
} }
pub fn show( pub fn show<S>(
files: &Files, files: &Files,
entries: &[Entry], entries: &[Entry],
layout: &LineLayout, layout: &LineLayout,
numbers: &[usize], numbers: &[usize],
) -> Result<()> { ) -> Result<(), Error<S>> {
if numbers.is_empty() { if numbers.is_empty() {
// Nothing to do // Nothing to do
return Ok(()); return Ok(());
@ -53,7 +47,7 @@ pub fn show(
let indices = numbers let indices = numbers
.iter() .iter()
.map(|n| layout.look_up_number(*n)) .map(|n| layout.look_up_number(*n))
.collect::<Result<Vec<usize>>>()?; .collect::<Result<Vec<usize>, _>>()?;
show_entry(files, &entries[indices[0]]); show_entry(files, &entries[indices[0]]);
for &index in indices.iter().skip(1) { for &index in indices.iter().skip(1) {

View file

@ -45,6 +45,20 @@ impl<'a> EvalCommand<'a> {
} }
} }
fn title(&self) -> String {
match self {
Self::Task(task) => task.title.clone(),
Self::Note(note) => note.title.clone(),
}
}
fn has_description(&self) -> bool {
match self {
Self::Task(task) => !task.desc.is_empty(),
Self::Note(note) => !note.desc.is_empty(),
}
}
/// Last root date mentioned in any `DONE`. /// Last root date mentioned in any `DONE`.
fn last_done_root(&self) -> Option<NaiveDate> { fn last_done_root(&self) -> Option<NaiveDate> {
match self { match self {
@ -172,7 +186,14 @@ impl<'a> CommandState<'a> {
None None
}; };
Ok(Entry::new(self.source, kind, dates, remind)) Ok(Entry::new(
self.source,
kind,
self.command.title(),
self.command.has_description(),
dates,
remind,
))
} }
/// Add an entry, respecting [`Self::from`] and [`Self::until`]. Does not /// Add an entry, respecting [`Self::from`] and [`Self::until`]. Does not

View file

@ -15,10 +15,12 @@ pub enum EntryKind {
} }
/// A single instance of a command. /// A single instance of a command.
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone)]
pub struct Entry { pub struct Entry {
pub source: Source, pub source: Source,
pub kind: EntryKind, pub kind: EntryKind,
pub title: String,
pub has_description: bool,
pub dates: Option<Dates>, pub dates: Option<Dates>,
/// Remind the user of an entry before it occurs. This date should always be /// Remind the user of an entry before it occurs. This date should always be
/// before the entry's start date, or `None` if there is no start date. /// before the entry's start date, or `None` if there is no start date.
@ -29,6 +31,8 @@ impl Entry {
pub fn new( pub fn new(
source: Source, source: Source,
kind: EntryKind, kind: EntryKind,
title: String,
has_description: bool,
dates: Option<Dates>, dates: Option<Dates>,
remind: Option<NaiveDate>, remind: Option<NaiveDate>,
) -> Self { ) -> Self {
@ -43,6 +47,8 @@ impl Entry {
Self { Self {
source, source,
kind, kind,
title,
has_description,
dates, dates,
remind, remind,
} }

View file

@ -7,7 +7,7 @@ use chrono::{DateTime, NaiveDate, Utc};
use codespan_reporting::files::SimpleFiles; use codespan_reporting::files::SimpleFiles;
use tzfile::Tz; use tzfile::Tz;
use self::commands::{Command, File}; use self::commands::{Command, Done, File};
pub use self::error::{Error, Result}; pub use self::error::{Error, Result};
use self::primitives::Spanned; use self::primitives::Spanned;
@ -337,7 +337,6 @@ impl Files {
} }
} }
/*
/// Add a [`Done`] statement to the task identified by `source`. /// Add a [`Done`] statement to the task identified by `source`.
/// ///
/// Returns whether the addition was successful. It can fail if the entry /// Returns whether the addition was successful. It can fail if the entry
@ -347,12 +346,11 @@ impl Files {
let file = &mut self.files[source.file]; let file = &mut self.files[source.file];
match &mut file.file.commands[source.command] { match &mut file.file.commands[source.command] {
Command::Task(t) => t.done.push(done), Command::Task(t) => t.done.push(done),
Command::Note(_) => return false, _ => return false,
} }
file.dirty = true; file.dirty = true;
true true
} }
*/
/* Errors */ /* Errors */