diff --git a/Cargo.lock b/Cargo.lock
index 9e10df1..b4ef379 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -100,6 +100,27 @@ dependencies = [
"generic-array",
]
+[[package]]
+name = "dirs-next"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf36e65a80337bea855cd4ef9b8401ffce06a7baedf2e85ec467b1ac3f6e82b6"
+dependencies = [
+ "cfg-if",
+ "dirs-sys-next",
+]
+
+[[package]]
+name = "dirs-sys-next"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
+dependencies = [
+ "libc",
+ "redox_users",
+ "winapi",
+]
+
[[package]]
name = "formaty"
version = "0.1.0"
@@ -107,6 +128,7 @@ dependencies = [
"bitvec",
"byteorder",
"num-bigint",
+ "platform-dirs",
"rust-embed",
"serde",
"structopt",
@@ -129,6 +151,17 @@ dependencies = [
"version_check",
]
+[[package]]
+name = "getrandom"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
[[package]]
name = "heck"
version = "0.3.3"
@@ -155,9 +188,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.101"
+version = "0.2.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21"
+checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b"
[[package]]
name = "num-bigint"
@@ -195,6 +228,15 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
+[[package]]
+name = "platform-dirs"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e188d043c1a692985f78b5464853a263f1a27e5bd6322bad3a4078ee3c998a38"
+dependencies = [
+ "dirs-next",
+]
+
[[package]]
name = "proc-macro-error"
version = "1.0.4"
@@ -243,6 +285,26 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
+[[package]]
+name = "redox_syscall"
+version = "0.2.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "redox_users"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
+dependencies = [
+ "getrandom",
+ "redox_syscall",
+ "thiserror",
+]
+
[[package]]
name = "rust-embed"
version = "6.3.0"
@@ -375,6 +437,26 @@ dependencies = [
"unicode-width",
]
+[[package]]
+name = "thiserror"
+version = "1.0.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "toml"
version = "0.5.8"
@@ -431,6 +513,12 @@ dependencies = [
"winapi-util",
]
+[[package]]
+name = "wasi"
+version = "0.10.2+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+
[[package]]
name = "winapi"
version = "0.3.9"
diff --git a/Cargo.toml b/Cargo.toml
index f27ec7e..faed9d5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,4 +12,5 @@ toml = "0.5.8"
byteorder = "1.4.3"
num-bigint = "0.4"
rust-embed="6.3.0"
-bitvec = "1.0.0"
\ No newline at end of file
+bitvec = "1.0.0"
+platform-dirs = "0.3.0"
\ No newline at end of file
diff --git a/README.md b/README.md
index bed78b5..9c19e63 100644
--- a/README.md
+++ b/README.md
@@ -71,9 +71,10 @@ FLAGS:
-V, --version Prints version information
OPTIONS:
- -b, --base Base of the input values
- -c, --config Path to the format config [env: FORMATY_CONFIG=]
- -i, --input_type Input data type [default: array]
+ -b, --base Base of the input values
+ -c, --config Path to the format config [env: FORMATY_CONFIG=]
+ -g, --global_config Path to the global config directory [env: FORMATY_GLOBAL_CONFIG=]
+ -i, --input_type Input data type [default: array]
ARGS:
Format to parse data as
diff --git a/src/formatter/mod.rs b/src/formatter/mod.rs
index e8bddb0..ce70573 100644
--- a/src/formatter/mod.rs
+++ b/src/formatter/mod.rs
@@ -2,14 +2,15 @@ pub mod format;
mod printers;
use crate::formatter::format::Format;
+use platform_dirs::AppDirs;
use rust_embed::RustEmbed;
use serde::Deserialize;
use std::error::Error;
use std::fmt::{Display, Formatter};
-use std::fs::File;
+use std::fs::{read_dir, File};
use std::io::Read;
use std::path::PathBuf;
-use std::str;
+use std::{fs, str};
#[derive(Debug)]
#[allow(clippy::enum_variant_names)]
@@ -63,21 +64,17 @@ pub struct FormatConfig {
}
impl FormatConfig {
- pub fn new(config_path: &Option) -> Result {
- let mut config_str = String::new();
-
- let mut config: FormatConfig = if let Some(config_path) = config_path {
- let mut config = File::open(config_path)?;
- config.read_to_string(&mut config_str)?;
-
- toml::from_str(&config_str).map_err(|e| FormatConfigError::TomlError {
- file_name: config_path.to_str().unwrap().to_string(),
- err: e,
- })?
- } else {
- FormatConfig::default()
- };
+ fn parse_config_file(
+ src_file_name: &str,
+ config_data: &str,
+ ) -> Result {
+ toml::from_str(config_data).map_err(|e| FormatConfigError::TomlError {
+ file_name: src_file_name.to_string(),
+ err: e,
+ })
+ }
+ fn get_built_in_config(&mut self) -> Result<(), FormatConfigError> {
for format_file_path in BuiltInFormats::iter() {
if format_file_path.ends_with("md") {
continue;
@@ -88,14 +85,69 @@ impl FormatConfig {
let config_str = str::from_utf8(&format_file.data).unwrap();
let mut built_in: FormatConfig =
- toml::from_str(config_str).map_err(|e| FormatConfigError::TomlError {
- file_name: format_file_path.to_string(),
- err: e,
- })?;
+ Self::parse_config_file(&format_file_path, config_str)?;
- config.formats.append(&mut built_in.formats);
+ self.formats.append(&mut built_in.formats);
}
+ Ok(())
+ }
+
+ fn get_file_config(&mut self, config_path: &Option) -> Result<(), FormatConfigError> {
+ if let Some(config_path) = config_path {
+ let mut config_file = File::open(config_path)?;
+ let mut config_data = String::new();
+ config_file.read_to_string(&mut config_data)?;
+ let mut arg_config =
+ Self::parse_config_file(config_path.to_str().unwrap(), &config_data)?;
+
+ self.formats.append(&mut arg_config.formats);
+ }
+
+ Ok(())
+ }
+
+ fn parse_directory(
+ &mut self,
+ directory_path: &Option,
+ ) -> Result<(), FormatConfigError> {
+ if let Some(directory_path) = directory_path {
+ for path in read_dir(directory_path)? {
+ let file_name = path?.file_name();
+ let config_file_path = directory_path.join(file_name);
+
+ self.get_file_config(&Some(config_file_path))?;
+ }
+ }
+
+ Ok(())
+ }
+
+ pub fn new(
+ config_path: &Option,
+ global_config_path: &Option,
+ ) -> Result {
+ let mut config = FormatConfig::default();
+
+ config.get_built_in_config()?;
+
+ config.get_file_config(config_path)?;
+
+ let global_dir = match global_config_path {
+ Some(g) => g.clone(),
+ None => {
+ let app_dirs = AppDirs::new(Some("formaty"), true).unwrap();
+
+ if !app_dirs.config_dir.exists() {
+ fs::create_dir(&app_dirs.config_dir)?;
+ }
+
+ app_dirs.config_dir
+ }
+ };
+
+ config.parse_directory(&Some(global_dir))?;
+
Ok(config)
}
diff --git a/src/main.rs b/src/main.rs
index 9f58b65..6b98ac4 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -22,6 +22,15 @@ pub struct Args {
)]
config: Option,
+ #[structopt(
+ short = "g",
+ long = "global_config",
+ env = "FORMATY_GLOBAL_CONFIG",
+ parse(from_os_str),
+ help = "Path to the global config directory"
+ )]
+ global_config: Option,
+
#[structopt(
help = "Input data type",
short = "i",
@@ -43,7 +52,7 @@ pub struct Args {
fn init() -> Result<(Vec, Format), FormatyError> {
let args: Args = Args::from_args();
- let config = FormatConfig::new(&args.config)?;
+ let config = FormatConfig::new(&args.config, &args.global_config)?;
let format = config.get_format(&args.format)?;