From b143abb25d6ece32412629baa3e75e94d139979f Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Thu, 5 Mar 2026 13:14:34 +0000 Subject: refactor(subject): standardise on subject over title in CLI and output - JSON output fields renamed from title to subject in pr list/view and issue list/view - Printed view output changed from Title: to Subject: - ngit issue create --subject (alias --title) - ngit send --subject (alias --title) - Error messages and interactive prompts updated to match --- src/bin/ngit/cli.rs | 6 ++-- src/bin/ngit/main.rs | 4 +-- src/bin/ngit/sub_commands/issue_list.rs | 8 ++--- src/bin/ngit/sub_commands/list.rs | 8 ++--- src/bin/ngit/sub_commands/send.rs | 52 ++++++++++++++++----------------- 5 files changed, 39 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/bin/ngit/cli.rs b/src/bin/ngit/cli.rs index 8cdbee1..8660b60 100644 --- a/src/bin/ngit/cli.rs +++ b/src/bin/ngit/cli.rs @@ -397,9 +397,9 @@ pub enum IssueCommands { }, /// create a new issue Create { - /// Issue title - #[arg(long)] - title: Option, + /// Issue subject/title + #[arg(long, alias = "title")] + subject: Option, /// Issue body / description #[arg(long)] body: Option, diff --git a/src/bin/ngit/main.rs b/src/bin/ngit/main.rs index 1dbf020..3f5e65c 100644 --- a/src/bin/ngit/main.rs +++ b/src/bin/ngit/main.rs @@ -179,11 +179,11 @@ async fn main() { .await } IssueCommands::Create { - title, + subject, body, labels, } => { - sub_commands::issue_create::launch(title.clone(), body.clone(), labels.clone()) + sub_commands::issue_create::launch(subject.clone(), body.clone(), labels.clone()) .await } IssueCommands::Close { id, reason, offline } => { diff --git a/src/bin/ngit/sub_commands/issue_list.rs b/src/bin/ngit/sub_commands/issue_list.rs index 8c7a7fc..8f78d5e 100644 --- a/src/bin/ngit/sub_commands/issue_list.rs +++ b/src/bin/ngit/sub_commands/issue_list.rs @@ -336,7 +336,7 @@ fn show_issue_details( serde_json::json!({ "id": issue.id.to_string(), "status": status, - "title": title, + "subject": title, "author": issue.pubkey.to_bech32().unwrap_or_default(), "labels": labels, "comment_count": comment_count, @@ -347,7 +347,7 @@ fn show_issue_details( serde_json::json!({ "id": issue.id.to_string(), "status": status, - "title": title, + "subject": title, "author": issue.pubkey.to_bech32().unwrap_or_default(), "labels": labels, "comment_count": comment_count, @@ -358,7 +358,7 @@ fn show_issue_details( return Ok(()); } - println!("Title: {title}"); + println!("Subject: {title}"); println!("Author: {}", issue.pubkey.to_bech32().unwrap_or_default()); println!("Status: {status}"); if !labels.is_empty() { @@ -470,7 +470,7 @@ fn output_json(issues: &[IssueRow<'_>]) -> Result<()> { serde_json::json!({ "id": issue.id.to_string(), "status": status_kind_to_str(*status_kind), - "title": get_issue_title(issue, subject_override.as_deref()), + "subject": get_issue_title(issue, subject_override.as_deref()), "author": issue.pubkey.to_bech32().unwrap_or_default(), "labels": labels, "comment_count": comment_count, diff --git a/src/bin/ngit/sub_commands/list.rs b/src/bin/ngit/sub_commands/list.rs index ab4f0f7..df147bc 100644 --- a/src/bin/ngit/sub_commands/list.rs +++ b/src/bin/ngit/sub_commands/list.rs @@ -413,7 +413,7 @@ fn output_json(proposals: &[(&nostr::Event, Kind, Vec, Option)]) serde_json::json!({ "id": id, "status": status, - "title": title, + "subject": title, "author": author, "branch": branch, "labels": proposal_labels, @@ -497,7 +497,7 @@ fn show_proposal_details( serde_json::json!({ "id": proposal.id.to_string(), "status": status_kind_to_str(*status_kind), - "title": display_title, + "subject": display_title, "author": proposal.pubkey.to_bech32().unwrap_or_default(), "branch": cover_letter.get_branch_name_with_pr_prefix_and_shorthand_id()?, "labels": proposal_labels, @@ -509,7 +509,7 @@ fn show_proposal_details( serde_json::json!({ "id": proposal.id.to_string(), "status": status_kind_to_str(*status_kind), - "title": display_title, + "subject": display_title, "author": proposal.pubkey.to_bech32().unwrap_or_default(), "branch": cover_letter.get_branch_name_with_pr_prefix_and_shorthand_id()?, "labels": proposal_labels, @@ -521,7 +521,7 @@ fn show_proposal_details( return Ok(()); } - println!("Title: {display_title}"); + println!("Subject: {display_title}"); println!( "Author: {}", proposal.pubkey.to_bech32().unwrap_or_default() diff --git a/src/bin/ngit/sub_commands/send.rs b/src/bin/ngit/sub_commands/send.rs index 86af2d3..e7671a2 100644 --- a/src/bin/ngit/sub_commands/send.rs +++ b/src/bin/ngit/sub_commands/send.rs @@ -38,9 +38,9 @@ pub struct SubCommandArgs { /// don't prompt for a cover letter #[arg(long, action)] pub(crate) no_cover_letter: bool, - /// optional cover letter title - #[clap(long)] - pub(crate) title: Option, + /// optional cover letter subject/title + #[clap(long, alias = "title")] + pub(crate) subject: Option, #[clap(long)] /// optional cover letter description pub(crate) description: Option, @@ -73,23 +73,23 @@ fn validate_send_args(cli: &Cli, args: &SubCommandArgs) -> Result<()> { return Ok(()); } - // Description requires title - if args.description.is_some() && args.title.is_none() { - let message = "ngit send requires --title when --description is provided"; - let details = vec![("--title ", "cover letter title")]; + // Description requires subject + if args.description.is_some() && args.subject.is_none() { + let message = "ngit send requires --subject when --description is provided"; + let details = vec![("--subject ", "cover letter subject")]; let suggestions = vec![ - "ngit send HEAD~2 --title \"My Feature\" --description \"Details\"", + "ngit send HEAD~2 --subject \"My Feature\" --description \"Details\"", "ngit send --interactive", ]; return Err(cli_error(message, &details, &suggestions)); } - // Title requires description - if args.title.is_some() && args.description.is_none() { - let message = "ngit send requires --description when --title is provided"; + // Subject requires description + if args.subject.is_some() && args.description.is_none() { + let message = "ngit send requires --description when --subject is provided"; let details = vec![("--description ", "cover letter description")]; let suggestions = vec![ - "ngit send HEAD~2 --title \"My Feature\" --description \"Details\"", + "ngit send HEAD~2 --subject \"My Feature\" --description \"Details\"", "ngit send --interactive", ]; return Err(cli_error(message, &details, &suggestions)); @@ -105,8 +105,8 @@ fn validate_send_args(cli: &Cli, args: &SubCommandArgs) -> Result<()> { return Ok(()); } - // Both title and description provided - all good - if args.title.is_some() && args.description.is_some() { + // Both subject and description provided - all good + if args.subject.is_some() && args.description.is_some() { return Ok(()); } @@ -121,11 +121,11 @@ fn validate_send_args(cli: &Cli, args: &SubCommandArgs) -> Result<()> { if args.since_or_range.is_empty() { details.push(("", "commits to send (eg. HEAD~2)")); } - details.push(("--title --description ", "cover letter details")); + details.push(("--subject --description ", "cover letter details")); details.push(("-d, --defaults", "use sensible defaults")); details.push(("--interactive", "prompt for values")); let suggestions = vec![ - "ngit send HEAD~2 --title \"My Feature\" --description \"Details\"", + "ngit send HEAD~2 --subject \"My Feature\" --description \"Details\"", "ngit send --defaults", "ngit send --interactive", ]; @@ -252,13 +252,13 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs, no_fetch: bool) -> Re let cover_letter_title_description = if cli_args.interactive { // Interactive flow: prompt for cover letter confirm, title, description let title = if as_pr { - match &args.title { + match &args.subject { Some(t) => Some(t.clone()), None => { if root_proposal.is_none() { Some( Interactor::default() - .input(PromptInputParms::default().with_prompt("title"))? + .input(PromptInputParms::default().with_prompt("subject"))? .clone(), ) } else { @@ -269,7 +269,7 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs, no_fetch: bool) -> Re } else if args.no_cover_letter { None } else { - match &args.title { + match &args.subject { Some(t) => Some(t.clone()), None => { if Interactor::default().confirm( @@ -279,7 +279,7 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs, no_fetch: bool) -> Re )? { Some( Interactor::default() - .input(PromptInputParms::default().with_prompt("title"))? + .input(PromptInputParms::default().with_prompt("subject"))? .clone(), ) } else { @@ -305,12 +305,12 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs, no_fetch: bool) -> Re } } else if as_pr { // PR always needs cover letter - let title = match &args.title { + let title = match &args.subject { Some(t) => t.clone(), None if cli_args.defaults => { git_repo.get_commit_message_summary(commits.first().context("no commits")?)? } - None => bail!("PR requires --title and --description (or use --defaults)"), + None => bail!("PR requires --subject and --description (or use --defaults)"), }; let description = match &args.description { Some(d) => d.clone(), @@ -324,15 +324,15 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs, no_fetch: bool) -> Re .trim() .to_string() } - None => bail!("PR requires --title and --description (or use --defaults)"), + None => bail!("PR requires --subject and --description (or use --defaults)"), }; Some((title, description)) } else { // Patch mode - match (&args.title, &args.description) { + match (&args.subject, &args.description) { (Some(t), Some(d)) => Some((t.clone(), d.clone())), - (Some(_), None) => bail!("--title requires --description"), - (None, Some(_)) => bail!("--description requires --title"), + (Some(_), None) => bail!("--subject requires --description"), + (None, Some(_)) => bail!("--description requires --subject"), (None, None) => None, // no cover letter } }; -- cgit v1.2.3