summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNaz <ndpm13@ch-naseem.com>2025-10-11 14:44:12 +0100
committerNaz <ndpm13@ch-naseem.com>2025-10-12 09:54:00 +0100
commitbbce03f95d82d5373f2b6a1c28b03eb25d7bb94c (patch)
tree7439ed8038bbb9a08a6b56fbfb90e8bea4b9f2ea
parent50cf5960cb1f0af831e28eb08b15b97794287f87 (diff)
✨feat: add flags to override values in config file
-rw-r--r--src/args.rs23
-rw-r--r--src/config.rs60
-rw-r--r--src/errors.rs8
-rw-r--r--src/lib.rs6
4 files changed, 79 insertions, 18 deletions
diff --git a/src/args.rs b/src/args.rs
index 415d816..6998e15 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -1,4 +1,4 @@
-use clap::{Parser, Subcommand};
+use clap::{Args, Parser, Subcommand};
/// Simple bookmarks manager written in Rust
#[derive(Debug, Parser)]
@@ -12,5 +12,24 @@ pub struct Cli {
pub enum Command {
/// Start the web server to serve the bookmarks page
#[command(name = "serv")]
- Serv,
+ Serv(ServArgs),
+}
+
+#[derive(Debug, Args)]
+pub struct ServArgs {
+ // Port to listen to
+ #[arg(long = "port", short)]
+ pub port: Option<String>,
+
+ // Path to theme file
+ #[arg(long = "style", short)]
+ pub style_file: Option<String>,
+
+ // Path to bookmarks file
+ #[arg(long = "bookmarks", short)]
+ pub bookmarks_file: Option<String>,
+
+ // Path to favicon file
+ #[arg(long = "favicon", short)]
+ pub favicon_file: Option<String>,
}
diff --git a/src/config.rs b/src/config.rs
index 6345ffa..2f1bbb7 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -2,7 +2,7 @@ use std::path::PathBuf;
use serde::{Deserialize, Serialize};
-use crate::{Error, Result};
+use crate::{Error, Result, args::ServArgs};
const STYLE: &str = include_str!("../examples/simple-gruvbox.css");
const BOOKMARKS: &str = include_str!("../examples/bookmarks.json");
@@ -17,22 +17,20 @@ pub struct Config {
}
impl Config {
- pub fn new() -> Result<Config> {
- let config_home = if let Ok(xdg_config_home) = std::env::var("XDG_CONFIG_HOME") {
- PathBuf::from(xdg_config_home).join("sbm-rs")
- } else if let Ok(home) = std::env::var("HOME") {
- PathBuf::from(home).join(".config/sbm-rs")
+ pub fn new(args: ServArgs) -> Result<Config> {
+ let config_home = Config::get_config_home()?;
+
+ let config_path = &config_home.join("config.toml");
+
+ let mut config = if config_path.exists() {
+ Config::load_config(config_path)?
} else {
- return Err(Error::ConfigNotFound);
+ Config::generate_defaults(config_home)?
};
- let config = &config_home.join("config.toml");
+ config.override_with_serv_args(args)?;
- if config.exists() {
- Config::load_config(config)
- } else {
- Config::generate_defaults(config_home)
- }
+ Ok(config)
}
pub fn load_config(config: &PathBuf) -> Result<Config> {
let config = std::fs::read_to_string(&config)?;
@@ -65,4 +63,40 @@ impl Config {
Ok(config)
}
+ pub fn override_with_serv_args(&mut self, args: ServArgs) -> Result<()> {
+ if let Some(port) = &args.port {
+ self.port = port.parse::<u16>()?;
+ }
+
+ if let Some(style_file) = &args.style_file {
+ if PathBuf::from(style_file).exists() {
+ self.style_file = PathBuf::from(style_file)
+ }
+ }
+
+ if let Some(bookmarks_file) = &args.bookmarks_file {
+ if PathBuf::from(bookmarks_file).exists() {
+ self.bookmarks_file = PathBuf::from(bookmarks_file)
+ }
+ }
+
+ if let Some(favicon_file) = &args.favicon_file {
+ if PathBuf::from(favicon_file).exists() {
+ self.favicon_file = PathBuf::from(favicon_file)
+ }
+ }
+
+ Ok(())
+ }
+ fn get_config_home() -> Result<PathBuf> {
+ let config_home = if let Ok(xdg_config_home) = std::env::var("XDG_CONFIG_HOME") {
+ PathBuf::from(xdg_config_home).join("sbm-rs")
+ } else if let Ok(home) = std::env::var("HOME") {
+ PathBuf::from(home).join(".config/sbm-rs")
+ } else {
+ return Err(Error::ConfigHomeNotFound);
+ };
+
+ Ok(config_home)
+ }
}
diff --git a/src/errors.rs b/src/errors.rs
index 251ee5f..6b53c2d 100644
--- a/src/errors.rs
+++ b/src/errors.rs
@@ -28,6 +28,9 @@ pub enum Error {
#[from]
TomlSerError(toml::ser::Error),
+
+ #[from]
+ ParseIntError(std::num::ParseIntError),
}
impl core::fmt::Display for Error {
@@ -44,6 +47,7 @@ impl core::fmt::Display for Error {
Error::SerdeError(e) => write!(fmt, "Serde error: {e}"),
Error::TomlDeError(e) => write!(fmt, "TOML deserialization error: {e}"),
Error::TomlSerError(e) => write!(fmt, "TOML serialization error: {e}"),
+ Error::ParseIntError(e) => write!(fmt, "Parsing error: {e}"),
}
}
}
@@ -80,6 +84,10 @@ impl IntoResponse for Error {
StatusCode::INTERNAL_SERVER_ERROR,
format!("TOML serialization error: {e}"),
),
+ Error::ParseIntError(ref e) => (
+ StatusCode::INTERNAL_SERVER_ERROR,
+ format!("Parsing error: {e}"),
+ ),
};
println!("{} {}", &status, &error_message);
diff --git a/src/lib.rs b/src/lib.rs
index 515f7c1..f65e4d4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -27,10 +27,10 @@ pub fn app(config: Config) -> Router {
pub async fn run() -> Result<()> {
let args = Cli::parse();
- let config = config::Config::new()?;
-
match args.command {
- Command::Serv => {
+ Command::Serv(args) => {
+ let config = config::Config::new(args)?;
+
let socket = SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), config.port);
let listener = TcpListener::bind(socket).await?;