e81d4628
Implement Display for IssueStatus and PatchStatus enums
a73x 2026-03-22 08:23
Add as_str() and Display impls so the status-to-string mapping lives in one place. Replace 14 scattered match blocks across 5 files. Closes issue cd1549f2. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
diff --git a/src/issue.rs b/src/issue.rs index b732f7f..05958ab 100644 --- a/src/issue.rs +++ b/src/issue.rs @@ -87,10 +87,7 @@ pub fn list_to_writer( } for e in &entries { let i = &e.issue; let status = match i.status { IssueStatus::Open => "open", IssueStatus::Closed => "closed", }; let status = i.status.as_str(); let labels = if i.labels.is_empty() { String::new() } else { diff --git a/src/lib.rs b/src/lib.rs index 2d11ea4..21c5b6b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,7 +20,7 @@ use base64::Engine; use cli::{Commands, IdentityCmd, IssueCmd, KeyCmd, PatchCmd}; use event::ReviewVerdict; use git2::Repository; use state::{IssueStatus, PatchStatus}; /// Check if the reviewer's base ref has moved ahead of the patch's latest revision. pub fn staleness_warning(repo: &Repository, patch: &state::PatchState) -> Option<String> { @@ -64,10 +64,7 @@ pub fn run(cli: cli::Cli, repo: &Repository) -> Result<(), error::Error> { } else { for e in &entries { let i = &e.issue; let status = match i.status { IssueStatus::Open => "open", IssueStatus::Closed => "closed", }; let status = i.status.as_str(); let labels = if i.labels.is_empty() { String::new() } else { @@ -92,11 +89,7 @@ pub fn run(cli: cli::Cli, repo: &Repository) -> Result<(), error::Error> { return Ok(()); } let i = issue::show(repo, &id)?; let status = match i.status { IssueStatus::Open => "open", IssueStatus::Closed => "closed", }; println!("Issue {} [{}]", &i.id[..8], status); println!("Issue {} [{}]", &i.id[..8], i.status); println!("Title: {}", i.title); println!("Author: {} <{}>", i.author.name, i.author.email); println!("Created: {}", i.created_at); @@ -217,14 +210,9 @@ pub fn run(cli: cli::Cli, repo: &Repository) -> Result<(), error::Error> { println!("No patches found."); } else { for p in &patches { let status = match p.status { PatchStatus::Open => "open", PatchStatus::Closed => "closed", PatchStatus::Merged => "merged", }; println!( "{:.8} {:6} {} (by {})", p.id, status, p.title, p.author.name p.id, p.status, p.title, p.author.name ); } } @@ -237,13 +225,8 @@ pub fn run(cli: cli::Cli, repo: &Repository) -> Result<(), error::Error> { return Ok(()); } let p = patch::show(repo, &id)?; let status = match p.status { PatchStatus::Open => "open", PatchStatus::Closed => "closed", PatchStatus::Merged => "merged", }; let rev_count = p.revisions.len(); println!("Patch {} [{}] (r{})", &p.id[..8], status, rev_count); println!("Patch {} [{}] (r{})", &p.id[..8], p.status, rev_count); println!("Title: {}", p.title); println!("Author: {} <{}>", p.author.name, p.author.email); match p.resolve_head(repo) { diff --git a/src/patch.rs b/src/patch.rs index 1b545cc..a97ad33 100644 --- a/src/patch.rs +++ b/src/patch.rs @@ -173,15 +173,10 @@ pub fn list_to_writer( return Ok(()); } for p in &patches { let status = match p.status { PatchStatus::Open => "open", PatchStatus::Closed => "closed", PatchStatus::Merged => "merged", }; writeln!( writer, "{:.8} {:6} {} (by {})", p.id, status, p.title, p.author.name p.id, p.status, p.title, p.author.name ) .ok(); } @@ -385,7 +380,7 @@ pub fn merge(repo: &Repository, id_prefix: &str) -> Result<PatchState, crate::er if p.status != PatchStatus::Open { return Err(git2::Error::from_str(&format!( "patch is {:?}, can only merge open patches", "patch is {}, can only merge open patches", p.status )) .into()); diff --git a/src/state.rs b/src/state.rs index 205e99f..f59f179 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,3 +1,5 @@ use std::fmt; use git2::{Oid, Repository}; use serde::{Deserialize, Serialize}; @@ -60,6 +62,21 @@ pub enum IssueStatus { Closed, } impl IssueStatus { pub fn as_str(&self) -> &'static str { match self { IssueStatus::Open => "open", IssueStatus::Closed => "closed", } } } impl fmt::Display for IssueStatus { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_str()) } } #[derive(Debug, Clone, Serialize, Deserialize)] #[allow(dead_code)] pub struct Comment { @@ -113,6 +130,22 @@ pub enum PatchStatus { Merged, } impl PatchStatus { pub fn as_str(&self) -> &'static str { match self { PatchStatus::Open => "open", PatchStatus::Closed => "closed", PatchStatus::Merged => "merged", } } } impl fmt::Display for PatchStatus { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_str()) } } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Revision { pub number: u32, diff --git a/src/status.rs b/src/status.rs index 022226d..14b0962 100644 --- a/src/status.rs +++ b/src/status.rs @@ -80,10 +80,7 @@ pub fn compute(repo: &Repository) -> Result<ProjectStatus, Error> { kind: "issue", id: issue.id[..8.min(issue.id.len())].to_string(), title: issue.title.clone(), status: match issue.status { IssueStatus::Open => "open".to_string(), IssueStatus::Closed => "closed".to_string(), }, status: issue.status.to_string(), created_at: issue.created_at.clone(), }); } @@ -92,11 +89,7 @@ pub fn compute(repo: &Repository) -> Result<ProjectStatus, Error> { kind: "patch", id: patch.id[..8.min(patch.id.len())].to_string(), title: patch.title.clone(), status: match patch.status { PatchStatus::Open => "open".to_string(), PatchStatus::Closed => "closed".to_string(), PatchStatus::Merged => "merged".to_string(), }, status: patch.status.to_string(), created_at: patch.created_at.clone(), }); } diff --git a/src/tui/widgets.rs b/src/tui/widgets.rs index 096c80c..4bf517f 100644 --- a/src/tui/widgets.rs +++ b/src/tui/widgets.rs @@ -152,10 +152,7 @@ fn render_list(frame: &mut Frame, app: &mut App, area: Rect) { let items: Vec<ListItem> = visible .iter() .map(|i| { let status = match i.status { IssueStatus::Open => "open", IssueStatus::Closed => "closed", }; let status = i.status.as_str(); let style = match i.status { IssueStatus::Open => Style::default().fg(Color::Green), IssueStatus::Closed => Style::default().fg(Color::Red), @@ -187,11 +184,7 @@ fn render_list(frame: &mut Frame, app: &mut App, area: Rect) { let items: Vec<ListItem> = visible .iter() .map(|p| { let status = match p.status { PatchStatus::Open => "open", PatchStatus::Closed => "closed", PatchStatus::Merged => "merged", }; let status = p.status.as_str(); let style = match p.status { PatchStatus::Open => Style::default().fg(Color::Green), PatchStatus::Closed => Style::default().fg(Color::Red), @@ -346,10 +339,7 @@ fn render_detail(frame: &mut Frame, app: &mut App, area: Rect) { } fn build_issue_detail(issue: &IssueState, patches: &[PatchState]) -> Text<'static> { let status = match issue.status { IssueStatus::Open => "open", IssueStatus::Closed => "closed", }; let status = issue.status.as_str(); let mut lines: Vec<Line> = vec![ Line::from(vec![ @@ -475,11 +465,7 @@ fn build_issue_detail(issue: &IssueState, patches: &[PatchState]) -> Text<'stati } fn build_patch_summary(patch: &PatchState) -> Text<'static> { let status_str = match patch.status { PatchStatus::Open => "open", PatchStatus::Closed => "closed", PatchStatus::Merged => "merged", }; let status_str = patch.status.as_str(); let status_color = match patch.status { PatchStatus::Open => Color::Green, PatchStatus::Closed => Color::Red, @@ -549,11 +535,7 @@ fn build_patch_detail_text(app: &App) -> Text<'static> { None => return Text::raw("No patch loaded."), }; let status_str = match patch.status { PatchStatus::Open => "open", PatchStatus::Closed => "closed", PatchStatus::Merged => "merged", }; let status_str = patch.status.as_str(); let status_color = match patch.status { PatchStatus::Open => Color::Green, PatchStatus::Closed => Color::Red,