Add config and service subcommands
config subcommand — show, path, edit ($EDITOR), and a non-interactive set that takes --prefix / --compat-dir / --gameid. Lets users retarget the Wine prefix without hand-editing TOML. service subcommand — install / uninstall / status for a systemd --user unit that autostarts the tray. install writes ~/.config/systemd/user/ battlenet-manager.service with ExecStart pointing at the current binary, then daemon-reloads and enable --now's the unit. uninstall tears it back down. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+54
-1
@@ -36,12 +36,65 @@ fn home_dir() -> PathBuf {
|
||||
}
|
||||
|
||||
impl Config {
|
||||
fn config_path() -> Result<PathBuf> {
|
||||
pub fn config_path() -> Result<PathBuf> {
|
||||
let dirs = ProjectDirs::from("co.aleshym", "", "battlenet-manager")
|
||||
.context("Could not determine config directory")?;
|
||||
Ok(dirs.config_dir().join("config.toml"))
|
||||
}
|
||||
|
||||
/// Print the config path followed by the serialised current config.
|
||||
pub fn show(&self) -> Result<()> {
|
||||
let path = Self::config_path()?;
|
||||
println!("# {}", path.display());
|
||||
let s = toml::to_string_pretty(self)?;
|
||||
print!("{s}");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Open the config file in $EDITOR (falling back to nano).
|
||||
/// Ensures the file exists first so the editor isn't launched on nothing.
|
||||
pub fn edit() -> Result<()> {
|
||||
let _ = Self::load()?; // writes defaults if missing
|
||||
let path = Self::config_path()?;
|
||||
let editor = std::env::var("EDITOR")
|
||||
.or_else(|_| std::env::var("VISUAL"))
|
||||
.unwrap_or_else(|_| "nano".into());
|
||||
let status = std::process::Command::new(&editor)
|
||||
.arg(&path)
|
||||
.status()
|
||||
.with_context(|| format!("Failed to spawn editor '{editor}'"))?;
|
||||
if !status.success() {
|
||||
anyhow::bail!("Editor '{editor}' exited non-zero");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Update individual fields non-interactively, then save.
|
||||
pub fn set_fields(
|
||||
&mut self,
|
||||
prefix: Option<PathBuf>,
|
||||
compat_dir: Option<PathBuf>,
|
||||
gameid: Option<String>,
|
||||
) -> Result<()> {
|
||||
if prefix.is_none() && compat_dir.is_none() && gameid.is_none() {
|
||||
anyhow::bail!("nothing to set — pass at least one of --prefix / --compat-dir / --gameid");
|
||||
}
|
||||
if let Some(p) = prefix {
|
||||
self.prefix_dir = p;
|
||||
}
|
||||
if let Some(p) = compat_dir {
|
||||
self.proton_compat_dir = p;
|
||||
}
|
||||
if let Some(g) = gameid {
|
||||
self.gameid = g;
|
||||
}
|
||||
self.save()?;
|
||||
println!("\x1b[1;32m✓\x1b[0m Config saved.");
|
||||
println!();
|
||||
self.show()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Load config from disk, creating a default one if it doesn't exist.
|
||||
pub fn load() -> Result<Self> {
|
||||
let path = Self::config_path()?;
|
||||
|
||||
Reference in New Issue
Block a user