did a little clean up in config_parser

This commit is contained in:
2025-01-09 23:29:42 +01:00
parent 1d4688cf95
commit 57dbafac3d
3 changed files with 44 additions and 76 deletions
+11 -36
View File
@@ -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)
//}
//
+14 -9
View File
@@ -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
View File
@@ -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())?;