be able to query entries

This commit is contained in:
Abraham Toriz 2021-06-21 17:38:51 -05:00
parent 47f4086c59
commit a29c3c40ab
No known key found for this signature in database
GPG Key ID: D5B4A746DB5DD42A
8 changed files with 122 additions and 18 deletions

View File

@ -3,7 +3,9 @@ use std::io::Write;
use clap::ArgMatches;
use crate::{error, database::Database};
use crate::error;
use crate::database::Database;
use crate::config::Config;
pub mod r#in;
pub mod display;
@ -11,5 +13,5 @@ pub mod display;
pub trait Command<'a> {
type Args: TryFrom<&'a ArgMatches<'a>>;
fn handle<D: Database, W: Write>(args: Self::Args, db: &mut D, out: &mut W) -> error::Result<()>;
fn handle<D: Database, W: Write>(args: Self::Args, db: &mut D, out: &mut W, config: &Config) -> error::Result<()>;
}

View File

@ -3,18 +3,33 @@ use std::io::Write;
use clap::ArgMatches;
use crate::{error, database::Database};
use crate::error;
use crate::database::Database;
use crate::types::Time;
use crate::formatters::Formatter;
use crate::config::Config;
use super::Command;
pub struct Args {
ids: bool,
start: Option<Time>,
end: Option<Time>,
format: Formatter,
grep: Option<String>,
}
impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
type Error = error::Error;
fn try_from(matches: &'a ArgMatches) -> error::Result<Args> {
unimplemented!()
Ok(Args {
ids: matches.is_present("ids"),
start: matches.value_of("at").map(|s| s.parse()).transpose()?,
end: matches.value_of("at").map(|s| s.parse()).transpose()?,
format: matches.value_of("format").unwrap().parse()?,
grep: matches.value_of("grep").map(|s| s.into()),
})
}
}
@ -24,11 +39,13 @@ pub struct DisplayCommand {
impl<'a> Command<'a> for DisplayCommand {
type Args = Args;
fn handle<D, W>(args: Self::Args, db: &mut D, out: &mut W) -> error::Result<()>
fn handle<D, W>(args: Self::Args, db: &mut D, out: &mut W, config: &Config) -> error::Result<()>
where
D: Database,
W: Write,
{
unimplemented!()
let current_sheet = db.current_sheet()?.unwrap_or("default".into());
args.format.print_formatted(db.entries_by_sheet(&current_sheet)?, out)
}
}

View File

@ -2,13 +2,13 @@ use std::convert::TryFrom;
use std::io::Write;
use clap::ArgMatches;
use chrono::{DateTime, Utc};
use crate::database::Database;
use crate::error;
use crate::types::Time;
use crate::editor;
use crate::commands::Command;
use crate::config::Config;
pub struct Args {
at: Option<Time>,
@ -31,7 +31,7 @@ pub struct InCommand {}
impl<'a> Command<'a> for InCommand {
type Args = Args;
fn handle<D, W>(args: Args, db: &mut D, out: &mut W) -> error::Result<()>
fn handle<D, W>(args: Args, db: &mut D, out: &mut W, config: &Config) -> error::Result<()>
where
D: Database,
W: Write,
@ -67,7 +67,7 @@ mod tests {
assert!(false, "there are no entries");
InCommand::handle(args, &mut d, &mut out).unwrap();
InCommand::handle(args, &mut d, &mut out, &Default::default()).unwrap();
assert!(false, "there is one entry");
}
@ -83,7 +83,7 @@ mod tests {
assert!(false, "there are no entries");
InCommand::handle(args, &mut d, &mut out).unwrap();
InCommand::handle(args, &mut d, &mut out, &Default::default()).unwrap();
assert!(false, "there are still no entries");
}

View File

@ -128,3 +128,22 @@ impl Config {
unimplemented!()
}
}
impl Default for Config {
fn default() -> Config {
Config {
database_file: PathBuf::new(), // "/home/abraham/.timetrap.db"
round_in_seconds: 900, // 900
append_notes_delimiter: " ".into(), //" "
formatter_search_paths: Vec::new(), //- "/home/abraham/.timetrap/formatters"
default_formatter: Formatter::Text, //text
auto_sheet: "dotfiles".into(), //dotfiles
auto_sheet_search_paths: Vec::new(), // - "/home/abraham/.timetrap/auto_sheets"
default_command: None,
auto_checkout: false, // false
require_note: true, // true
note_editor: "vim".into(), // nvim
week_start: WeekDay::Monday, // Monday
}
}
}

View File

@ -1,7 +1,6 @@
use std::path::Path;
use rusqlite::{Connection, ToSql};
use chrono::{DateTime, Utc};
use crate::error;
use crate::models::{Entry, Meta};
@ -15,13 +14,22 @@ pub trait Database {
fn entry_query(&self, query: &str, params: &[&dyn ToSql]) -> error::Result<Vec<Entry>>;
fn meta_query(&self, query: &str, params: &[&dyn ToSql]) -> error::Result<Vec<Meta>>;
fn entries_by_sheet(&mut self, sheet: String) -> error::Result<Vec<Entry>> {
self.entry_query("some".into(), &[])
// Entry queries
fn entries_by_sheet(&mut self, sheet: &str) -> error::Result<Vec<Entry>> {
self.entry_query("select * from entries where sheet=?1", &[&sheet])
}
fn entry_insert(&mut self, at: Time, note: String) -> error::Result<()> {
self.execute("", &[])
}
// Meta queries
fn current_sheet(&self) -> error::Result<Option<String>> {
let results = self.meta_query("select * from meta where key=?1", &[&"current_sheet"])?;
Ok(results.into_iter().next().map(|m| m.value))
}
}
pub struct SqliteDatabase {
@ -52,7 +60,7 @@ impl Database for SqliteDatabase {
fn entry_query(&self, query: &str, params: &[&dyn ToSql]) -> error::Result<Vec<Entry>> {
let mut stmt = self.connection.prepare(query)?;
let results = stmt.query_map([], |row| {
let results = stmt.query_map(params, |row| {
let x = Ok(Entry {
id: row.get("id")?,
note: row.get("note")?,
@ -69,7 +77,7 @@ impl Database for SqliteDatabase {
fn meta_query(&self, query: &str, params: &[&dyn ToSql]) -> error::Result<Vec<Meta>> {
let mut stmt = self.connection.prepare(query)?;
let results = stmt.query_map([], |row| Ok(Meta {
let results = stmt.query_map(params, |row| Ok(Meta {
id: row.get("id")?,
key: row.get("key")?,
value: row.get("value")?,

View File

@ -1,7 +1,43 @@
use std::str::FromStr;
use std::io::Write;
use serde::{Serialize, Deserialize};
use crate::error;
use crate::models::Entry;
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Formatter {
Text,
Custom(String),
}
impl Formatter {
pub fn print_formatted<W: Write>(&self, entries: Vec<Entry>, out: &mut W) -> error::Result<()> {
match &self {
Formatter::Text => {
for entry in entries {
writeln!(out, "{:?}", entry);
}
}
Formatter::Custom(name) => {
}
}
Ok(())
}
}
impl FromStr for Formatter {
type Err = error::Error;
fn from_str(s: &str) -> error::Result<Formatter> {
let lower = s.to_lowercase();
Ok(match &*lower {
"text" => Formatter::Text,
custom_format => Formatter::Custom(custom_format.into()),
})
}
}

View File

@ -12,12 +12,12 @@ use tiempo::commands::{ Command, r#in::InCommand, display::DisplayCommand, };
fn error_trap(matches: ArgMatches) -> error::Result<()> {
let config = Config::read()?;
let mut conn = SqliteDatabase::from_path(config.database_file)?;
let mut conn = SqliteDatabase::from_path(&config.database_file)?;
let mut out = io::stdout();
match matches.subcommand() {
("in", Some(matches)) => InCommand::handle(matches.try_into()?, &mut conn, &mut out),
("display", Some(matches)) => DisplayCommand::handle(matches.try_into()?, &mut conn, &mut out),
("in", Some(matches)) => InCommand::handle(matches.try_into()?, &mut conn, &mut out, &config),
("display", Some(matches)) => DisplayCommand::handle(matches.try_into()?, &mut conn, &mut out, &config),
(cmd, _) => Err(error::Error::UnimplementedCommand(cmd.into())),
}
}
@ -109,6 +109,26 @@ fn main() {
.about("Display the current timesheet or a specific. Pass `all' as SHEET
to display all unarchived sheets or `full' to display archived and
unarchived sheets.")
.arg(Arg::with_name("ids")
.short("v").long("ids")
.help("Print database ids (for use with edit)"))
.arg(Arg::with_name("start")
.short("s").long("start")
.takes_value(true)
.value_name("DATE")
.help("Include entries that start on this date or later"))
.arg(Arg::with_name("end")
.short("e").long("end")
.takes_value(true).value_name("DATE")
.help("Include entries that start on this date or earlier"))
.arg(Arg::with_name("format")
.short("f").long("format")
.takes_value(true).value_name("FORMAT").default_value("text")
.help("The output format. Valid built-in formats are ical, csv, json, ids, factor, and text (default). Documentation on defining custom formats can be found in the README included in this distribution."))
.arg(Arg::with_name("grep")
.short("g").long("grep")
.takes_value(true).value_name("REGEXP")
.help("Include entries where the note matches this regexp."))
)
.subcommand(SubCommand::with_name("in")

View File

@ -1,5 +1,6 @@
use chrono::{DateTime, Utc};
#[derive(Debug)]
pub struct Entry {
pub id: u64,
pub note: String,
@ -8,6 +9,7 @@ pub struct Entry {
pub sheet: String,
}
#[derive(Debug)]
pub struct Meta {
pub id: u64,
pub key: String,