did a little clean up in config_parser
This commit is contained in:
+11
-36
@@ -1,7 +1,7 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{quote, TokenStreamExt};
|
use quote::quote;
|
||||||
|
|
||||||
use syn::{Attribute, Error, Field, Meta, Path, punctuated::Punctuated, token::Comma};
|
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() {
|
match attr_name.first() {
|
||||||
Some(value) => if value.ident == "nested_config" {
|
Some(value) => if value.ident == "nested_config" {
|
||||||
assignments.extend(quote! {
|
assignments.extend(quote! {
|
||||||
self.#name.parse_from_map(&#config_map_name);
|
self.#name.parse_from_map(&mut #config_map_name);
|
||||||
});
|
});
|
||||||
continue 'field_loop;
|
continue 'field_loop;
|
||||||
|
} else if value.ident == "no_config" {
|
||||||
|
continue 'field_loop;
|
||||||
},
|
},
|
||||||
None => (),
|
None => (),
|
||||||
}
|
}
|
||||||
@@ -32,8 +34,13 @@ pub fn gen_config_load_function(fields: &Punctuated<Field, Comma>, config_map_na
|
|||||||
assignments.extend(quote! {
|
assignments.extend(quote! {
|
||||||
self.#name = match #config_map_name.get(#name_string) {
|
self.#name = match #config_map_name.get(#name_string) {
|
||||||
Some(value) => match value.parse::<#ty>() {
|
Some(value) => match value.parse::<#ty>() {
|
||||||
Ok(parsed) => parsed,
|
Ok(parsed) => {
|
||||||
Err(_) => self.#name.clone(),
|
_ = #config_map_name.remove(#name_string);
|
||||||
|
parsed
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
self.#name.clone()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
None => 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())
|
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 common::gen_config_load_function;
|
||||||
use proc_macro2::{TokenStream}; // TODO: change to proc_macro2, to hopefully fix #assignments
|
use proc_macro2::TokenStream;
|
||||||
use syn::{parse_macro_input, spanned::Spanned, DeriveInput, Ident};
|
use syn::{parse_macro_input, DeriveInput};
|
||||||
use quote::{quote};
|
use quote::quote;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod common;
|
mod common;
|
||||||
@@ -11,7 +11,7 @@ mod common;
|
|||||||
/// which parses a string and fills the fills recognised values into the struct
|
/// which parses a string and fills the fills recognised values into the struct
|
||||||
/// - implements `write_default_config() -> Result<String>`
|
/// - implements `write_default_config() -> Result<String>`
|
||||||
/// which write a default configuration, in case the documentation is lacking
|
/// 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 {
|
pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
let ast = parse_macro_input!(input as DeriveInput);
|
let ast = parse_macro_input!(input as DeriveInput);
|
||||||
let name = &ast.ident;
|
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 {
|
let fields = if let syn::Data::Struct(syn::DataStruct{ fields: syn::Fields::Named(syn::FieldsNamed{ ref named, .. }), .. }) = ast.data {
|
||||||
named
|
named
|
||||||
} else {
|
} 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) {
|
let assignments = match gen_config_load_function(fields, &config_name) {
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
@@ -29,21 +29,26 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
|||||||
//let string = format!("{:#?}", ast);
|
//let string = format!("{:#?}", ast);
|
||||||
//_ = std::fs::write("test.txt", string);
|
//_ = std::fs::write("test.txt", string);
|
||||||
|
|
||||||
let expanded_stream: TokenStream = quote::quote! {
|
let expanded_stream: TokenStream = quote! {
|
||||||
impl #name {
|
impl #name {
|
||||||
|
/// tries to parse config from a string
|
||||||
pub fn parse_from_string(&mut self, input: &String) -> std::io::Result<()> {
|
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
|
#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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// **do not call**
|
/// **do not call**
|
||||||
/// this function needs to be public for nested configs but is not intended
|
/// this function needs to be public for nested configs but is not intended
|
||||||
/// to be called by the user
|
/// to be called by the user
|
||||||
pub fn parse_from_map(&mut self, input: &std::collections::HashMap<String, String>) -> std::io::Result<()> {
|
pub fn parse_from_map(&mut self, input: &mut std::collections::HashMap<String, String>) -> std::io::Result<()> {
|
||||||
let #config_name = input;
|
let mut #config_name = input;
|
||||||
|
|
||||||
#assignments
|
#assignments
|
||||||
|
|
||||||
|
|||||||
+19
-31
@@ -8,7 +8,7 @@ use dirs::config_dir;
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::{Error, Result};
|
use std::io::{Error, Result};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use derive_config_parser::ConfigParser;
|
use config_parser::ConfigParser;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
@@ -16,21 +16,24 @@ pub struct Config {
|
|||||||
pub settings: Settings,
|
pub settings: Settings,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default, ConfigParser)]
|
||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
|
#[nested_config]
|
||||||
pub general: GeneralSettings,
|
pub general: GeneralSettings,
|
||||||
|
#[nested_config]
|
||||||
pub format: FormatSettings,
|
pub format: FormatSettings,
|
||||||
|
#[nested_config]
|
||||||
pub styles: StyleSettings,
|
pub styles: StyleSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default, ConfigParser)]
|
||||||
pub struct GeneralSettings {
|
pub struct GeneralSettings {
|
||||||
pub show_stack_on_push: bool,
|
pub show_stack_on_push: bool,
|
||||||
pub show_stack_on_pop: bool,
|
pub show_stack_on_pop: bool,
|
||||||
pub show_stack_on_bookmark: bool,
|
pub show_stack_on_bookmark: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default, ConfigParser)]
|
||||||
pub struct FormatSettings {
|
pub struct FormatSettings {
|
||||||
pub stack_separator: String,
|
pub stack_separator: String,
|
||||||
pub bookmarks_separator: String,
|
pub bookmarks_separator: String,
|
||||||
@@ -90,12 +93,19 @@ impl Config {
|
|||||||
.push(format!("navigate/{}", Self::CONFIG_FILE_NAME));
|
.push(format!("navigate/{}", Self::CONFIG_FILE_NAME));
|
||||||
|
|
||||||
// parse configuration file and populate config struct
|
// parse configuration file and populate config struct
|
||||||
let file_error = config.build_settings();
|
if config.conf_file.is_file() {
|
||||||
config.set_default_settings()?;
|
let config_str = match fs::read_to_string(&config.conf_file) {
|
||||||
if file_error.is_err() {
|
Ok(value) => value,
|
||||||
config.write_config_file()?;
|
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)
|
Ok(config)
|
||||||
}
|
}
|
||||||
@@ -107,19 +117,6 @@ impl Config {
|
|||||||
|
|
||||||
/// reads and parses the configuration file
|
/// reads and parses the configuration file
|
||||||
fn build_settings(&mut self) -> Result<()> {
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,15 +156,6 @@ impl Config {
|
|||||||
Ok(())
|
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
|
/// convert color settings to ansi escape sequences
|
||||||
pub fn parse_color_settings(&mut self) -> Result<()> {
|
pub fn parse_color_settings(&mut self) -> Result<()> {
|
||||||
self.settings.styles.stack_number = parse_style(self.settings.styles.stack_number.clone())?;
|
self.settings.styles.stack_number = parse_style(self.settings.styles.stack_number.clone())?;
|
||||||
|
|||||||
Reference in New Issue
Block a user