separate default and base config

This commit is contained in:
mat 2024-04-18 04:41:26 +00:00
parent afc526c6f2
commit 75572c17a2
7 changed files with 60 additions and 43 deletions

2
README
View File

@ -13,7 +13,7 @@ build it with `cargo b -r`, the resulting binary will be at
`target/release/metasearch2`. `target/release/metasearch2`.
the config.toml file is created in your current working directory on the first the config.toml file is created in your current working directory on the first
run of metasearch2. alternatively, you can copy the default-config.toml in the run of metasearch2. alternatively, you can copy the config-default.toml in the
repo and rename it to config.toml. repo and rename it to config.toml.
the default port is 28019. the default port is 28019.

View File

@ -1,3 +1,5 @@
# This is the config that's used as a fallback when a field is missing from the user's config.toml.
bind = "0.0.0.0:28019" bind = "0.0.0.0:28019"
engine_list_separator = false engine_list_separator = false

13
config-default.toml Normal file
View File

@ -0,0 +1,13 @@
# See https://github.com/mat-1/metasearch2/blob/master/config-base.toml and
# https://github.com/mat-1/metasearch2/blob/master/src/config.rs for some of
# the possible options
bind = "0.0.0.0:28019"
[ui]
# engine_list_separator = true
# version_info = true
[engines]
# numbat = false
# fend = true

View File

@ -9,40 +9,52 @@ use crate::engines::Engine;
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
pub struct Config { pub struct Config {
pub bind: SocketAddr, pub bind: SocketAddr,
#[serde(default)] pub ui: UiConfig,
pub engine_list_separator: Option<bool>,
#[serde(default)]
pub version_info: Option<bool>,
pub engines: EnginesConfig, pub engines: EnginesConfig,
} }
impl Config { #[derive(Deserialize, Debug)]
pub fn read_or_create() -> eyre::Result<Self> { pub struct UiConfig {
let default_config_str = include_str!("../default-config.toml"); #[serde(default)]
let mut config: Config = toml::from_str(default_config_str)?; pub show_engine_list_separator: Option<bool>,
#[serde(default)]
pub show_version_info: Option<bool>,
}
let config_path = std::env::args().nth(1).unwrap_or("config.toml".into()); #[derive(Deserialize, Debug)]
let config_path = Path::new(&config_path); pub struct EnginesConfig {
if config_path.exists() { #[serde(flatten)]
let given_config = toml::from_str::<Config>(&fs::read_to_string(config_path)?)?; pub map: HashMap<Engine, DefaultableEngineConfig>,
config.update(given_config); }
Ok(config)
} else { impl Config {
pub fn read_or_create(config_path: &Path) -> eyre::Result<Self> {
let base_config_str = include_str!("../config-base.toml");
let mut config: Config = toml::from_str(base_config_str)?;
if !config_path.exists() {
info!("No config found, creating one at {config_path:?}"); info!("No config found, creating one at {config_path:?}");
let default_config_str = include_str!("../config-default.toml");
fs::write(config_path, default_config_str)?; fs::write(config_path, default_config_str)?;
Ok(config)
} }
let given_config = toml::from_str::<Config>(&fs::read_to_string(config_path)?)?;
config.update(given_config);
Ok(config)
} }
// Update the current config with the given config. This is used to make it so // Update the current config with the given config. This is used to make it so
// the default-config.toml is always used as a fallback if the user decides to // the config-base.toml is always used as a fallback if the user decides to
// use the default for something. // use the default for something.
pub fn update(&mut self, new: Config) { pub fn update(&mut self, new: Config) {
self.bind = new.bind; self.bind = new.bind;
self.engine_list_separator = new.engine_list_separator.or(self.engine_list_separator); self.ui.show_engine_list_separator = new
assert_ne!(self.engine_list_separator, None); .ui
self.version_info = new.version_info.or(self.version_info); .show_engine_list_separator
assert_ne!(self.version_info, None); .or(self.ui.show_engine_list_separator);
assert_ne!(self.ui.show_engine_list_separator, None);
self.ui.show_version_info = new.ui.show_version_info.or(self.ui.show_version_info);
assert_ne!(self.ui.show_version_info, None);
for (key, new) in new.engines.map { for (key, new) in new.engines.map {
if let Some(existing) = self.engines.map.get_mut(&key) { if let Some(existing) = self.engines.map.get_mut(&key) {
existing.update(new); existing.update(new);
@ -53,12 +65,6 @@ impl Config {
} }
} }
#[derive(Deserialize, Debug)]
pub struct EnginesConfig {
#[serde(flatten)]
pub map: HashMap<Engine, DefaultableEngineConfig>,
}
static DEFAULT_ENABLED_FULL_ENGINE_CONFIG: Lazy<FullEngineConfig> = static DEFAULT_ENABLED_FULL_ENGINE_CONFIG: Lazy<FullEngineConfig> =
Lazy::new(FullEngineConfig::default); Lazy::new(FullEngineConfig::default);
static DEFAULT_DISABLED_FULL_ENGINE_CONFIG: Lazy<FullEngineConfig> = static DEFAULT_DISABLED_FULL_ENGINE_CONFIG: Lazy<FullEngineConfig> =

View File

@ -1,3 +1,5 @@
use std::path::Path;
use config::Config; use config::Config;
use tracing::error; use tracing::error;
@ -11,7 +13,10 @@ pub mod web;
async fn main() { async fn main() {
tracing_subscriber::fmt::init(); tracing_subscriber::fmt::init();
let config = match Config::read_or_create() { let config_path = std::env::args().nth(1).unwrap_or("config.toml".into());
let config_path = Path::new(&config_path);
let config = match Config::read_or_create(config_path) {
Ok(config) => config, Ok(config) => config,
Err(err) => { Err(err) => {
error!("Couldn't parse config:\n{err}"); error!("Couldn't parse config:\n{err}");

View File

@ -33,7 +33,7 @@ pub async fn index(State(config): State<Arc<Config>>) -> impl IntoResponse {
input type="submit" value="Search"; input type="submit" value="Search";
} }
} }
@if config.version_info.unwrap() { @if config.ui.show_version_info.unwrap() {
span."version-info" { span."version-info" {
@if COMMIT_HASH == "unknown" || COMMIT_HASH_SHORT == "unknown" { @if COMMIT_HASH == "unknown" || COMMIT_HASH_SHORT == "unknown" {
"Version " "Version "

View File

@ -55,26 +55,17 @@ fn render_end_of_html() -> String {
fn render_engine_list(engines: &[engines::Engine], config: &Config) -> PreEscaped<String> { fn render_engine_list(engines: &[engines::Engine], config: &Config) -> PreEscaped<String> {
let mut html = String::new(); let mut html = String::new();
let mut first_iter = true; for (i, engine) in engines.iter().enumerate() {
for engine in engines { if config.ui.show_engine_list_separator.unwrap() && i > 0 {
if config.engine_list_separator.unwrap() && !first_iter {
html.push_str(" &middot; "); html.push_str(" &middot; ");
} }
first_iter = false;
let raw_engine_id = &engine.id(); let raw_engine_id = &engine.id();
let engine_id = if config.engine_list_separator.unwrap() { let engine_id = if config.ui.show_engine_list_separator.unwrap() {
raw_engine_id.replace('_', " ") raw_engine_id.replace('_', " ")
} else { } else {
raw_engine_id.to_string() raw_engine_id.to_string()
}; };
html.push_str( html.push_str(&html! { span."engine-list-item" { (engine_id) } }.into_string())
&html! {
span."engine-list-item" {
(engine_id)
}
}
.into_string(),
)
} }
html! { html! {
div."engine-list" { div."engine-list" {