From 3813eaabb360eba1b8983222c9c142f3d7b88276 Mon Sep 17 00:00:00 2001 From: GarandPLG Date: Sat, 6 Jun 2026 11:53:22 +0200 Subject: [PATCH] Add debug flag and config init support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a `--debug` option and an `Init` subcommand to the CLI. Add a new `config` module with loader and schema types for reading and creating a default `veil.yaml` (supporting a local debug config path). Update `.gitignore`, `default.nix`, and `flake.nix` comments to reference the templates directory. Provide an example configuration template and integrate it into the application’s entry point. --- .gitignore | 1 + default.nix | 2 +- flake.nix | 4 +- src/cli.rs | 9 ++++ src/config/loader.rs | 91 +++++++++++++++++++++++++++++++++++++ src/config/mod.rs | 5 ++ src/config/schema.rs | 91 +++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/main.rs | 15 ++++-- templates/example.veil.yaml | 14 ++++++ 10 files changed, 227 insertions(+), 6 deletions(-) create mode 100644 src/config/loader.rs create mode 100644 src/config/mod.rs create mode 100644 src/config/schema.rs create mode 100644 templates/example.veil.yaml diff --git a/.gitignore b/.gitignore index 88883ee..d015847 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /target /result +/local-config veil-rs.log diff --git a/default.nix b/default.nix index c82e70b..a191f90 100644 --- a/default.nix +++ b/default.nix @@ -33,7 +33,7 @@ in passthru.updateScript = nix-update-script {}; # postInstall = '' - # cp static files + # cp -r templates $out/bin # ''; meta = { diff --git a/flake.nix b/flake.nix index 3ce5bfa..8465750 100644 --- a/flake.nix +++ b/flake.nix @@ -45,11 +45,11 @@ src = ./.; # buildInputs = with pkgs; []; - # + nativeBuildInputs = with pkgs; [pkg-config]; # postInstall = '' - # cp static files + # cp -r templates $out/bin # ''; }; }; diff --git a/src/cli.rs b/src/cli.rs index 5de556c..614fbc4 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -16,12 +16,21 @@ pub struct Cli { )] pub log: bool, + #[arg( + long, + short = 'd', + help = "Run in debug mode – look for config in ./local-config/veil.yaml", + default_value_t = false + )] + pub debug: bool, + #[command(subcommand)] pub command: Cmds, } #[derive(Subcommand, Clone, Debug)] pub enum Cmds { + Init, Sync, Add, Rm, diff --git a/src/config/loader.rs b/src/config/loader.rs new file mode 100644 index 0000000..9f98adf --- /dev/null +++ b/src/config/loader.rs @@ -0,0 +1,91 @@ +use crate::config::VeilConfig; +use anyhow::{Context, Result as AnyhowResult}; +use std::{ + fs::{File, create_dir_all, read_to_string}, + io::{Error, ErrorKind, Result, Write}, + path::{Path, PathBuf}, +}; + +pub struct VeilFile; + +impl VeilFile { + /// Load a config from an explicit `path`. + pub fn load(path: &Path) -> AnyhowResult { + let content: String = read_to_string(path) + .with_context(|| format!("Cannot read config: {}", path.display()))?; + + serde_yaml::from_str(&content).with_context(|| "Failed to parse veil.yaml") + } + + /// Find the default configuration file. + /// + /// * If `debug` is true → tries `./local-config/veil.yaml`. + /// * Otherwise → looks inside `$XDG_CONFIG_HOME/veil/` (or `$HOME/.config/veil/`). + /// * The three accepted names are: `veil.yaml`, `.veil.yaml`, `veil.yml`. + /// + /// Returns `Some(PathBuf)` when a file is found, otherwise `None`. + pub fn find_default(debug: bool) -> Option { + if debug { + let debug_path: &Path = Path::new("./local-config/veil.yaml"); + if debug_path.exists() { + return Some(debug_path.to_path_buf()); + } + } + + let candidates: [&str; 3] = ["veil.yaml", ".veil.yaml", "veil.yml"]; + + if let Some(base) = dirs::config_dir() { + let veil_dir: PathBuf = base.join("veil"); + for name in &candidates { + let candidate: PathBuf = veil_dir.join(name); + if candidate.exists() { + return Some(candidate); + } + } + } + + None + } + + /// Create a default configuration file based on the bundled example template. + /// + /// * `debug` – if `true` we use the debug location (`./local-config/veil.yaml`); + /// otherwise we use the XDG config directory (`$XDG_CONFIG_HOME/veil/veil.yaml`). + pub fn init_config(debug: bool) -> Result<()> { + let dest_dir: PathBuf = if debug { + PathBuf::from("./local-config") + } else { + let base: PathBuf = dirs::config_dir().ok_or_else(|| { + Error::new(ErrorKind::NotFound, "Unable to locate XDG config directory") + })?; + base.join("veil") + }; + + create_dir_all(&dest_dir)?; + + let dest_file: PathBuf = dest_dir.join("veil.yaml"); + + if dest_file.exists() { + println!("⚙️ Config already exists at {}", dest_file.display()); + return Ok(()); + } + + let template_path: PathBuf = Path::new(env!("CARGO_MANIFEST_DIR")) + .join("templates") + .join("example.veil.yaml"); + + let template: String = read_to_string(&template_path).map_err(|e| { + Error::new( + e.kind(), + format!("Failed to read template {}: {}", template_path.display(), e), + ) + })?; + + let mut file: File = File::create(&dest_file)?; + file.write_all(template.as_bytes())?; + file.flush()?; + + println!("✅ Created new config at {}", dest_file.display()); + Ok(()) + } +} diff --git a/src/config/mod.rs b/src/config/mod.rs new file mode 100644 index 0000000..a96003a --- /dev/null +++ b/src/config/mod.rs @@ -0,0 +1,5 @@ +pub mod loader; +pub mod schema; + +pub use loader::VeilFile; +pub use schema::{AppConfig, VeilConfig, WindowConfig}; diff --git a/src/config/schema.rs b/src/config/schema.rs new file mode 100644 index 0000000..49ed73e --- /dev/null +++ b/src/config/schema.rs @@ -0,0 +1,91 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct VeilConfig { + pub apps: Vec, +} + +impl VeilConfig { + pub fn new(apps: Vec) -> Self { + Self { apps } + } +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct AppConfig { + pub id: String, + pub name: String, + pub title: String, + pub url: String, + pub icon: String, + #[serde(default)] + pub window: WindowConfig, +} + +impl AppConfig { + pub fn new( + id: String, + name: String, + url: String, + title: String, + icon: String, + window: WindowConfig, + ) -> Self { + Self { + id, + name, + title, + url, + icon, + window, + } + } +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +#[serde(default)] +pub struct WindowConfig { + pub width: u32, + pub height: u32, + pub resizable: bool, + pub fullscreen: bool, + pub decorations: bool, + pub always_on_top: bool, + pub center: bool, +} + +impl WindowConfig { + pub fn new( + width: u32, + height: u32, + resizable: bool, + fullscreen: bool, + decorations: bool, + always_on_top: bool, + center: bool, + ) -> Self { + Self { + width, + height, + resizable, + fullscreen, + decorations, + always_on_top, + center, + } + } +} + +impl Default for WindowConfig { + fn default() -> Self { + Self { + width: 1280, + height: 800, + resizable: true, + fullscreen: false, + decorations: true, + always_on_top: false, + center: true, + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 6513bb9..3ed86b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,3 @@ pub mod cli; +pub mod config; pub mod logs; diff --git a/src/main.rs b/src/main.rs index e173217..f2c693c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,17 @@ use std::io::Result; -use veil_rs::cli::Cli; +use veil_rs::{ + cli::{Cli, Cmds}, + config::VeilFile, +}; fn main() -> Result<()> { - let _args: Cli = Cli::get_args(); + let args: Cli = Cli::get_args(); - Ok(()) + match args.command { + Cmds::Init => VeilFile::init_config(args.debug), + Cmds::Sync => Ok(()), + Cmds::Add => Ok(()), + Cmds::Rm => Ok(()), + Cmds::Ls => Ok(()), + } } diff --git a/templates/example.veil.yaml b/templates/example.veil.yaml new file mode 100644 index 0000000..bc5d300 --- /dev/null +++ b/templates/example.veil.yaml @@ -0,0 +1,14 @@ +apps: + - id: com.veil.jellyfin + name: jellyfin + title: Jellyfin + url: https://jellyfin.example.com + icon: https://jellyfin.example.com/favicon.ico + window: + width: 1280 + height: 800 + resizable: true + fullscreen: false + decorations: true + always_on_top: false + center: true