Add config file support (#15)
This commit is contained in:
parent
b42d93dcc8
commit
61607e023f
7 changed files with 162 additions and 40 deletions
88
Cargo.lock
generated
88
Cargo.lock
generated
|
@ -120,6 +120,8 @@ dependencies = [
|
|||
"pretty_env_logger",
|
||||
"rocket",
|
||||
"rusqlite",
|
||||
"serde 1.0.124",
|
||||
"serde_derive",
|
||||
"shellexpand",
|
||||
"structopt",
|
||||
"uuid",
|
||||
|
@ -293,17 +295,17 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "config"
|
||||
version = "0.9.3"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9107d78ed62b3fa5a86e7d18e647abed48cfd8f8fab6c72f4cdb982d196f7e6"
|
||||
checksum = "19b076e143e1d9538dde65da30f8481c2a6c44040edb8e02b9bf1351edb92ce3"
|
||||
dependencies = [
|
||||
"lazy_static 1.4.0",
|
||||
"lazy_static",
|
||||
"nom",
|
||||
"rust-ini",
|
||||
"serde 1.0.123",
|
||||
"serde 1.0.124",
|
||||
"serde-hjson",
|
||||
"serde_json",
|
||||
"toml",
|
||||
"toml 0.5.8",
|
||||
"yaml-rust",
|
||||
]
|
||||
|
||||
|
@ -314,7 +316,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "7cc80946b3480f421c2f17ed1cb841753a371c7c5104f51d507e13f532c856aa"
|
||||
dependencies = [
|
||||
"encode_unicode",
|
||||
"lazy_static 1.4.0",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"regex",
|
||||
"terminal_size",
|
||||
|
@ -352,7 +354,7 @@ checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
|
|||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if 1.0.0",
|
||||
"lazy_static 1.4.0",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -675,7 +677,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "7baab56125e25686df467fe470785512329883aab42696d661247aca2a2896e4"
|
||||
dependencies = [
|
||||
"console",
|
||||
"lazy_static 1.4.0",
|
||||
"lazy_static",
|
||||
"number_prefix",
|
||||
"regex",
|
||||
]
|
||||
|
@ -692,18 +694,25 @@ version = "0.2.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "lexical-core"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21f866863575d0e1d654fbeeabdc927292fdf862873dc3c96c6f753357e13374"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
"cfg-if 1.0.0",
|
||||
"ryu",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.86"
|
||||
|
@ -784,12 +793,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "4.2.3"
|
||||
version = "5.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
|
||||
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
|
||||
dependencies = [
|
||||
"lexical-core",
|
||||
"memchr",
|
||||
"version_check 0.1.5",
|
||||
"version_check 0.9.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1091,7 +1101,7 @@ dependencies = [
|
|||
"rocket_http",
|
||||
"state",
|
||||
"time",
|
||||
"toml",
|
||||
"toml 0.4.10",
|
||||
"version_check 0.9.2",
|
||||
"yansi",
|
||||
]
|
||||
|
@ -1187,23 +1197,34 @@ checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.123"
|
||||
version = "1.0.124"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae"
|
||||
checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f"
|
||||
|
||||
[[package]]
|
||||
name = "serde-hjson"
|
||||
version = "0.8.2"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b833c5ad67d52ced5f5938b2980f32a9c1c5ef047f0b4fb3127e7a423c76153"
|
||||
checksum = "6a3a4e0ea8a88553209f6cc6cfe8724ecad22e1acf372793c27d995290fe74f8"
|
||||
dependencies = [
|
||||
"lazy_static 0.2.11",
|
||||
"lazy_static",
|
||||
"linked-hash-map 0.3.0",
|
||||
"num-traits 0.1.43",
|
||||
"regex",
|
||||
"serde 0.8.23",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.124"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.62"
|
||||
|
@ -1212,7 +1233,7 @@ checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486"
|
|||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde 1.0.123",
|
||||
"serde 1.0.124",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1257,6 +1278,12 @@ version = "0.4.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3015a7d0a5fd5105c91c3710d42f9ccf0abfb287d62206484dcc67f9569a6483"
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.8.0"
|
||||
|
@ -1270,7 +1297,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "5277acd7ee46e63e5168a80734c9f6ee81b1367a7d8772a2d765df2a3705d28c"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"lazy_static 1.4.0",
|
||||
"lazy_static",
|
||||
"structopt-derive",
|
||||
]
|
||||
|
||||
|
@ -1389,7 +1416,16 @@ version = "0.4.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f"
|
||||
dependencies = [
|
||||
"serde 1.0.123",
|
||||
"serde 1.0.124",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
|
||||
dependencies = [
|
||||
"serde 1.0.124",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -20,7 +20,9 @@ hostname = "0.3.1"
|
|||
rocket = "0.4.7"
|
||||
chrono-english = "0.1.4"
|
||||
cli-table = "0.4"
|
||||
config = "0.9"
|
||||
config = "0.10"
|
||||
serde_derive = "1.0.124"
|
||||
serde = "1.0.124"
|
||||
|
||||
[dependencies.rusqlite]
|
||||
version = "0.24"
|
||||
|
|
14
README.md
14
README.md
|
@ -179,6 +179,20 @@ $ atuin stats all
|
|||
+---------------------+-------+
|
||||
```
|
||||
|
||||
## Config
|
||||
|
||||
A'tuin is configurable via TOML. The file lives at ` ~/.config/atuin/config.toml`,
|
||||
and looks like this:
|
||||
|
||||
```
|
||||
[local]
|
||||
dialect = "uk" # or us. sets the date format used by stats
|
||||
server_address = "https://atuin.elliehuxtable.com/" # the server to sync with
|
||||
|
||||
[local.db]
|
||||
path = "~/.local/share/atuin/history.db" # the local database for history
|
||||
```
|
||||
|
||||
## ...what's with the name?
|
||||
|
||||
A'tuin is named after "The Great A'tuin", a giant turtle from Terry Pratchett's
|
||||
|
|
|
@ -3,6 +3,7 @@ use structopt::StructOpt;
|
|||
use uuid::Uuid;
|
||||
|
||||
use crate::local::database::Database;
|
||||
use crate::settings::Settings;
|
||||
|
||||
mod history;
|
||||
mod import;
|
||||
|
@ -39,12 +40,12 @@ pub fn uuid_v4() -> String {
|
|||
}
|
||||
|
||||
impl AtuinCmd {
|
||||
pub fn run(self, db: &mut impl Database) -> Result<()> {
|
||||
pub fn run(self, db: &mut impl Database, settings: &Settings) -> Result<()> {
|
||||
match self {
|
||||
Self::History(history) => history.run(db),
|
||||
Self::Import(import) => import.run(db),
|
||||
Self::Server(server) => server.run(),
|
||||
Self::Stats(stats) => stats.run(db),
|
||||
Self::Stats(stats) => stats.run(db, settings),
|
||||
Self::Init => init::init(),
|
||||
|
||||
Self::Uuid => {
|
||||
|
|
|
@ -10,6 +10,7 @@ use structopt::StructOpt;
|
|||
|
||||
use crate::local::database::Database;
|
||||
use crate::local::history::History;
|
||||
use crate::settings::Settings;
|
||||
|
||||
#[derive(StructOpt)]
|
||||
pub enum Cmd {
|
||||
|
@ -70,7 +71,7 @@ fn compute_stats(history: &[History]) -> Result<()> {
|
|||
}
|
||||
|
||||
impl Cmd {
|
||||
pub fn run(&self, db: &mut impl Database) -> Result<()> {
|
||||
pub fn run(&self, db: &mut impl Database, settings: &Settings) -> Result<()> {
|
||||
match self {
|
||||
Self::Day { words } => {
|
||||
let words = if words.is_empty() {
|
||||
|
@ -79,7 +80,10 @@ impl Cmd {
|
|||
words.join(" ")
|
||||
};
|
||||
|
||||
let start = parse_date_string(&words, Local::now(), Dialect::Us)?;
|
||||
let start = match settings.local.dialect.to_lowercase().as_str() {
|
||||
"uk" => parse_date_string(&words, Local::now(), Dialect::Uk)?,
|
||||
_ => parse_date_string(&words, Local::now(), Dialect::Us)?,
|
||||
};
|
||||
let end = start + Duration::days(1);
|
||||
|
||||
let history = db.range(start.into(), end.into())?;
|
||||
|
|
19
src/main.rs
19
src/main.rs
|
@ -1,11 +1,10 @@
|
|||
#![feature(str_split_once)]
|
||||
#![feature(proc_macro_hygiene)]
|
||||
#![feature(decl_macro)]
|
||||
#![warn(clippy::pedantic, clippy::nursery)]
|
||||
#![allow(clippy::use_self)] // not 100% reliable
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use directories::ProjectDirs;
|
||||
use eyre::{eyre, Result};
|
||||
use structopt::StructOpt;
|
||||
|
||||
|
@ -15,12 +14,17 @@ extern crate log;
|
|||
#[macro_use]
|
||||
extern crate rocket;
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
use command::AtuinCmd;
|
||||
use local::database::Sqlite;
|
||||
use settings::Settings;
|
||||
|
||||
mod command;
|
||||
mod local;
|
||||
mod remote;
|
||||
mod settings;
|
||||
|
||||
#[derive(StructOpt)]
|
||||
#[structopt(
|
||||
|
@ -38,6 +42,8 @@ struct Atuin {
|
|||
|
||||
impl Atuin {
|
||||
fn run(self) -> Result<()> {
|
||||
let settings = Settings::new()?;
|
||||
|
||||
let db_path = if let Some(db_path) = self.db {
|
||||
let path = db_path
|
||||
.to_str()
|
||||
|
@ -45,17 +51,12 @@ impl Atuin {
|
|||
let path = shellexpand::full(path)?;
|
||||
PathBuf::from(path.as_ref())
|
||||
} else {
|
||||
ProjectDirs::from("com", "elliehuxtable", "atuin")
|
||||
.ok_or_else(|| {
|
||||
eyre!("could not determine db file location\nspecify one using the --db flag")
|
||||
})?
|
||||
.data_dir()
|
||||
.join("history.db")
|
||||
PathBuf::from(settings.local.db.path.as_str())
|
||||
};
|
||||
|
||||
let mut db = Sqlite::new(db_path)?;
|
||||
|
||||
self.atuin.run(&mut db)
|
||||
self.atuin.run(&mut db, &settings)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
64
src/settings.rs
Normal file
64
src/settings.rs
Normal file
|
@ -0,0 +1,64 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use config::{Config, File};
|
||||
use directories::ProjectDirs;
|
||||
use eyre::{eyre, Result};
|
||||
use std::fs;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct LocalDatabase {
|
||||
pub path: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct Local {
|
||||
pub server_address: String,
|
||||
pub dialect: String,
|
||||
pub db: LocalDatabase,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct Settings {
|
||||
pub local: Local,
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
pub fn new() -> Result<Self> {
|
||||
let config_dir = ProjectDirs::from("com", "elliehuxtable", "atuin").unwrap();
|
||||
let config_dir = config_dir.config_dir();
|
||||
|
||||
fs::create_dir_all(config_dir)?;
|
||||
|
||||
let mut config_file = PathBuf::new();
|
||||
config_file.push(config_dir);
|
||||
config_file.push("config.toml");
|
||||
let config_file = config_file.as_path();
|
||||
|
||||
// create the config file if it does not exist
|
||||
|
||||
let mut s = Config::new();
|
||||
|
||||
let db_path = ProjectDirs::from("com", "elliehuxtable", "atuin")
|
||||
.ok_or_else(|| {
|
||||
eyre!("could not determine db file location\nspecify one using the --db flag")
|
||||
})?
|
||||
.data_dir()
|
||||
.join("history.db");
|
||||
|
||||
s.set_default("local.server_address", "https://atuin.elliehuxtable.com")?;
|
||||
s.set_default("local.dialect", "us")?;
|
||||
s.set_default("local.db.path", db_path.to_str())?;
|
||||
|
||||
if config_file.exists() {
|
||||
s.merge(File::with_name(config_file.to_str().unwrap()))?;
|
||||
}
|
||||
|
||||
// all paths should be expanded
|
||||
let db_path = s.get_str("local.db.path")?;
|
||||
let db_path = shellexpand::full(db_path.as_str())?;
|
||||
s.set("local.db.path", db_path.to_string())?;
|
||||
|
||||
s.try_into()
|
||||
.map_err(|e| eyre!("failed to deserialize: {}", e))
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue