Skip to content

Commit

Permalink
feat(clafrica): add support for config file
Browse files Browse the repository at this point in the history
  • Loading branch information
pythonbrad committed May 14, 2023
1 parent 4ec88ef commit 003b2a9
Show file tree
Hide file tree
Showing 9 changed files with 307 additions and 25 deletions.
137 changes: 137 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions clafrica/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ authors = ["Fomegne Brady <fomegnemeudje@outlook.com>"]
clafrica-lib = { version = "0.2.0", path = "../clafrica-lib" }
enigo = "0.1.2"
rdev = "0.5.2"
serde = { version = "1.0.163", features = ["serde_derive"] }
toml = "0.7.3"
Empty file added clafrica/data/blank_sample.toml
Empty file.
7 changes: 7 additions & 0 deletions clafrica/data/config_sample.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Main clafrica config file

[core]
buffer_size = 12

[data]
sample = { path = "./data_sample.toml" }
22 changes: 22 additions & 0 deletions clafrica/data/data_sample.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Sample data file

[info]
name = "Sample code"
authors = [
"Foo Bar <foo@example.com>",
{ name = "Baz Qux", email = "bazqux@example.com", url = "https://example.com/bazqux" }
]
website = "sample@example.com"
description = "Sample code for testing purpose."

[data]
2a_ = "á̠"
2af_ = "ɑ̠́"
2ai_ = "έ̠"
2ia = "íá"
2iaf = "íɑ́"
2ie = "íé"
2ua = "úá"
2uaf = "úɑ́"
2uuaf = "ʉ́ɑ́"
sample2 = { path = "./data_sample2.toml" }
14 changes: 14 additions & 0 deletions clafrica/data/data_sample2.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Sample data file

[info]
name = "Sample code 2"
authors = ["Foo Bar <foo@example.com>"]
website = "sample@example.com"
description = "Sample code for testing purpose."

[data]
2aa = { value = "áá", alias = ["a22"]}
2ee = { value = "éé", alias = ["e22"]}
2aff = { value = "ɑ́ɑ́", alias = ["aff22"]}
2ii = { value = "íí", alias = ["i22"]}
2oo = { value = "óó", alias = ["o22"]}
104 changes: 104 additions & 0 deletions clafrica/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
use serde::Deserialize;
use std::{collections::HashMap, error, fs, path::Path};
use toml::{self};

#[derive(Deserialize, Debug, Clone)]
pub struct Config {
pub core: Option<CoreConfig>,
pub data: HashMap<String, Data>,
}

#[derive(Deserialize, Debug, Clone)]
pub struct CoreConfig {
pub buffer_size: usize,
}

#[derive(Deserialize, Debug, Clone)]
#[serde(untagged)]
pub enum Data {
Simple(String),
File(DataFile),
Detailed(DetailedData),
}

#[derive(Deserialize, Debug, Clone)]
pub struct DataFile {
path: String,
}

#[derive(Deserialize, Debug, Clone)]
pub struct DetailedData {
value: String,
alias: Vec<String>,
}

impl Config {
pub fn from_file(filepath: &Path) -> Result<Self, Box<dyn error::Error>> {
let content = fs::read_to_string(filepath)?;
let mut config: Self = toml::from_str(&content)?;

let config_path = filepath.parent().unwrap();

let mut data = HashMap::new();

config
.data
.iter()
.try_for_each(|(key, value)| -> Result<(), Box<dyn error::Error>> {
match value {
Data::File(DataFile { path }) => {
let filepath = config_path.join(path);
let conf = Config::from_file(&filepath)?;
data.extend(conf.data);
}
Data::Simple(_) => {
data.insert(key.to_owned(), value.clone());
}
Data::Detailed(DetailedData { value, alias }) => {
alias.iter().chain([key.to_owned()].iter()).for_each(|e| {
data.insert(e.to_owned(), Data::Simple(value.to_owned()));
});
}
};
Ok(())
})?;

config.data = data;

Ok(config)
}

pub fn extract_data(&self) -> HashMap<&String, &String> {
self.data
.iter()
.filter_map(|(k, v)| {
let v = match v {
Data::Simple(value) => Some(value),
_ => None,
};
v.map(|v| (k, v))
})
.collect()
}
}

#[cfg(test)]
mod tests {
#[test]
fn from_file() {
use crate::config::Config;
use std::path::Path;

let conf = Config::from_file(&Path::new("./data/config_sample.toml"));

let conf = conf.unwrap();
assert_eq!(conf.core.unwrap().buffer_size, 12);
assert_eq!(conf.data.len(), 19);

let conf = Config::from_file(&Path::new("./not_found"));
assert!(conf.is_err());

let conf = Config::from_file(&Path::new("./data/blank_sample.toml"));
assert!(conf.is_err());
}
}
33 changes: 12 additions & 21 deletions clafrica/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,25 @@
pub mod api;
pub mod config;

use crate::api::Frontend;
use clafrica_lib::{text_buffer, utils};
use enigo::{Enigo, Key, KeyboardControllable};
use rdev::{self, EventType, Key as E_Key};
use std::{env, io, sync::mpsc, thread};

pub mod api;
use std::{io, sync::mpsc, thread};

pub struct Config {
pub data_path: String,
pub buffer_size: usize,
}

impl Config {
pub fn build(mut args: env::Args) -> Result<Self, &'static str> {
args.next();
Ok(Self {
data_path: args.next().ok_or("filepath required")?,
buffer_size: 10,
})
}
pub mod prelude {
pub use crate::config::Config;
}

pub fn run(config: Config, mut frontend: impl Frontend) -> Result<(), io::Error> {
let data = utils::load_data(&config.data_path)?;
pub fn run(config: config::Config, mut frontend: impl Frontend) -> Result<(), io::Error> {
let map = utils::build_map(
data.iter()
.map(|e| [e[0].as_ref(), e[1].as_ref()])
config
.extract_data()
.into_iter()
.map(|(k, v)| [k.as_str(), v.as_str()])
.collect(),
);
let mut cursor = text_buffer::Cursor::new(map, config.buffer_size);
let mut cursor = text_buffer::Cursor::new(map, config.core.map(|e| e.buffer_size).unwrap_or(8));

let mut keyboard = Enigo::new();

Expand Down
Loading

0 comments on commit 003b2a9

Please sign in to comment.