be able to query entries
This commit is contained in:
parent
47f4086c59
commit
a29c3c40ab
|
@ -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<()>;
|
||||
}
|
||||
|
|
|
@ -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(¤t_sheet)?, out)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")?,
|
||||
|
|
|
@ -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()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
26
src/main.rs
26
src/main.rs
|
@ -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")
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue