diff --git a/README.md b/README.md index 2219fd7..e51bfb7 100644 --- a/README.md +++ b/README.md @@ -103,13 +103,34 @@ Press `/` to enter search mode. Type to filter the list incrementally. Press `En ## Configuration -prism-tui reads its configuration from PrismLauncher's data directory: +### PrismLauncher Data Directory -- **Linux**: `~/.local/share/PrismLauncher/` +prism-tui automatically detects your PrismLauncher data directory: + +- **Linux**: `~/.local/share/PrismLauncher/` or Flatpak location - **macOS**: `~/Library/Application Support/PrismLauncher/` - **Windows**: `%APPDATA%/PrismLauncher/` -No additional configuration is required. +For custom or portable installations, you can override the data directory in two ways (checked in this order): + +1. **Environment variable**: `PRISMLAUNCHER_DATA=/path/to/data prism-tui` +2. **Config file**: Set `data_dir` in the config (see below) + +### Config File + +prism-tui stores its settings in a TOML config file: + +- **Linux**: `~/.config/prism-tui/config.toml` +- **macOS**: `~/Library/Application Support/prism-tui/config.toml` +- **Windows**: `%APPDATA%\prism-tui\config.toml` + +```toml +default_sort = "Last Played" +sort_ascending = true +data_dir = "~/Games/PrismLauncher" # optional, overrides auto-detection +``` + +Sort and sort-direction preferences are saved automatically. The `data_dir` option supports `~` tilde expansion. ## Architecture diff --git a/src/app.rs b/src/app.rs index 66abd0b..7f66480 100644 --- a/src/app.rs +++ b/src/app.rs @@ -203,7 +203,7 @@ pub struct App { } impl App { - pub fn new(config: PrismConfig) -> Result { + pub fn new(config: PrismConfig, app_config: AppConfig) -> Result { use crate::data::{load_accounts, load_groups, load_instances}; let instances_dir = config.instances_dir(); @@ -213,8 +213,6 @@ impl App { let active_account = accounts.iter().find(|a| a.is_active).cloned(); - let app_config = AppConfig::load(); - let sort_mode = app_config.default_sort_mode(); let sort_ascending = app_config.sort_ascending; diff --git a/src/data/app_config.rs b/src/data/app_config.rs index 65391eb..ddca2c5 100644 --- a/src/data/app_config.rs +++ b/src/data/app_config.rs @@ -9,6 +9,8 @@ pub struct AppConfig { pub default_sort: String, #[serde(default = "default_true")] pub sort_ascending: bool, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub data_dir: Option, } fn default_true() -> bool { @@ -24,6 +26,7 @@ impl Default for AppConfig { Self { default_sort: default_sort(), sort_ascending: true, + data_dir: None, } } } @@ -65,6 +68,10 @@ impl AppConfig { } } + pub fn resolved_data_dir(&self) -> Option { + self.data_dir.as_ref().map(|p| expand_tilde(p)) + } + pub fn default_sort_mode(&self) -> SortMode { match self.default_sort.as_str() { "Name" => SortMode::Name, @@ -75,3 +82,17 @@ impl AppConfig { } } } + +fn expand_tilde(path: &str) -> PathBuf { + let rest = path.strip_prefix("~/").or_else(|| path.strip_prefix("~\\")); + if let Some(rest) = rest { + if let Some(home) = dirs::home_dir() { + return home.join(rest); + } + } else if path == "~" + && let Some(home) = dirs::home_dir() + { + return home; + } + PathBuf::from(path) +} diff --git a/src/data/config.rs b/src/data/config.rs index 78fb382..a6951e0 100644 --- a/src/data/config.rs +++ b/src/data/config.rs @@ -38,16 +38,31 @@ impl PrismConfig { } } -pub fn find_prism_data_dir() -> Result { - // Check environment variable first +pub fn find_prism_data_dir(config_data_dir: Option) -> Result { + // 1. Check environment variable first if let Ok(path) = env::var("PRISMLAUNCHER_DATA") { let path = PathBuf::from(path); if path.exists() { return Ok(path); } + return Err(PrismError::Config(format!( + "PRISMLAUNCHER_DATA directory does not exist: {}", + path.display() + ))); } - // Standard location + // 2. Config file data_dir + if let Some(path) = config_data_dir { + if path.exists() { + return Ok(path); + } + return Err(PrismError::Config(format!( + "Configured data_dir does not exist: {}", + path.display() + ))); + } + + // 3. Standard platform location if let Some(data_dir) = dirs::data_dir() { let standard = data_dir.join("PrismLauncher"); if standard.exists() { @@ -55,7 +70,7 @@ pub fn find_prism_data_dir() -> Result { } } - // Flatpak location (Linux only) + // 4. Flatpak location (Linux only) #[cfg(target_os = "linux")] { if let Some(home) = dirs::home_dir() { diff --git a/src/main.rs b/src/main.rs index e4ec5b9..a9bf142 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ mod view; use app::App; use color_eyre::Result; -use data::{PrismConfig, find_prism_data_dir}; +use data::{AppConfig, PrismConfig, find_prism_data_dir}; use message::Message; use std::time::Duration; use tui::{Event, EventStream, Terminal}; @@ -19,9 +19,10 @@ use tui::{Event, EventStream, Terminal}; async fn main() -> Result<()> { color_eyre::install()?; - let data_dir = find_prism_data_dir()?; + let app_config = AppConfig::load(); + let data_dir = find_prism_data_dir(app_config.resolved_data_dir())?; let config = PrismConfig::load(&data_dir)?; - let mut app = App::new(config)?; + let mut app = App::new(config, app_config)?; let mut terminal = Terminal::new()?; let mut events = EventStream::new(Duration::from_millis(250));