diff --git a/docs/examples/config.yaml b/docs/examples/config.yaml index 383d892..c71b8d2 100644 --- a/docs/examples/config.yaml +++ b/docs/examples/config.yaml @@ -11,9 +11,11 @@ reddit: - read - vote - subscribe + # - save # add this scope to use "Save post" in the action menu redirect_uri: "http://127.0.0.1:65010/reddix/callback" ui: theme: default + # initial_subreddit: apple # optional: open with this subreddit selected (same as -r apple) media: cache_dir: null max_size_bytes: 524288000 diff --git a/src/app.rs b/src/app.rs index ea01871..7a56c7a 100644 --- a/src/app.rs +++ b/src/app.rs @@ -12,9 +12,26 @@ use crate::storage; use crate::theme; use crate::ui; -pub fn run() -> Result<()> { - let cfg = config::load(config::LoadOptions::default()).context("load config")?; - let config_path = config::default_path(); +/// Options for the main run entry point (e.g. from CLI). +#[derive(Default)] +pub struct RunOptions { + /// If set, open with this subreddit selected (e.g. "apple" or "r/apple"). + pub initial_subreddit: Option, + /// If set, load config from this path instead of the default. + pub config_file: Option, +} + +pub fn run(options: Option) -> Result<()> { + let run_opts = options.unwrap_or_default(); + let load_opts = config::LoadOptions { + config_file: run_opts.config_file.clone(), + env_prefix: None, + }; + let cfg = config::load(load_opts).context("load config")?; + let config_path = run_opts + .config_file + .clone() + .or_else(config::default_path); let display_path = friendly_path(config_path.as_ref()); ui::configure_terminal_cell_metrics_override(cfg.ui.cell_width, cfg.ui.cell_height); @@ -157,6 +174,9 @@ pub fn run() -> Result<()> { session_manager: session_manager.clone(), fetch_subreddits_on_start, theme: theme::palette_for(theme), + initial_subreddit: run_opts + .initial_subreddit + .or_else(|| cfg.ui.initial_subreddit.clone()), }; let mut model = ui::Model::new(options); diff --git a/src/config.rs b/src/config.rs index 8c46a0c..3bac83f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -74,6 +74,9 @@ pub struct UIConfig { pub cell_width: Option, #[serde(default)] pub cell_height: Option, + /// If set, open with this subreddit selected (same as -r/--subreddit). + #[serde(default)] + pub initial_subreddit: Option, } impl Default for UIConfig { @@ -82,6 +85,7 @@ impl Default for UIConfig { theme: default_theme(), cell_width: None, cell_height: None, + initial_subreddit: None, } } } @@ -222,6 +226,9 @@ fn merge_config(mut base: Config, other: Config) -> Config { if other.ui.cell_height.is_some() { base.ui.cell_height = other.ui.cell_height; } + if other.ui.initial_subreddit.is_some() { + base.ui.initial_subreddit = other.ui.initial_subreddit; + } if other.media.cache_dir.is_some() { base.media.cache_dir = other.media.cache_dir; @@ -293,6 +300,7 @@ fn apply_env_value(cfg: &mut Config, key: &str, value: String) { cfg.ui.cell_height = Some(parsed); } } + "ui.initial_subreddit" => cfg.ui.initial_subreddit = Some(value), "media.cache_dir" => cfg.media.cache_dir = Some(PathBuf::from(value)), "media.max_size_bytes" => { if let Ok(parsed) = value.parse::() { diff --git a/src/lib.rs b/src/lib.rs index b4de8e5..cf5d481 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,4 +17,4 @@ pub mod video; pub const VERSION: &str = env!("CARGO_PKG_VERSION"); -pub use app::run; +pub use app::{run, RunOptions}; diff --git a/src/main.rs b/src/main.rs index a4500b8..9c04793 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,39 +1,63 @@ fn main() { - if handle_cli_flags() { - return; - } - - if let Err(err) = reddix::run() { - eprintln!("error: {err:?}"); - std::process::exit(1); - } -} - -fn handle_cli_flags() -> bool { - let mut saw_flag = false; - for arg in std::env::args().skip(1) { - match arg.as_str() { + let args: Vec = std::env::args().collect(); + let mut initial_subreddit: Option = None; + let mut config_file: Option = None; + let mut i = 1; + while i < args.len() { + match args[i].as_str() { "--version" | "-V" => { println!("Reddix {}", reddix::VERSION); - saw_flag = true; + return; } "--help" | "-h" => { println!( - "Reddix — Reddit, refined for the terminal.\n\n --version, -V Show version and exit\n --help, -h Show this help message\n --check-updates Check for updates and exit" + "Reddix — Reddit, refined for the terminal.\n\n --version, -V Show version and exit\n --help, -h Show this help message\n -r, --subreddit NAME Open with this subreddit selected (e.g. -r apple)\n --config PATH Use config file at PATH\n --check-updates Check for updates and exit" ); - saw_flag = true; + return; + } + "--config" => { + i += 1; + if i < args.len() && !args[i].starts_with('-') { + config_file = Some(std::path::PathBuf::from(&args[i])); + } + i += 1; + continue; + } + "-r" | "--subreddit" => { + i += 1; + if i < args.len() && !args[i].starts_with('-') { + initial_subreddit = Some(args[i].clone()); + } + i += 1; + continue; } "--check-updates" => { - saw_flag = true; if let Err(err) = check_updates_once() { eprintln!("Update check failed: {err:?}"); std::process::exit(1); } + return; + } + _ => { + i += 1; } - _ => {} } } - saw_flag + + let run_opts = if initial_subreddit.is_some() || config_file.is_some() { + Some(reddix::RunOptions { + initial_subreddit, + config_file, + ..Default::default() + }) + } else { + None + }; + + if let Err(err) = reddix::run(run_opts) { + eprintln!("error: {err:?}"); + std::process::exit(1); + } } fn check_updates_once() -> anyhow::Result<()> { diff --git a/src/ui.rs b/src/ui.rs index d76f79a..ee8ba5b 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -3517,6 +3517,8 @@ pub struct Options { pub session_manager: Option>, pub fetch_subreddits_on_start: bool, pub theme: crate::theme::Palette, + /// If set, open with this subreddit selected (e.g. "apple" or "r/apple"). + pub initial_subreddit: Option, } pub struct Model { @@ -4577,6 +4579,21 @@ impl Model { .iter() .position(|name| name.eq_ignore_ascii_case("r/frontpage")) .unwrap_or(0); + if let Some(ref name) = opts.initial_subreddit { + let normalized = normalize_subreddit_name(name); + if normalized != "r/frontpage" { + if let Some(idx) = model + .subreddits + .iter() + .position(|s| s.eq_ignore_ascii_case(&normalized)) + { + model.selected_sub = idx; + } else { + model.subreddits.push(normalized); + model.selected_sub = model.subreddits.len().saturating_sub(1); + } + } + } model.selected_post = 0; model.selected_comment = 0; model.post_offset.set(0);