From 9d142ee7046a415bb764f626e61476ed349c98ca Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Tue, 10 Feb 2026 12:51:45 +0000 Subject: feat: add global CLI flags for non-interactive mode Add --defaults, --interactive, and --force flags to support non-interactive operation. Non-interactive mode is now the default behavior, with interactive mode enabled via the -i/--interactive flag. Also add CliError handling in main() to support styled error output from subcommands. --- src/bin/ngit/cli.rs | 12 ++++++++++++ src/bin/ngit/main.rs | 26 ++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/bin/ngit/cli.rs b/src/bin/ngit/cli.rs index 76874c3..d2246d7 100644 --- a/src/bin/ngit/cli.rs +++ b/src/bin/ngit/cli.rs @@ -11,6 +11,7 @@ use crate::sub_commands; help_template = "{name} {version}\nnostr plugin for git\n - clone a nostr repository, or add as a remote, by using the url format nostr://pub123/identifier\n - remote branches beginning with `pr/` are open PRs from contributors; `ngit list` can be used to view all PRs\n - to open a PR, push a branch with the prefix `pr/` or use `ngit send` for advanced options\n- publish a repository to nostr with `ngit init`\n\n{usage}\n{all-args}" )] #[command(propagate_version = true)] +#[allow(clippy::struct_excessive_bools)] pub struct Cli { #[command(subcommand)] pub command: Option, @@ -32,6 +33,15 @@ pub struct Cli { /// show customization options via git config #[arg(short, long, global = true)] pub customize: bool, + /// Use default values without prompting (non-interactive mode) + #[arg(short = 'd', long, global = true, conflicts_with = "interactive")] + pub defaults: bool, + /// Enable interactive prompts (default behavior) + #[arg(short = 'i', long, global = true)] + pub interactive: bool, + /// Force operations, bypass safety guards + #[arg(short = 'f', long, global = true)] + pub force: bool, } pub const CUSTOMISE_TEMPLATE: &str = r" @@ -111,6 +121,8 @@ pub enum AccountCommands { Logout, /// export nostr keys to login to other nostr clients ExportKeys, + /// create a new nostr account + Create(sub_commands::create::SubCommandArgs), } #[derive(clap::Parser)] diff --git a/src/bin/ngit/main.rs b/src/bin/ngit/main.rs index 71b6e85..5d29b02 100644 --- a/src/bin/ngit/main.rs +++ b/src/bin/ngit/main.rs @@ -2,13 +2,13 @@ #![allow(clippy::large_futures)] #![cfg_attr(not(test), warn(clippy::expect_used))] -use anyhow::Result; use clap::Parser; use cli::{AccountCommands, CUSTOMISE_TEMPLATE, Cli, Commands}; mod cli; use ngit::{ - cli_interactor, client, + cli_interactor::{self, CliError}, + client, git::{self, utils::set_git_timeout}, git_events, login, repo_ref, }; @@ -16,9 +16,15 @@ use ngit::{ mod sub_commands; #[tokio::main] -async fn main() -> Result<()> { +async fn main() { let cli = Cli::parse(); + // Non-interactive by default; set NGIT_INTERACTIVE_MODE only when -i is + // specified + if cli.interactive { + std::env::set_var("NGIT_INTERACTIVE_MODE", "1"); + } + if cli.customize { print!("{CUSTOMISE_TEMPLATE}"); std::process::exit(0); // Exit the program @@ -26,7 +32,7 @@ async fn main() -> Result<()> { let _ = set_git_timeout(); - if let Some(command) = &cli.command { + let result = if let Some(command) = &cli.command { match command { Commands::Account(args) => match &args.account_command { AccountCommands::Login(sub_args) => { @@ -34,6 +40,9 @@ async fn main() -> Result<()> { } AccountCommands::Logout => sub_commands::logout::launch().await, AccountCommands::ExportKeys => sub_commands::export_keys::launch().await, + AccountCommands::Create(sub_args) => { + sub_commands::create::launch(&cli, sub_args).await + } }, Commands::Init(args) => sub_commands::init::launch(&cli, args).await, Commands::List => sub_commands::list::launch().await, @@ -44,5 +53,14 @@ async fn main() -> Result<()> { // Handle the case where no command is provided eprintln!("Error: A command must be provided. Use '--help' for more information."); std::process::exit(1); + }; + + if let Err(err) = result { + if err.downcast_ref::().is_some() { + // Already printed styled output to stderr + std::process::exit(1); + } + eprintln!("Error: {err:?}"); + std::process::exit(1); } } -- cgit v1.2.3