Merge pull request #2 from conradludgate/main
feat: use directories project data dir
This commit is contained in:
commit
46285309fe
6 changed files with 90 additions and 55 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -121,6 +121,15 @@ dependencies = [
|
|||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "directories"
|
||||
version = "3.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8fed639d60b58d0f53498ab13d26f621fd77569cc6edb031f4cc36a2ad9da0f"
|
||||
dependencies = [
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "2.0.2"
|
||||
|
@ -438,6 +447,7 @@ name = "shync"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"directories",
|
||||
"eyre",
|
||||
"log",
|
||||
"pretty_env_logger",
|
||||
|
|
|
@ -14,3 +14,4 @@ eyre = "0.6.1"
|
|||
shellexpand = "2.0.0"
|
||||
rusqlite = "0.24.0"
|
||||
structopt = "0.3.15"
|
||||
directories = "3.0.1"
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
use std::path::Path;
|
||||
|
||||
use eyre::Result;
|
||||
use shellexpand;
|
||||
|
||||
use rusqlite::{params, Connection};
|
||||
use rusqlite::NO_PARAMS;
|
||||
use rusqlite::{params, Connection};
|
||||
|
||||
use super::history::History;
|
||||
use crate::History;
|
||||
|
||||
pub trait Database {
|
||||
fn save(&self, h: History) -> Result<()>;
|
||||
|
@ -19,23 +18,25 @@ pub struct SqliteDatabase {
|
|||
conn: Connection,
|
||||
}
|
||||
|
||||
impl SqliteDatabase{
|
||||
pub fn new(path: &str) -> Result<SqliteDatabase> {
|
||||
let path = shellexpand::full(path)?;
|
||||
impl SqliteDatabase {
|
||||
pub fn new(path: impl AsRef<Path>) -> Result<SqliteDatabase> {
|
||||
let path = path.as_ref();
|
||||
|
||||
debug!("opening sqlite database at {:?}", path);
|
||||
|
||||
let create = !Path::new(path).exists();
|
||||
let create = !path.exists();
|
||||
if create {
|
||||
if let Some(dir) = path.parent() {
|
||||
std::fs::create_dir_all(dir)?;
|
||||
}
|
||||
}
|
||||
|
||||
let conn = Connection::open(path)?;
|
||||
|
||||
if create {
|
||||
Self::setup_db(&conn)?;
|
||||
}
|
||||
|
||||
Ok(SqliteDatabase{
|
||||
conn: conn,
|
||||
})
|
||||
Ok(SqliteDatabase { conn })
|
||||
}
|
||||
|
||||
fn setup_db(conn: &Connection) -> Result<()> {
|
||||
|
@ -43,11 +44,11 @@ impl SqliteDatabase{
|
|||
|
||||
conn.execute(
|
||||
"create table if not exists history (
|
||||
id integer primary key,
|
||||
timestamp integer not null,
|
||||
command text not null,
|
||||
cwd text not null
|
||||
)",
|
||||
id integer primary key,
|
||||
timestamp integer not null,
|
||||
command text not null,
|
||||
cwd text not null
|
||||
)",
|
||||
NO_PARAMS,
|
||||
)?;
|
||||
|
||||
|
@ -64,8 +65,9 @@ impl Database for SqliteDatabase {
|
|||
timestamp,
|
||||
command,
|
||||
cwd
|
||||
) values (?1, ?2, ?3)",
|
||||
params![h.timestamp, h.command, h.cwd])?;
|
||||
) values (?1, ?2, ?3)",
|
||||
params![h.timestamp, h.command, h.cwd],
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -73,7 +75,9 @@ impl Database for SqliteDatabase {
|
|||
fn list(&self) -> Result<()> {
|
||||
debug!("listing history");
|
||||
|
||||
let mut stmt = self.conn.prepare("SELECT timestamp, command, cwd FROM history")?;
|
||||
let mut stmt = self
|
||||
.conn
|
||||
.prepare("SELECT timestamp, command, cwd FROM history")?;
|
||||
let history_iter = stmt.query_map(params![], |row| {
|
||||
Ok(History {
|
||||
timestamp: row.get(0)?,
|
||||
|
|
|
@ -8,11 +8,11 @@ pub struct History {
|
|||
}
|
||||
|
||||
impl History {
|
||||
pub fn new(command: &str, cwd: &str) -> History {
|
||||
pub fn new(command: String, cwd: String) -> History {
|
||||
History {
|
||||
timestamp: chrono::Utc::now().timestamp_millis(),
|
||||
command: command.to_string(),
|
||||
cwd: cwd.to_string(),
|
||||
command,
|
||||
cwd,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
pub mod history;
|
||||
pub mod database;
|
||||
pub mod history;
|
||||
|
|
80
src/main.rs
80
src/main.rs
|
@ -1,45 +1,72 @@
|
|||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use directories::ProjectDirs;
|
||||
use eyre::{eyre, Result};
|
||||
use structopt::StructOpt;
|
||||
use eyre::Result;
|
||||
|
||||
#[macro_use] extern crate log;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
use pretty_env_logger;
|
||||
|
||||
mod local;
|
||||
|
||||
use local::history::History;
|
||||
use local::database::{Database, SqliteDatabase};
|
||||
use local::history::History;
|
||||
|
||||
#[derive(StructOpt)]
|
||||
#[structopt(
|
||||
author="Ellie Huxtable <e@elm.sh>",
|
||||
version="0.1.0",
|
||||
about="Keep your shell history in sync"
|
||||
author = "Ellie Huxtable <e@elm.sh>",
|
||||
version = "0.1.0",
|
||||
about = "Keep your shell history in sync"
|
||||
)]
|
||||
enum Shync {
|
||||
struct Shync {
|
||||
#[structopt(long, parse(from_os_str), help = "db file path")]
|
||||
db: Option<PathBuf>,
|
||||
|
||||
#[structopt(subcommand)]
|
||||
shync: ShyncCmd,
|
||||
}
|
||||
|
||||
#[derive(StructOpt)]
|
||||
enum ShyncCmd {
|
||||
#[structopt(
|
||||
about="manipulate shell history",
|
||||
aliases=&["h", "hi", "his", "hist", "histo", "histor"],
|
||||
)]
|
||||
History(HistoryCmd),
|
||||
|
||||
#[structopt(
|
||||
about="import shell history from file",
|
||||
)]
|
||||
#[structopt(about = "import shell history from file")]
|
||||
Import,
|
||||
|
||||
#[structopt(
|
||||
about="start a shync server",
|
||||
)]
|
||||
#[structopt(about = "start a shync server")]
|
||||
Server,
|
||||
}
|
||||
|
||||
impl Shync {
|
||||
fn run(self, db: SqliteDatabase) -> Result<()> {
|
||||
match self {
|
||||
Shync::History(history) => history.run(db),
|
||||
_ => Ok(())
|
||||
fn run(self) -> Result<()> {
|
||||
let db_path = match self.db {
|
||||
Some(db_path) => {
|
||||
let path = db_path
|
||||
.to_str()
|
||||
.ok_or(eyre!("path {:?} was not valid UTF-8", db_path))?;
|
||||
let path = shellexpand::full(path)?;
|
||||
PathBuf::from(path.as_ref())
|
||||
}
|
||||
None => {
|
||||
let project_dirs = ProjectDirs::from("bike", "ellie", "shync").ok_or(eyre!(
|
||||
"could not determine db file location\nspecify one using the --db flag"
|
||||
))?;
|
||||
let root = project_dirs.data_dir();
|
||||
root.join("history.db")
|
||||
}
|
||||
};
|
||||
|
||||
let db = SqliteDatabase::new(db_path)?;
|
||||
|
||||
match self.shync {
|
||||
ShyncCmd::History(history) => history.run(db),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,9 +77,7 @@ enum HistoryCmd {
|
|||
about="add a new command to the history",
|
||||
aliases=&["a", "ad"],
|
||||
)]
|
||||
Add {
|
||||
command: Vec<String>,
|
||||
},
|
||||
Add { command: Vec<String> },
|
||||
|
||||
#[structopt(
|
||||
about="list all items in history",
|
||||
|
@ -64,14 +89,10 @@ enum HistoryCmd {
|
|||
impl HistoryCmd {
|
||||
fn run(self, db: SqliteDatabase) -> Result<()> {
|
||||
match self {
|
||||
HistoryCmd::Add{command: words} => {
|
||||
HistoryCmd::Add { command: words } => {
|
||||
let command = words.join(" ");
|
||||
|
||||
let cwd = env::current_dir()?;
|
||||
let h = History::new(
|
||||
command.as_str(),
|
||||
cwd.display().to_string().as_str(),
|
||||
);
|
||||
let cwd = env::current_dir()?.display().to_string();
|
||||
let h = History::new(command, cwd);
|
||||
|
||||
debug!("adding history: {:?}", h);
|
||||
db.save(h)?;
|
||||
|
@ -79,7 +100,7 @@ impl HistoryCmd {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
HistoryCmd::List => db.list()
|
||||
HistoryCmd::List => db.list(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,6 +108,5 @@ impl HistoryCmd {
|
|||
fn main() -> Result<()> {
|
||||
pretty_env_logger::init();
|
||||
|
||||
let db = SqliteDatabase::new("~/.history.db")?;
|
||||
Shync::from_args().run(db)
|
||||
Shync::from_args().run()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue