harmont_cli/context.rs
1use std::io::IsTerminal;
2
3use anyhow::{Context, Result};
4
5use crate::cli::Cli;
6use crate::config::Config;
7use hm_render::OutputMode;
8
9/// Runtime context that bundles resolved config and output preferences.
10///
11/// After the plan-4 cloud-plugin cutover this is intentionally thin:
12/// API client, credential store, and active-org resolution moved into
13/// `hm-plugin-cloud`. The host context retains the config file (for
14/// future use) and the output mode.
15#[derive(Debug)]
16pub struct RunContext {
17 pub config: Config,
18 /// Output mode for the residual built-in verbs (the legacy global
19 /// `--format` flag was retired in plan 3; per-subcommand `--format`
20 /// is the only currently-wired source, so this defaults to human).
21 pub output: OutputMode,
22}
23
24impl RunContext {
25 /// Build a [`RunContext`] from parsed CLI args.
26 ///
27 /// # Errors
28 ///
29 /// Returns an error if the config file is unreadable or malformed.
30 pub fn from_cli(cli: &Cli) -> Result<Self> {
31 let start_dir = std::env::current_dir().context("cannot determine current directory")?;
32 let project_root = hm_util::dirs::find_project_root(&start_dir);
33 let config = Config::load(project_root.as_deref())?;
34
35 let output = OutputMode::Human {
36 // Single source of truth for the color/TTY rule (still honors --no-color).
37 color: hm_render::color_enabled(cli.no_color),
38 // Interactive prompts/spinners key off stdout being a TTY.
39 interactive: std::io::stdout().is_terminal(),
40 };
41
42 Ok(Self { config, output })
43 }
44}