From e50687b908e802c9f3328c9b57060b63bb5706c0 Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Fri, 20 Feb 2026 23:03:15 +0000 Subject: improve `ngit repo` output styling - make repo name bold yellow as a title; section headings bold dim - add dim horizontal rules above and below the name/description block - move earliest unique commit to the bottom (after additional relays) - add --offline flag to skip network fetch and use local cache only --- src/bin/ngit/cli.rs | 3 +++ src/bin/ngit/main.rs | 2 +- src/bin/ngit/sub_commands/repo/mod.rs | 49 +++++++++++++++++++++-------------- 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/bin/ngit/cli.rs b/src/bin/ngit/cli.rs index fa5d906..164035b 100644 --- a/src/bin/ngit/cli.rs +++ b/src/bin/ngit/cli.rs @@ -187,6 +187,9 @@ pub struct AccountSubCommandArgs { pub struct RepoSubCommandArgs { #[command(subcommand)] pub repo_command: Option, + /// Use local cache only, skip network fetch + #[arg(long)] + pub offline: bool, } #[derive(Subcommand)] diff --git a/src/bin/ngit/main.rs b/src/bin/ngit/main.rs index 924a714..5a7654a 100644 --- a/src/bin/ngit/main.rs +++ b/src/bin/ngit/main.rs @@ -50,7 +50,7 @@ async fn main() { }, Commands::Init(args) => sub_commands::init::launch(&cli, args).await, Commands::Repo(args) => { - sub_commands::repo::launch(&cli, args.repo_command.as_ref()).await + sub_commands::repo::launch(&cli, args.repo_command.as_ref(), args.offline).await } Commands::List { status, diff --git a/src/bin/ngit/sub_commands/repo/mod.rs b/src/bin/ngit/sub_commands/repo/mod.rs index 7914e1d..b15afdb 100644 --- a/src/bin/ngit/sub_commands/repo/mod.rs +++ b/src/bin/ngit/sub_commands/repo/mod.rs @@ -23,13 +23,13 @@ use crate::{ sub_commands::init, }; -pub async fn launch(cli_args: &Cli, repo_command: Option<&RepoCommands>) -> Result<()> { +pub async fn launch(cli_args: &Cli, repo_command: Option<&RepoCommands>, offline: bool) -> Result<()> { match repo_command { Some(RepoCommands::Init(args) | RepoCommands::Edit(args)) => { init::launch(cli_args, args).await } Some(RepoCommands::Accept(args)) => accept::launch(cli_args, args).await, - None => show_info(cli_args).await, + None => show_info(cli_args, offline).await, } } @@ -37,7 +37,7 @@ pub async fn launch(cli_args: &Cli, repo_command: Option<&RepoCommands>) -> Resu // `ngit repo` (no subcommand) — show repository info // --------------------------------------------------------------------------- -async fn show_info(cli_args: &Cli) -> Result<()> { +async fn show_info(cli_args: &Cli, offline: bool) -> Result<()> { let git_repo = Repo::discover().context("failed to find a git repository")?; let git_repo_path = git_repo.get_path()?; let client = Client::new(Params::with_git_config_relay_defaults(&Some(&git_repo))); @@ -69,7 +69,9 @@ async fn show_info(cli_args: &Cli) -> Result<()> { // Fetch latest data from relays — suppress the summary line. // fetching_quietly writes a blank line to stderr after errors so there // is clear separation before the repo info below. - let _ = fetching_quietly(git_repo_path, &client, &repo_coordinate).await; + if !offline { + let _ = fetching_quietly(git_repo_path, &client, &repo_coordinate).await; + } let Some(repo_ref) = (get_repo_ref_from_cache(Some(git_repo_path), &repo_coordinate).await).ok() @@ -95,9 +97,14 @@ async fn print_repo_info( coordinate: &Nip19Coordinate, git_repo_path: &Path, ) { - let heading = Style::new().bold(); + let title = Style::new().bold().yellow(); + let heading = Style::new().bold().dim(); let dim = Style::new().dim(); + let term_width = console::Term::stdout().size().1 as usize; + let rule_width = term_width.clamp(20, 60); + let rule = dim.apply_to("─".repeat(rule_width)); + let multi_maintainer = repo_ref.maintainers.len() > 1 || repo_ref .maintainers_without_annoucnement @@ -105,38 +112,31 @@ async fn print_repo_info( .is_some_and(|v| !v.is_empty()); // --- Basic metadata --- - println!("{}", heading.apply_to(&repo_ref.name)); + println!("{rule}"); + println!(" {}", title.apply_to(&repo_ref.name)); // Show identifier only when it differs from the name let identifier_slug = repo_ref.identifier.to_lowercase().replace(' ', "-"); let name_slug = repo_ref.name.to_lowercase().replace(' ', "-"); if identifier_slug != name_slug { println!( - "{}", + " {}", dim.apply_to(format!("identifier: {}", repo_ref.identifier)) ); } if !repo_ref.description.is_empty() { - println!("{}", repo_ref.description); + println!(" {}", repo_ref.description); } if !repo_ref.web.is_empty() { for url in &repo_ref.web { - println!("{}", dim.apply_to(url)); + println!(" {}", dim.apply_to(url)); } } if !repo_ref.hashtags.is_empty() { - println!("{}", dim.apply_to(repo_ref.hashtags.join(" "))); - } - if !repo_ref.root_commit.is_empty() { - println!( - "{}", - dim.apply_to(format!( - "earliest unique commit: {}", - &repo_ref.root_commit[..7.min(repo_ref.root_commit.len())] - )) - ); + println!(" {}", dim.apply_to(repo_ref.hashtags.join(" "))); } + println!("{rule}"); println!(); // --- Maintainers --- @@ -317,6 +317,17 @@ async fn print_repo_info( println!(); } + if !repo_ref.root_commit.is_empty() { + println!( + "{}", + dim.apply_to(format!( + "earliest unique commit: {}", + &repo_ref.root_commit[..7.min(repo_ref.root_commit.len())] + )) + ); + println!(); + } + // --- Maintainer model note (only relevant when there are multiple maintainers) --- if multi_maintainer { println!( -- cgit v1.2.3