did a little clean up in config_parser
This commit is contained in:
+11
-36
@@ -1,7 +1,7 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{quote, TokenStreamExt};
|
||||
use quote::quote;
|
||||
|
||||
use syn::{Attribute, Error, Field, Meta, Path, punctuated::Punctuated, token::Comma};
|
||||
|
||||
@@ -21,9 +21,11 @@ pub fn gen_config_load_function(fields: &Punctuated<Field, Comma>, config_map_na
|
||||
match attr_name.first() {
|
||||
Some(value) => if value.ident == "nested_config" {
|
||||
assignments.extend(quote! {
|
||||
self.#name.parse_from_map(&#config_map_name);
|
||||
self.#name.parse_from_map(&mut #config_map_name);
|
||||
});
|
||||
continue 'field_loop;
|
||||
} else if value.ident == "no_config" {
|
||||
continue 'field_loop;
|
||||
},
|
||||
None => (),
|
||||
}
|
||||
@@ -32,8 +34,13 @@ pub fn gen_config_load_function(fields: &Punctuated<Field, Comma>, config_map_na
|
||||
assignments.extend(quote! {
|
||||
self.#name = match #config_map_name.get(#name_string) {
|
||||
Some(value) => match value.parse::<#ty>() {
|
||||
Ok(parsed) => parsed,
|
||||
Err(_) => self.#name.clone(),
|
||||
Ok(parsed) => {
|
||||
_ = #config_map_name.remove(#name_string);
|
||||
parsed
|
||||
},
|
||||
Err(_) => {
|
||||
self.#name.clone()
|
||||
},
|
||||
},
|
||||
None => self.#name.clone(),
|
||||
};
|
||||
@@ -42,35 +49,3 @@ pub fn gen_config_load_function(fields: &Punctuated<Field, Comma>, config_map_na
|
||||
Ok(assignments.into())
|
||||
}
|
||||
|
||||
//pub fn parse_config_file(input: &String) -> std::io::Result<std::collections::HashMap<String, String>> {
|
||||
// let mut config = std::collections::HashMap::<String, String>::new();
|
||||
// let lines = input.lines();
|
||||
//
|
||||
// for line in lines {
|
||||
// let line = line.trim();
|
||||
// // ignore empty lines
|
||||
// if line.is_empty() { continue; }
|
||||
//
|
||||
// if line.starts_with("[") {
|
||||
// // check for table
|
||||
// if !line.ends_with("]") {
|
||||
// // TODO: implement error handling
|
||||
// } else if line.contains(' ') {
|
||||
// // TODO: implement error handling
|
||||
// }
|
||||
// //let tokens = line.split('.');
|
||||
// // TODO: implement hirarchical map
|
||||
// } else {
|
||||
// // check for config
|
||||
// let mut tokens: Vec<&str> = line.split('=').map(|entry| entry.trim()).collect();
|
||||
// tokens.retain(|entry| !entry.is_empty());
|
||||
// if tokens.len() != 2 {
|
||||
// // println!("error in line'", line);
|
||||
// continue;
|
||||
// }
|
||||
// config.insert(tokens[0].to_string(), tokens[1].to_string());
|
||||
// }
|
||||
// }
|
||||
// Ok(config)
|
||||
//}
|
||||
//
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use common::gen_config_load_function;
|
||||
use proc_macro2::{TokenStream}; // TODO: change to proc_macro2, to hopefully fix #assignments
|
||||
use syn::{parse_macro_input, spanned::Spanned, DeriveInput, Ident};
|
||||
use quote::{quote};
|
||||
use proc_macro2::TokenStream;
|
||||
use syn::{parse_macro_input, DeriveInput};
|
||||
use quote::quote;
|
||||
|
||||
#[macro_use]
|
||||
mod common;
|
||||
@@ -11,7 +11,7 @@ mod common;
|
||||
/// which parses a string and fills the fills recognised values into the struct
|
||||
/// - implements `write_default_config() -> Result<String>`
|
||||
/// which write a default configuration, in case the documentation is lacking
|
||||
#[proc_macro_derive(ConfigParser, attributes(nested_config))]
|
||||
#[proc_macro_derive(ConfigParser, attributes(color_config, nested_config, no_config))]
|
||||
pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let ast = parse_macro_input!(input as DeriveInput);
|
||||
let name = &ast.ident;
|
||||
@@ -19,7 +19,7 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let fields = if let syn::Data::Struct(syn::DataStruct{ fields: syn::Fields::Named(syn::FieldsNamed{ ref named, .. }), .. }) = ast.data {
|
||||
named
|
||||
} else {
|
||||
todo!("use `syn::Error` to return comprehensive error message");
|
||||
panic!("the macro `ConfigParser` applies only to structs!");
|
||||
};
|
||||
let assignments = match gen_config_load_function(fields, &config_name) {
|
||||
Ok(value) => value,
|
||||
@@ -29,21 +29,26 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
//let string = format!("{:#?}", ast);
|
||||
//_ = std::fs::write("test.txt", string);
|
||||
|
||||
let expanded_stream: TokenStream = quote::quote! {
|
||||
let expanded_stream: TokenStream = quote! {
|
||||
impl #name {
|
||||
/// tries to parse config from a string
|
||||
pub fn parse_from_string(&mut self, input: &String) -> std::io::Result<()> {
|
||||
let #config_name : std::collections::HashMap<String, String> = Self::parse_config_file(input)?;
|
||||
let mut #config_name : std::collections::HashMap<String, String> = Self::parse_config_file(input)?;
|
||||
|
||||
#assignments
|
||||
|
||||
if !#config_name.is_empty() {
|
||||
let leftovers = #config_name.keys().cloned().collect::<Vec<String>>();
|
||||
return Err(std::io::Error::other(format!("the following settings were not recognised: {:#?}", leftovers)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// **do not call**
|
||||
/// this function needs to be public for nested configs but is not intended
|
||||
/// to be called by the user
|
||||
pub fn parse_from_map(&mut self, input: &std::collections::HashMap<String, String>) -> std::io::Result<()> {
|
||||
let #config_name = input;
|
||||
pub fn parse_from_map(&mut self, input: &mut std::collections::HashMap<String, String>) -> std::io::Result<()> {
|
||||
let mut #config_name = input;
|
||||
|
||||
#assignments
|
||||
|
||||
|
||||
+19
-31
@@ -8,7 +8,7 @@ use dirs::config_dir;
|
||||
use std::fs;
|
||||
use std::io::{Error, Result};
|
||||
use std::path::PathBuf;
|
||||
use derive_config_parser::ConfigParser;
|
||||
use config_parser::ConfigParser;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Config {
|
||||
@@ -16,21 +16,24 @@ pub struct Config {
|
||||
pub settings: Settings,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[derive(Debug, Clone, Default, ConfigParser)]
|
||||
pub struct Settings {
|
||||
#[nested_config]
|
||||
pub general: GeneralSettings,
|
||||
#[nested_config]
|
||||
pub format: FormatSettings,
|
||||
#[nested_config]
|
||||
pub styles: StyleSettings,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[derive(Debug, Clone, Default, ConfigParser)]
|
||||
pub struct GeneralSettings {
|
||||
pub show_stack_on_push: bool,
|
||||
pub show_stack_on_pop: bool,
|
||||
pub show_stack_on_bookmark: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[derive(Debug, Clone, Default, ConfigParser)]
|
||||
pub struct FormatSettings {
|
||||
pub stack_separator: String,
|
||||
pub bookmarks_separator: String,
|
||||
@@ -90,12 +93,19 @@ impl Config {
|
||||
.push(format!("navigate/{}", Self::CONFIG_FILE_NAME));
|
||||
|
||||
// parse configuration file and populate config struct
|
||||
let file_error = config.build_settings();
|
||||
config.set_default_settings()?;
|
||||
if file_error.is_err() {
|
||||
config.write_config_file()?;
|
||||
if config.conf_file.is_file() {
|
||||
let config_str = match fs::read_to_string(&config.conf_file) {
|
||||
Ok(value) => value,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
_ = config.settings.parse_from_string(&config_str);
|
||||
} else {
|
||||
// TODO: write default configuration
|
||||
}
|
||||
config.parse_color_settings()?;
|
||||
|
||||
// TODO: ALSDKJFJFJASDkk
|
||||
//config.set_default_settings()?;
|
||||
//config.parse_color_settings()?;
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
@@ -107,19 +117,6 @@ impl Config {
|
||||
|
||||
/// reads and parses the configuration file
|
||||
fn build_settings(&mut self) -> Result<()> {
|
||||
if !self.conf_file.is_file() {
|
||||
return Err(Error::other(
|
||||
"-- config file `navigation.conf` does not exist",
|
||||
));
|
||||
}
|
||||
let config_str = match fs::read_to_string(&self.conf_file) {
|
||||
Ok(value) => value,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
self.settings = match toml::from_str(&config_str) {
|
||||
Ok(value) => value,
|
||||
Err(error) => return Err(Error::other(error.to_string())),
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -159,15 +156,6 @@ impl Config {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// write configuration file to save changed settings
|
||||
pub fn write_config_file(&self) -> Result<()> {
|
||||
let conf_str = match toml::to_string(&self.settings) {
|
||||
Ok(value) => value,
|
||||
Err(error) => return Err(Error::other(error.to_string())),
|
||||
};
|
||||
fs::write(self.conf_file.clone(), conf_str)
|
||||
}
|
||||
|
||||
/// convert color settings to ansi escape sequences
|
||||
pub fn parse_color_settings(&mut self) -> Result<()> {
|
||||
self.settings.styles.stack_number = parse_style(self.settings.styles.stack_number.clone())?;
|
||||
|
||||
Reference in New Issue
Block a user