use std::{io::IsTerminal, sync::OnceLock};
pub mod cli_args;
pub mod commands;
pub mod help;
pub mod render;
pub mod style;
pub mod tips;
pub mod transaction_sentinel;
#[cfg(feature = "client")]
pub use cli_args::PresenceCommands;
pub use cli_args::{
ActorCommands, AgentCommands, AttemptArgs, BisectCommands, CheckpointArgs, Cli, CloneArgs,
CollapseArgs, Commands, ContextCommands, DaemonCommands, DiagnoseArgs, DiffArgs, DoctorArgs,
DoctorCommands, DoctorDocsArgs, HookCommands, HookInstallSource, InitArgs, IntegrationCommands,
IntegrationInstallArgs, IntegrationRelayArgs, IntegrationTargetArgs, LogArgs,
MaintenanceCommands, MarkerCommands, MergeArgs, OutputMode, PullArgs, PurgeApplyArgs,
PurgeCommands, PurgeListArgs, PushArgs, ReadyArgs, RedactApplyArgs, RedactCommands,
RedactListArgs, RedactShowArgs, RedactTrustAddArgs, RedactTrustCommands, RedactTrustListArgs,
RedactTrustRemoveArgs, RemoteCommands, ResolveArgs, RetroArgs, RevertArgs, RunArgs,
SessionCommands, SessionEndArgs, SessionListArgs, SessionSegmentArgs, SessionShowArgs,
SessionStartArgs, SnapshotArgs, StashCommands, StoreCommands, ThreadAbsorbArgs,
ThreadCleanupArgs, ThreadCommands, ThreadDropArgs, ThreadListArgs, ThreadMoveArgs,
ThreadNameArgs, ThreadPromoteArgs, ThreadRenameArgs, ThreadResolveArgs, ThreadShowArgs,
ThreadStartArgs, TryArgs, UndoArgs, WatchArgs, WorkspaceCommands, WorkspaceModeArg,
WorkspaceShowArgs,
};
#[cfg(feature = "client")]
pub use cli_args::{AuthCommands, SupportCommands};
#[cfg(feature = "git-overlay")]
pub use cli_args::{BridgeCommands, GitCommands};
#[cfg(feature = "semantic")]
pub use cli_args::{HotEventKindArg, HotSpotKeyArg, SemanticCommands};
use repo::{Config, OutputFormat};
use crate::config::UserConfig;
pub fn is_tty() -> bool {
std::io::stdout().is_terminal()
}
pub fn load_user_config_or_exit() -> UserConfig {
UserConfig::load_default().unwrap_or_else(|err| {
eprintln!("failed to load Heddle user config: {err}");
std::process::exit(2);
})
}
pub fn should_output_json(cli: &Cli, config: Option<&Config>) -> bool {
let user_config = Some(load_user_config_or_exit());
let mut format = user_config
.as_ref()
.map(|cfg| cfg.output.format)
.or_else(|| config.map(|cfg| cfg.output.format))
.unwrap_or(OutputFormat::Auto);
if let Some(output) = cli.output {
format = match output {
OutputMode::Auto => OutputFormat::Auto,
OutputMode::Json => OutputFormat::Json,
OutputMode::Text => OutputFormat::Text,
};
}
if cli.json {
warn_json_deprecated_once();
format = OutputFormat::Json;
}
match format {
OutputFormat::Json => true,
OutputFormat::Text => false,
OutputFormat::Auto => !is_tty(),
}
}
impl weft_client_shim::CliContext for Cli {
fn repo_path(&self) -> Option<&std::path::Path> {
self.repo.as_deref()
}
fn operation_id_wire(&self) -> String {
crate::operation_id::wire(self)
}
fn should_output_json(&self, repo_config: Option<&Config>) -> bool {
should_output_json(self, repo_config)
}
}
fn warn_json_deprecated_once() {
static WARNED: OnceLock<()> = OnceLock::new();
if WARNED.set(()).is_ok() {
eprintln!("warning: --json is deprecated; use --output json");
}
}
pub fn worktree_status_options(config: Option<&Config>) -> repo::WorktreeStatusOptions {
load_user_config_or_exit().worktree_status_options(config)
}