Skip to content

Commit

Permalink
Merge pull request #53 from Sammy99jsp/dev
Browse files Browse the repository at this point in the history
AvdanOS Configuration Pt. II
  • Loading branch information
Akane authored Sep 10, 2022
2 parents 9e2e6a1 + cd1527a commit b8f0784
Show file tree
Hide file tree
Showing 22 changed files with 1,767 additions and 342 deletions.
11 changes: 10 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ documentation = "https://docs.avdanos.com/"
homepage = "https://avdanos.com/"
license = "GPL-3.0"
version = "0.0.1"
authors = ["Akane <[email protected]>", "Froxcey <[email protected]>", "Sammy <placeholder@email.com>"]
authors = ["Akane <[email protected]>", "Froxcey <[email protected]>", "Sammy <sammy99jsp@avdanos.com>"]
edition = "2021"
build = "build.rs"

Expand All @@ -18,6 +18,15 @@ json_comments = "0.2.1"
regex = "1.6.0"
slog-stdlog = "4.1.1"
bitflags = "1"
colored = "2.0.0"

[dependencies.compositor-macros]
path = "./src/macros"

[dependencies.json-tree]

git = "https://github.com/Sammy99jsp/json-tree.git"
features = ["jsonc"]

[dependencies.smithay]

Expand Down
73 changes: 42 additions & 31 deletions src/config/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,65 @@ use lazy_static::lazy_static;

pub(crate) use json_comments::StripComments;

use json_tree::{Index, TokenContent};
use json_tree::{Index,};
use serde::Deserialize;

use crate::{CONST::{
CONFIG_FOLDER,
CONFIG_FILE,
}, config::errors::UnexpectedToken};

use super::sections::{keybinds::Keybinds, section::ConfigurationSection};
use super::sections::{keybinds::Keybinds};

lazy_static! {
pub static ref PATH : String = CONFIG_FOLDER.join(*CONFIG_FILE).to_string_lossy().to_string();
pub static ref PATH : String = CONFIG_FOLDER.join(*CONFIG_FILE).to_string_lossy().to_string();
}
static mut INDEX : Option<Index> = None;

static mut _INDEX : Option<Index> = None;

static mut CONFIG : Option<Config> = None;

#[derive(Deserialize, Debug)]
pub struct Config {
keybinds: <Keybinds as ConfigurationSection>::Raw,
pub keybinds: Keybinds
}

impl Config {

pub fn path() -> String {
PATH.to_string()
}

///
/// Returns the config file's JSON index.
///
pub fn index<'a>() -> &'a Index {
unsafe {
_INDEX.as_ref().unwrap()
INDEX.as_ref().unwrap()
}
}

///
/// Returns the Global Configuration Object.
///
pub fn config<'a>() -> &'a Self {
unsafe {
CONFIG.as_ref().unwrap()
}
}
pub fn from_file() -> Result<Config, Box<dyn Error>> {


///
/// Loads the config.
///
/// THIS FUNCTION SHOULD BE NEAR THE TOP OF `main.rs`
///
pub fn load() -> Result<(), Box<dyn Error>> {
let path = PATH.to_string();
fs::create_dir_all(*CONFIG_FOLDER)
.expect("Error while creating the AvdanOS config directory!");

// TODO: If config file not found, either download config
// or use a pre-bundled copy.
let file: File = fs::OpenOptions::new()
.read(true).write(true).create(true)
.open(&path)?;
Expand Down Expand Up @@ -91,32 +117,17 @@ impl Config {
index
};

let mut parsed: Config = serde_json::from_reader(stripped)?;


unsafe {
_INDEX = Some(src_map);
INDEX = Some(src_map);
}

let result = Keybinds::parse(
Keybinds::traceable(
Some(true)
),
&parsed.keybinds,
Self::index()
);

match result {
Ok(k) => {
return Ok(parsed)
},
Err(errs) => {
for err in errs {
println!("{}\n", err);
}
let o = serde_json::from_reader(stripped)?;


unsafe {
CONFIG = Some(o);
};

panic!()
}
}
Ok(())
}
}
2 changes: 1 addition & 1 deletion src/config/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use compositor_macros::AvError;
use json_tree::{ParserError, TokenContent};
use crate::core::error::{TraceableError, AvError, Traceable};

use super::config::{self, Config};
use super::config;


///
Expand Down
8 changes: 8 additions & 0 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pub mod config;
pub mod sections;
pub mod section;
pub mod templating;
pub mod errors;

pub use config::Config;
pub use section::ConfigurationSection;
196 changes: 196 additions & 0 deletions src/config/section.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
use std::collections::HashMap;

use colored::Colorize;
use compositor_macros::{AvError, location, description};
use json_tree::{JSONPath, };

use crate::{core::error::{TraceableError, Traceable, AvError}, config::{config::{self, Config}, templating::{r#macro::SignatureMismatchError, AvMacro, avvalue::AvValue}}, Nadva::error::compare_errors};

pub trait ConfigurationSection : Sized {
///
/// The absolute path to this section as a str.
///
const PATH : &'static str;

///
/// Returns the absolute path to this section.
/// Can be used in finding location of data.
///
fn path() -> JSONPath {
Self::PATH.to_string().try_into().unwrap()
}

///
/// Returns this section's traceable.
///
fn traceable(key : Option<bool>) -> Traceable {
let loc = Config::index().get(&Self::path()).unwrap();
Traceable::combine(&config::PATH.to_string(), loc, key)
}

fn from_map(declared : HashMap<AvMacro, AvValue>, raw : HashMap<String, serde_json::Value>) -> HashMap<AvMacro, AvValue> {
let path : JSONPath = Self::path();

let res = raw.iter().map(|(k, v)| {
// Parse as a macro.
let p = path.push(k.clone());
let loc = Config::index().get(&p).unwrap();
let k_pos = Traceable::combine(&Config::path(), loc, Some(true));
let v_pos = Traceable::combine(&Config::path(), loc, Some(false));

(
AvMacro::parse(
k_pos.clone(),
k.clone()
),
v,
k_pos,
v_pos
)
});

// Syntactically invalid macros.

let mut errors : Vec<(Box<dyn TraceableError>, Traceable)> = vec![];

res
.clone()
.filter(|(k, _, _, _)| k.is_err())
.for_each(|(k, _, p, _)| {
let n = k.unwrap_err();

for err in n {
errors.push((err, p.clone()));
}
}
);


// Syntactically Valid macros
let defined = res
.filter(|(k, _, _, _)| k.is_ok())
.map(|(k, v, p1, p2)| (k.unwrap(), v, p1, p2));


let mut output : HashMap<AvMacro, AvValue> = HashMap::new();


let mut found_macros : Vec<usize> = vec![];
// Look up the valid macros against our declared HashMap.

for (declared_m, default_v) in declared {
let defined_m = defined.clone().position(|(m, _, _, _)| m.identifier() == declared_m.identifier());

let (avmacro, avvalue) = match defined_m {
None => {
// Macro not in user's config,
// use default
// (and possibly issue a warning).

// TODO: @Sammy99jsp add 'not found' warning.


errors.push((
Box::new(
MacroMissing(Self::traceable(Some(false)), declared_m.identifier(), Self::path())
),
Self::traceable(Some(false))
));
(declared_m, default_v)
},
Some(i) => {
found_macros.push(i);
let (m, v, p, p_v) = defined.clone().nth(i).unwrap();

// Check if the macro's signature matches our defined one.
let sig_check = declared_m.has_signature(&m);

if let Err((delta, vec)) = sig_check {
errors.push((
Box::new(
SignatureMismatchError(
p.clone(),
m.identifier(),
(delta, vec.iter().map(|e| (*e).clone()).collect())
)
) as Box<dyn TraceableError>,
p
));

(declared_m, default_v)
} else {
// VALUE CHECKS
// Now check the value's type against the default's
match default_v
.parse_same_type(p_v.clone(), v.clone())
{
Err(e) => {
errors.push((e, p));
(declared_m, default_v)
},
Ok(val) => {
// Last value check:
// Check if value is consistent with macro
match val.consistent_with_macro(p_v.clone(), &m) {
Ok(()) => (declared_m, val),
Err(e) => {
errors.push((e, p));
(declared_m, default_v)
},
}
}
}
}

}
};

output.insert(avmacro, avvalue);
}

// User defined macros which were not found in our declaration.
let not_found : Vec<_> = defined
.enumerate()
.filter(|(i, _)| !found_macros.contains(i))
.map(|(_, e)| e)
.collect();

for (m, _, p1, _) in not_found {
errors.push(
(
Box::new(
MacroNotFound(p1.clone(), m.identifier(), Self::path())
) as Box<dyn TraceableError>,
p1
)
)
}

errors
.sort_by(|(a, _), (b, _)|
compare_errors(a, b).unwrap()
);

for (err, _) in errors {
println!("{}", err);
}

output
}
}

#[AvError(TraceableError, CONFIG_MACRO_NOT_FOUND, "Config: Macro Not Found")]
pub struct MacroNotFound(pub Traceable, pub String, pub JSONPath);

impl TraceableError for MacroNotFound {
location!(&self.0);
description!(("The macro `{}` is not defined in this section (`{}`) -- we've used the default.", self.1.blue(), self.2));
}

#[AvError(TraceableError, CONFIG_MACRO_MISSING, "Config: Macro Missing")]
pub struct MacroMissing(pub Traceable, pub String, pub JSONPath);

impl TraceableError for MacroMissing {
location!(&self.0);
description!(("The macro `{}` wasn't found in {}.", self.1.blue(), self.2));
}
Loading

0 comments on commit b8f0784

Please sign in to comment.