first commit

This commit is contained in:
əlemi 2022-03-13 20:13:13 +01:00
parent 7fde73888f
commit 1aee78643c
No known key found for this signature in database
GPG key ID: BBCBFE5D7244634E
2 changed files with 140 additions and 0 deletions

11
Cargo.toml Normal file
View file

@ -0,0 +1,11 @@
[package]
name = "memo-cli"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
argparse = "0.2.2"
chrono = "0.4.19"
rusqlite = { version="0.27.0", features=["chrono"] }

129
src/main.rs Normal file
View file

@ -0,0 +1,129 @@
extern crate argparse;
use argparse::{ArgumentParser, Store, StoreTrue};
use chrono::{DateTime, Duration, Utc};
use rusqlite::{params, Connection, Error};
struct Memo {
id: u32,
body: String,
due: DateTime<Utc>,
}
fn init_db(path: &str) -> Result<Connection, Error> {
let connection = Connection::open(path)?;
connection.execute(
"CREATE TABLE IF NOT EXISTS memo (
id INTEGER PRIMARY KEY,
body TEXT NOT NULL,
due DATETIME
);",
[],
)?;
return Ok(connection);
}
fn all(conn: Connection) -> Result<Vec<Memo>, rusqlite::Error> {
let mut statement = conn.prepare("SELECT * FROM memo ORDER BY due, id")?;
let mut rows = statement.query([])?;
let mut results = Vec::new();
while let Some(row) = rows.next()? {
results.push(Memo {
id: row.get(0)?,
body: row.get(1)?,
due: row.get(2)?,
});
}
return Ok(results);
}
pub trait PrettyPrint {
fn pretty(&self) -> String;
}
impl PrettyPrint for Duration {
fn pretty(&self) -> String {
if self.num_days().abs() > 400 {
return format!("{}y {}m", self.num_days().abs() / 365, (self.num_days() % (30*12)) / 30);
} else if self.num_days().abs() >= 365 {
return format!("{}y", self.num_days().abs() / 365);
} else if self.num_days().abs() >= 90 {
return format!("{}m", self.num_days().abs() / 30); // sort of
} else if self.num_days().abs() >= 1 {
return format!("{}d", self.num_days().abs());
} else if self.num_hours().abs() > 0 {
let h = self.num_minutes().abs() / 60;
let m = self.num_minutes().abs() % 60;
return format!("{}h {}min", h, m);
} else if self.num_minutes().abs() > 0 {
return format!("{}min", self.num_minutes().abs());
} else if self.num_seconds().abs() > 0 {
return format!("{}s", self.num_seconds().abs());
}
return self.to_string();
}
}
fn main() {
let home_path = std::env!("HOME").to_string();
if home_path.len() < 1 {
panic!("Cannot work without a home folder");
}
let mut version = false;
let mut memo: String = "".to_string();
let mut db_path: String = home_path + "/.local/share/memo-cli.db";
{
// this block limits scope of borrows by ap.refer() method
let mut ap = ArgumentParser::new();
ap.set_description("A simple tool to remember things");
ap.refer(&mut version).add_option(
&["-V", "--version"],
StoreTrue,
"Show current version and die",
);
ap.refer(&mut memo)
.add_option(&["-n", "--new"], Store, "Add a new memo");
ap.refer(&mut db_path)
.add_option(&["--path"], Store, "Specify db path");
ap.parse_args_or_exit();
}
if version {
const VERSION: &str = env!("CARGO_PKG_VERSION");
println!("memo-cli v{}", VERSION);
return;
}
let connection =
init_db(&db_path).unwrap_or_else(|err| panic!("Could not open db : {}", err.to_string()));
if memo.len() > 0 {
connection
.execute(
"INSERT INTO memo (body, due) VALUES (?, ?)",
params![memo, Utc::now()],
)
.unwrap_or_else(|err| panic!("Could not insert into db : {}", err.to_string()));
println!("New memo : '{}'", memo);
} else {
let zero_duration = Duration::seconds(0);
let memos = all(connection)
.unwrap_or_else(|err| panic!("Could not read all memos : {}", err.to_string()));
for m in memos {
let delta = m.due - Utc::now();
if delta.le(&zero_duration) {
println!("[*] {} : +{} \t[{}]", m.body, delta.pretty(), m.id);
} else {
println!(" * {} : -{} \t[{}]", m.body, delta.pretty(), m.id);
}
}
}
}