generated from GarandPLG/rust-flake-template
Add debug flag and config init support
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.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
/target
|
/target
|
||||||
/result
|
/result
|
||||||
|
/local-config
|
||||||
|
|
||||||
veil-rs.log
|
veil-rs.log
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ in
|
|||||||
passthru.updateScript = nix-update-script {};
|
passthru.updateScript = nix-update-script {};
|
||||||
|
|
||||||
# postInstall = ''
|
# postInstall = ''
|
||||||
# cp static files
|
# cp -r templates $out/bin
|
||||||
# '';
|
# '';
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
|
|||||||
@@ -45,11 +45,11 @@
|
|||||||
src = ./.;
|
src = ./.;
|
||||||
|
|
||||||
# buildInputs = with pkgs; [];
|
# buildInputs = with pkgs; [];
|
||||||
#
|
|
||||||
nativeBuildInputs = with pkgs; [pkg-config];
|
nativeBuildInputs = with pkgs; [pkg-config];
|
||||||
|
|
||||||
# postInstall = ''
|
# postInstall = ''
|
||||||
# cp static files
|
# cp -r templates $out/bin
|
||||||
# '';
|
# '';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,12 +16,21 @@ pub struct Cli {
|
|||||||
)]
|
)]
|
||||||
pub log: bool,
|
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)]
|
#[command(subcommand)]
|
||||||
pub command: Cmds,
|
pub command: Cmds,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Clone, Debug)]
|
#[derive(Subcommand, Clone, Debug)]
|
||||||
pub enum Cmds {
|
pub enum Cmds {
|
||||||
|
Init,
|
||||||
Sync,
|
Sync,
|
||||||
Add,
|
Add,
|
||||||
Rm,
|
Rm,
|
||||||
|
|||||||
@@ -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<VeilConfig> {
|
||||||
|
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<PathBuf> {
|
||||||
|
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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
pub mod loader;
|
||||||
|
pub mod schema;
|
||||||
|
|
||||||
|
pub use loader::VeilFile;
|
||||||
|
pub use schema::{AppConfig, VeilConfig, WindowConfig};
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||||
|
pub struct VeilConfig {
|
||||||
|
pub apps: Vec<AppConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VeilConfig {
|
||||||
|
pub fn new(apps: Vec<AppConfig>) -> 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
pub mod cli;
|
pub mod cli;
|
||||||
|
pub mod config;
|
||||||
pub mod logs;
|
pub mod logs;
|
||||||
|
|||||||
+12
-3
@@ -1,8 +1,17 @@
|
|||||||
use std::io::Result;
|
use std::io::Result;
|
||||||
use veil_rs::cli::Cli;
|
use veil_rs::{
|
||||||
|
cli::{Cli, Cmds},
|
||||||
|
config::VeilFile,
|
||||||
|
};
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
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(()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
Reference in New Issue
Block a user