Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ Configuration files are located in the application's configuration directory, wh
A sample `app.toml` is available at [examples/app.toml](../examples/app.toml).

`spotify_player` uses `app.toml` for application settings. Available options:
`spotify_player` also supports cli config overriding using -o / --config-override flag. Example:

```bash
spotify_player -o device.volume=80 -o theme=dracula
```

| Option | Description | Default |
| --------------------------------- | ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
Expand Down
8 changes: 8 additions & 0 deletions spotify_player/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,14 @@ pub fn init_cli() -> anyhow::Result<clap::Command> {
.value_name("FOLDER")
.default_value(default_cache_folder.into_os_string())
.help("Path to the application's cache folder"),
)
.arg(
clap::Arg::new("config-override")
.short('o')
.long("config-override")
.value_name("KEY=VALUE")
.action(clap::ArgAction::Append)
.help("Override a config option (e.g. -o device.volume=80 -o theme=dracula)"),
);

#[cfg(feature = "daemon")]
Expand Down
34 changes: 34 additions & 0 deletions spotify_player/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use std::{
sync::OnceLock,
};

use anyhow::Context;
use keymap::KeymapConfig;
use theme::ThemeConfig;

Expand Down Expand Up @@ -517,3 +518,36 @@ pub fn set_config(configs: Configs) {
.set(configs)
.expect("configs should be initialized only once");
}

// Apply a CLI config override to the application config.
// Serializes the config to TOML, navigates to the key via dot-notation,
// overrides the value, and deserializes back into AppConfig.
// Returns an error if the key path is invalid or the value type mismatches.
pub fn apply_config_override(config: &mut AppConfig, key: &str, value: &str) -> anyhow::Result<()> {
let mut config_value = toml::Value::try_from(&*config)?;

let parts: Vec<&str> = key.split('.').collect();
let mut current = &mut config_value;

for (i, part) in parts.iter().enumerate() {
if i == parts.len() - 1 {
let table = current
.as_table_mut()
.context(format!("'{key}' is not a valid config path"))?;

let parsed_value: toml::Value = value
.parse()
.unwrap_or_else(|_| toml::Value::String(value.to_string()));

table.insert(part.to_string(), parsed_value);
} else {
current = current
.get_mut(part)
.context(format!("Config key '{part}' not found in path '{key}'"))?;
}
}

*config = config_value.try_into()?;

Ok(())
}
13 changes: 10 additions & 3 deletions spotify_player/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ use std::{collections::VecDeque, io::Write, sync::Arc};
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;

use crate::config::apply_config_override;

fn init_spotify(
client_pub: &flume::Sender<client::ClientRequest>,
client: &client::AppClient,
Expand Down Expand Up @@ -270,9 +272,14 @@ fn main() -> Result<()> {
// set the log folder to be the cache folder if it is not set
configs.app_config.log_folder = Some(cache_folder);
}
if let Some(theme) = args.get_one::<String>("theme") {
// override the theme config if user specifies a `theme` cli argument
theme.clone_into(&mut configs.app_config.theme);
if let Some(overrides) = args.get_many::<String>("config-override") {
for override_str in overrides {
let (key, value) = override_str.split_once('=').context(format!(
"Invalid override format: '{override_str}'. Expected KEY=VALUE"
))?;

apply_config_override(&mut configs.app_config, key, value)?;
}
}
config::set_config(configs);
}
Expand Down
Loading