From 9c3ebce8104db3f8d9c68c9137a35c6461b7bc6c Mon Sep 17 00:00:00 2001 From: aragami3070 Date: Fri, 22 Aug 2025 22:20:20 +0400 Subject: [PATCH 01/14] Feat(issue): add get method for git_utils --- src/git_utils/issues.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/git_utils/issues.rs b/src/git_utils/issues.rs index 30cc28a..31fa38c 100644 --- a/src/git_utils/issues.rs +++ b/src/git_utils/issues.rs @@ -1,7 +1,7 @@ use std::error::Error; use octorust::types::{ - self, IssuesCreateRequest, IssuesCreateRequestLabelsOneOf, IssuesUpdateRequest, State, + self, Issue, IssuesCreateRequest, IssuesCreateRequestLabelsOneOf, IssuesUpdateRequest, State, TitleOneOf, }; use octorust::Client; @@ -9,6 +9,19 @@ use octorust::Client; use crate::git_utils::comments; use crate::git_utils::repo_info::RepoInfo; +pub async fn get( + github_client: &Client, + repo_info: &RepoInfo, + issue_number: i64, +) -> Result> { + let issue = github_client + .issues() + .get(&repo_info.get_owner(), &repo_info.get_name(), issue_number) + .await?; + + Ok(issue.body) +} + pub async fn get_list( github_client: &Client, repo_info: &RepoInfo, @@ -106,9 +119,9 @@ fn get_update_request( state: &State, ) -> IssuesUpdateRequest { let new_title = match title { - Some(t) => Some(TitleOneOf::String(t.to_string())), - None => None - }; + Some(t) => Some(TitleOneOf::String(t.to_string())), + None => None, + }; let new_labels = match labels { Some(l) => l From 82313f0a538d90da38bdda78eafc47fd541dd9e5 Mon Sep 17 00:00:00 2001 From: aragami3070 Date: Fri, 22 Aug 2025 22:22:01 +0400 Subject: [PATCH 02/14] Feat(cli_out): add print_issue --- src/cli_out/print_in_cli.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/cli_out/print_in_cli.rs b/src/cli_out/print_in_cli.rs index bd8cebd..d0fe04d 100644 --- a/src/cli_out/print_in_cli.rs +++ b/src/cli_out/print_in_cli.rs @@ -1,7 +1,7 @@ use std::process; use octorust::types::{ - IssueComment, IssueSimple, MinimalRepository, PullRequestReviewComment, Release, + Issue, IssueComment, IssueSimple, MinimalRepository, PullRequestReviewComment, Release, }; use crate::cli_in::set_vars::IssuesListStates; @@ -35,6 +35,30 @@ pub fn print_issues(list_issues: Vec, state: IssuesListStates, numb } } +pub fn print_issue(issue: Issue) { + println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); + println!("│Issue {}: {};", issue.number, issue.title); + println!("│State: {}", issue.state); + println!("│labels:"); + for label in issue.labels { + match label.labels_data() { + Some(data) => { + println!("│ Name: {}", data.name); + println!("│ Description: {}", data.description); + } + None => {} + } + } + println!("│Body: {}", issue.body); + match issue.created_at { + Some(time) => { + println!("│Created at: {}", time); + } + None => {} + }; + println!("╰────────────────────────────────────────────────────────────────────────────────────────────────"); +} + pub fn print_url(result: String, description: &str) { println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); println!("│{} : {}", description, result.replace(" ", "-")); From 53650600b064f3952677c10217821dabbee2ecfc Mon Sep 17 00:00:00 2001 From: aragami3070 Date: Fri, 22 Aug 2025 22:34:16 +0400 Subject: [PATCH 03/14] Feat(cli_out): add print labels in print_issues --- src/cli_out/print_in_cli.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/cli_out/print_in_cli.rs b/src/cli_out/print_in_cli.rs index d0fe04d..e62e385 100644 --- a/src/cli_out/print_in_cli.rs +++ b/src/cli_out/print_in_cli.rs @@ -30,7 +30,16 @@ pub fn print_issues(list_issues: Vec, state: IssuesListStates, numb println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); println!("│Issue {}: {};", issue.number, issue.title); println!("│Body: {}", issue.body); - println!("│Time: {}", issue.timeline_url); + println!("│labels:"); + for label in issue.labels { + println!("│ {}: {}", label.name, label.description); + } + match issue.created_at { + Some(time) => { + println!("│Created at: {}", time); + } + None => {} + }; println!("╰────────────────────────────────────────────────────────────────────────────────────────────────"); } } @@ -39,6 +48,7 @@ pub fn print_issue(issue: Issue) { println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); println!("│Issue {}: {};", issue.number, issue.title); println!("│State: {}", issue.state); + println!("│Body: {}", issue.body); println!("│labels:"); for label in issue.labels { match label.labels_data() { @@ -49,7 +59,6 @@ pub fn print_issue(issue: Issue) { None => {} } } - println!("│Body: {}", issue.body); match issue.created_at { Some(time) => { println!("│Created at: {}", time); From 4de3781e3238497a646dc565c9c0e83b00f6b80b Mon Sep 17 00:00:00 2001 From: aragami3070 Date: Fri, 22 Aug 2025 22:52:07 +0400 Subject: [PATCH 04/14] Feat(cli_out): add PrintError struct for handle error when print results data --- src/cli_out/print_in_cli.rs | 53 ++++++++++++++++--- .../handle_commands/handle_comment.rs | 12 +++-- 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/cli_out/print_in_cli.rs b/src/cli_out/print_in_cli.rs index e62e385..3b25ae3 100644 --- a/src/cli_out/print_in_cli.rs +++ b/src/cli_out/print_in_cli.rs @@ -1,4 +1,35 @@ -use std::process; +use std::error::Error; +use std::fmt; + +/// Errors returned by the tried print result +#[derive(Debug, PartialEq, Eq)] +pub struct PrintError { + kind: PrintErrorKind, + description: String, +} + +/// Type of PrintError +#[derive(Debug, PartialEq, Eq)] +enum PrintErrorKind { + /// Github response was wrong + BadResponse, +} + +impl Error for PrintError {} + +impl fmt::Display for PrintError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match &self.kind { + PrintErrorKind::BadResponse => { + write!( + f, + "tried print, but the github response turned out to be invalid.\nDescription: {}", + &self.description + ) + } + } + } +} use octorust::types::{ Issue, IssueComment, IssueSimple, MinimalRepository, PullRequestReviewComment, Release, @@ -87,7 +118,7 @@ pub fn print_repos(repos: Vec, owner: String, owner_type: &st } } -pub fn print_comments(list_comments: Vec) { +pub fn print_comments(list_comments: Vec) -> Result<(), Box> { println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); println!("│Comments:"); println!("╰────────────────────────────────────────────────────────────────────────────────────────────────"); @@ -98,17 +129,22 @@ pub fn print_comments(list_comments: Vec) { match comment.user { Some(u) => u.login, None => { - eprintln!("Bad response from github"); - process::exit(1); + return Err(Box::new(PrintError { + kind: PrintErrorKind::BadResponse, + description: "User who create comment not find".to_string(), + })); } } ); println!("│Body: {}", comment.body); println!("╰────────────────────────────────────────────────────────────────────────────────────────────────"); } + Ok(()) } -pub fn print_review_comments(list_comments: Vec) { +pub fn print_review_comments( + list_comments: Vec, +) -> Result<(), Box> { println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); println!("│Review comments:"); println!("╰────────────────────────────────────────────────────────────────────────────────────────────────"); @@ -119,8 +155,10 @@ pub fn print_review_comments(list_comments: Vec) { match comment.user { Some(u) => u.login, None => { - eprintln!("Bad response from github"); - process::exit(1); + return Err(Box::new(PrintError { + kind: PrintErrorKind::BadResponse, + description: "User who create comment not find".to_string(), + })); } } ); @@ -129,4 +167,5 @@ pub fn print_review_comments(list_comments: Vec) { println!("│In file: {}", comment.path); println!("╰────────────────────────────────────────────────────────────────────────────────────────────────"); } + Ok(()) } diff --git a/src/cli_parse/handle_commands/handle_comment.rs b/src/cli_parse/handle_commands/handle_comment.rs index 5e7a311..952e010 100644 --- a/src/cli_parse/handle_commands/handle_comment.rs +++ b/src/cli_parse/handle_commands/handle_comment.rs @@ -22,10 +22,12 @@ pub async fn handle_comment_command( Ok(()) } - CommentCommand::GetAll { + CommentCommand::GetAll { owner, repo, - number, target } => { + number, + target, + } => { handle_get_all(github_client, owner, repo, number, target).await?; Ok(()) } @@ -74,7 +76,7 @@ async fn handle_get_all( let result = comments::get_all(&github_client, &repo_info, &number).await?; - print_comments(result); + print_comments(result)?; let review_comments = match target { CommentTarget::PullRequest => { @@ -90,7 +92,7 @@ async fn handle_get_all( CommentTarget::Issue => Vec::new(), }; if !review_comments.is_empty() { - print_review_comments(review_comments); + print_review_comments(review_comments)?; } Ok(()) } @@ -111,6 +113,6 @@ async fn handle_get_all_from_review( let result = comments::get_all_from_review(&github_client, &repo_info, &number, sort.0, order.0).await?; - print_review_comments(result); + print_review_comments(result)?; Ok(()) } From cf7d8d55757e5e9b068a2b226e6668501757097e Mon Sep 17 00:00:00 2001 From: aragami3070 Date: Fri, 22 Aug 2025 22:55:25 +0400 Subject: [PATCH 05/14] Chore(cli_out): remove '|' in all prints --- src/cli_out/print_in_cli.rs | 64 ++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/cli_out/print_in_cli.rs b/src/cli_out/print_in_cli.rs index 3b25ae3..9e14aa7 100644 --- a/src/cli_out/print_in_cli.rs +++ b/src/cli_out/print_in_cli.rs @@ -39,13 +39,13 @@ use crate::cli_in::set_vars::IssuesListStates; pub fn print_release(result: Release) { println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); - println!("│Release tag: {}", result.tag_name); - println!("│Release id: {}", result.id); - println!("│Release title: {}", result.name); - println!("│Release body: {}", result.body); - println!("│Release tag_commit: {}", result.target_commitish); - println!("│Release url: {}", result.url); - println!("│Release upload_url: {}", result.upload_url); + println!(" Release tag: {}", result.tag_name); + println!(" Release id: {}", result.id); + println!(" Release title: {}", result.name); + println!(" Release body: {}", result.body); + println!(" Release tag_commit: {}", result.target_commitish); + println!(" Release url: {}", result.url); + println!(" Release upload_url: {}", result.upload_url); println!("╰────────────────────────────────────────────────────────────────────────────────────────────────"); } @@ -59,15 +59,15 @@ pub fn print_issues(list_issues: Vec, state: IssuesListStates, numb println!(); for issue in list_issues { println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); - println!("│Issue {}: {};", issue.number, issue.title); - println!("│Body: {}", issue.body); - println!("│labels:"); + println!(" Issue {}: {};", issue.number, issue.title); + println!(" Body: {}", issue.body); + println!(" labels:"); for label in issue.labels { - println!("│ {}: {}", label.name, label.description); + println!(" {}: {}", label.name, label.description); } match issue.created_at { Some(time) => { - println!("│Created at: {}", time); + println!(" Created at: {}", time); } None => {} }; @@ -77,22 +77,22 @@ pub fn print_issues(list_issues: Vec, state: IssuesListStates, numb pub fn print_issue(issue: Issue) { println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); - println!("│Issue {}: {};", issue.number, issue.title); - println!("│State: {}", issue.state); - println!("│Body: {}", issue.body); - println!("│labels:"); + println!(" Issue {}: {};", issue.number, issue.title); + println!(" State: {}", issue.state); + println!(" Body: {}", issue.body); + println!(" labels:"); for label in issue.labels { match label.labels_data() { Some(data) => { - println!("│ Name: {}", data.name); - println!("│ Description: {}", data.description); + println!(" Name: {}", data.name); + println!(" Description: {}", data.description); } None => {} } } match issue.created_at { Some(time) => { - println!("│Created at: {}", time); + println!(" Created at: {}", time); } None => {} }; @@ -101,7 +101,7 @@ pub fn print_issue(issue: Issue) { pub fn print_url(result: String, description: &str) { println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); - println!("│{} : {}", description, result.replace(" ", "-")); + println!(" {} : {}", description, result.replace(" ", "-")); println!("╰────────────────────────────────────────────────────────────────────────────────────────────────"); } @@ -110,22 +110,22 @@ pub fn print_repos(repos: Vec, owner: String, owner_type: &st for repo in repos { println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); - println!("│Repo {}: {}", repo.id, repo.full_name); - println!("│Language: {}", repo.language); - println!("│Url: {}", repo.url); - println!("│Description: {}", repo.description); + println!(" Repo {}: {}", repo.id, repo.full_name); + println!(" Language: {}", repo.language); + println!(" Url: {}", repo.url); + println!(" Description: {}", repo.description); println!("╰────────────────────────────────────────────────────────────────────────────────────────────────"); } } pub fn print_comments(list_comments: Vec) -> Result<(), Box> { println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); - println!("│Comments:"); + println!(" Comments:"); println!("╰────────────────────────────────────────────────────────────────────────────────────────────────"); for comment in list_comments { println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); println!( - "│Who create: {}", + " Who create: {}", match comment.user { Some(u) => u.login, None => { @@ -136,7 +136,7 @@ pub fn print_comments(list_comments: Vec) -> Result<(), Box, ) -> Result<(), Box> { println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); - println!("│Review comments:"); + println!(" Review comments:"); println!("╰────────────────────────────────────────────────────────────────────────────────────────────────"); for comment in list_comments { println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); println!( - "│Who create: {}", + " Who create: {}", match comment.user { Some(u) => u.login, None => { @@ -162,9 +162,9 @@ pub fn print_review_comments( } } ); - println!("│Body: {}", comment.body); - println!("│For line: {}", comment.line); - println!("│In file: {}", comment.path); + println!(" Body: {}", comment.body); + println!(" For line: {}", comment.line); + println!(" In file: {}", comment.path); println!("╰────────────────────────────────────────────────────────────────────────────────────────────────"); } Ok(()) From 112ba1bf6eb072ce77a3aff36fd53429e2e7591a Mon Sep 17 00:00:00 2001 From: aragami3070 Date: Fri, 22 Aug 2025 22:56:29 +0400 Subject: [PATCH 06/14] Feat(cli_in): add get command in issue part --- src/cli_in/issue_command.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/cli_in/issue_command.rs b/src/cli_in/issue_command.rs index 5338497..7f5d3d8 100644 --- a/src/cli_in/issue_command.rs +++ b/src/cli_in/issue_command.rs @@ -33,6 +33,19 @@ pub enum IssueCommand { iss_on_page: i64, }, + /// Get issue by number + Get { + /// Repo owner (optional) + #[clap(long, short, default_value = None)] + owner: Option, + /// Repo name (optional) + #[clap(long, short, default_value = None)] + repo: Option, + /// Update issue with number + #[clap(long, short)] + number: i64, + }, + /// Create issue Create { /// Repo owner (optional) From c0131cf2f86ee8c072c6fa33d9a9c30b58e1a3a2 Mon Sep 17 00:00:00 2001 From: aragami3070 Date: Fri, 22 Aug 2025 22:56:53 +0400 Subject: [PATCH 07/14] Feat(cli_parse): add get issue handle --- src/cli_parse/handle_commands/handle_issue.rs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/cli_parse/handle_commands/handle_issue.rs b/src/cli_parse/handle_commands/handle_issue.rs index bcbc8ad..0731778 100644 --- a/src/cli_parse/handle_commands/handle_issue.rs +++ b/src/cli_parse/handle_commands/handle_issue.rs @@ -4,7 +4,10 @@ use std::error::Error; use crate::cli_in::issue_command::IssueCommand; use crate::cli_in::set_vars::IssuesListStates; use crate::cli_in::set_vars::States; +use crate::cli_out::print_in_cli::print_comments; +use crate::cli_out::print_in_cli::print_issue; use crate::cli_out::print_in_cli::print_issues; +use crate::git_utils::comments; use crate::git_utils::issues; use crate::git_utils::repo_info::Repo; use crate::git_utils::repo_info::RepoInfo; @@ -40,6 +43,15 @@ pub async fn handle_issue_command( Ok(()) } + IssueCommand::Get { + owner, + repo, + number, + } => { + handle_get(github_client, owner, repo, number).await?; + Ok(()) + } + IssueCommand::Create { owner, repo, @@ -121,6 +133,26 @@ async fn handle_list( Ok(()) } +async fn handle_get( + github_client: Client, + owner: Option, + repo: Option, + number: i64, +) -> Result<(), Box> { + let repo_info = match owner { + Some(_) => RepoInfo::new(Repo::Input, owner, repo)?, + None => RepoInfo::new(Repo::Current, None, None)?, + }; + + let result = issues::get(&github_client, &repo_info, number).await?; + + let list_comments = comments::get_all(&github_client, &repo_info, &number).await?; + + print_issue(result); + print_comments(list_comments)?; + Ok(()) +} + async fn handle_create( github_client: Client, owner: Option, From c2ab4c432f0c53615d66f2ab377fdc10b5d2460b Mon Sep 17 00:00:00 2001 From: aragami3070 Date: Sat, 23 Aug 2025 00:59:13 +0400 Subject: [PATCH 08/14] Feat(cli_out): add print_simple_issue --- src/cli_out/print_in_cli.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/cli_out/print_in_cli.rs b/src/cli_out/print_in_cli.rs index 9e14aa7..e1f56c1 100644 --- a/src/cli_out/print_in_cli.rs +++ b/src/cli_out/print_in_cli.rs @@ -75,6 +75,24 @@ pub fn print_issues(list_issues: Vec, state: IssuesListStates, numb } } +pub fn print_simple_issue(issue: IssueSimple) { + println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); + println!(" Issue {}: {};", issue.number, issue.title); + println!(" State: {}", issue.state); + println!(" Body: {}", issue.body); + println!(" labels:"); + for label in issue.labels { + println!(" {}: {}", label.name, label.description); + } + match issue.created_at { + Some(time) => { + println!(" Created at: {}", time); + } + None => {} + }; + println!("╰────────────────────────────────────────────────────────────────────────────────────────────────"); +} + pub fn print_issue(issue: Issue) { println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); println!(" Issue {}: {};", issue.number, issue.title); @@ -84,8 +102,7 @@ pub fn print_issue(issue: Issue) { for label in issue.labels { match label.labels_data() { Some(data) => { - println!(" Name: {}", data.name); - println!(" Description: {}", data.description); + println!(" {}: {}", data.name, data.description); } None => {} } From 2dcbd81ba3fed0e913c9f8a357f3cb052c39a09a Mon Sep 17 00:00:00 2001 From: aragami3070 Date: Sat, 23 Aug 2025 01:00:23 +0400 Subject: [PATCH 09/14] Chore(cargo): add fzf-warpped package --- Cargo.lock | 141 +++++++++++++++++++++++++++++++++++++++++++++-------- Cargo.toml | 1 + 2 files changed, 121 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7ba21ac..b6cb215 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -90,7 +90,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.103", ] [[package]] @@ -101,7 +101,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.103", ] [[package]] @@ -208,7 +208,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim", + "strsim 0.11.1", ] [[package]] @@ -220,7 +220,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.103", ] [[package]] @@ -235,6 +235,41 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + [[package]] name = "deranged" version = "0.4.0" @@ -244,6 +279,37 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "derive_builder" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder_macro" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" +dependencies = [ + "derive_builder_core", + "syn 1.0.109", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -252,7 +318,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.103", ] [[package]] @@ -338,7 +404,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.103", ] [[package]] @@ -377,6 +443,15 @@ dependencies = [ "slab", ] +[[package]] +name = "fzf-wrapped" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c61a44d13f57f2bb4c181a380dbb2e0367d1af53ca6721b5c9fc6b9c7e345d" +dependencies = [ + "derive_builder", +] + [[package]] name = "getrandom" version = "0.2.16" @@ -415,6 +490,7 @@ name = "github-cli" version = "1.12.0" dependencies = [ "clap", + "fzf-wrapped", "octorust", "paste", "rstest", @@ -636,6 +712,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "1.0.3" @@ -1381,7 +1463,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn", + "syn 2.0.103", "unicode-ident", ] @@ -1478,7 +1560,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn", + "syn 2.0.103", ] [[package]] @@ -1510,7 +1592,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.103", ] [[package]] @@ -1521,7 +1603,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.103", ] [[package]] @@ -1606,6 +1688,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strsim" version = "0.11.1" @@ -1618,6 +1706,17 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.103" @@ -1646,7 +1745,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.103", ] [[package]] @@ -1675,7 +1774,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.103", ] [[package]] @@ -1686,7 +1785,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.103", ] [[package]] @@ -1771,7 +1870,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.103", ] [[package]] @@ -1865,7 +1964,7 @@ checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.103", ] [[package]] @@ -1983,7 +2082,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn", + "syn 2.0.103", "wasm-bindgen-shared", ] @@ -2018,7 +2117,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.103", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2224,7 +2323,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.103", "synstructure", ] @@ -2245,7 +2344,7 @@ checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.103", ] [[package]] @@ -2265,7 +2364,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.103", "synstructure", ] @@ -2305,5 +2404,5 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.103", ] diff --git a/Cargo.toml b/Cargo.toml index c43ff3f..cab1999 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,3 +9,4 @@ clap = { version = "4.5.39", features = ["derive"] } tokio = { version = "1.45.1", features = ["full"] } rstest = "0.26.1" paste = "1.0.15" +fzf-wrapped = "0.1.4" From 49b117f25355164f3309ede45f79179ae75ee641 Mon Sep 17 00:00:00 2001 From: aragami3070 Date: Sat, 23 Aug 2025 01:01:18 +0400 Subject: [PATCH 10/14] Feat(cli_out): add fyzzy_select with choose_issue --- src/cli_out/fuzzy_select.rs | 37 +++++++++++++++++++++++++++++++++++++ src/cli_out/mod.rs | 1 + 2 files changed, 38 insertions(+) create mode 100644 src/cli_out/fuzzy_select.rs diff --git a/src/cli_out/fuzzy_select.rs b/src/cli_out/fuzzy_select.rs new file mode 100644 index 0000000..1a99043 --- /dev/null +++ b/src/cli_out/fuzzy_select.rs @@ -0,0 +1,37 @@ +use std::error::Error; + +use fzf_wrapped::{run_with_output, Border, Fzf}; +use octorust::types::IssueSimple; + +pub fn choose_issue(list_issues: Vec) -> Result, Box> { + let issue_titles: Vec = list_issues + .iter() + .map(|iss| format!("({}) Title: {}", iss.number, iss.title)) + .collect(); + + let fzf = Fzf::builder() + .border(Border::Rounded) + .border_label("List issues") + .header("Pick needed issue form list") + .build()?; + + let choosed_issue = run_with_output(fzf, issue_titles); + + let issue_num = match choosed_issue { + Some(ch_i) => { + let index = match ch_i.find(')') { + Some(c) => c, + None => return Ok(None), + }; + ch_i[1..index].parse::() + } + None => return Ok(None), + }?; + + for issue in list_issues { + if issue.number == issue_num { + return Ok(Some(issue)); + } + } + Ok(None) +} diff --git a/src/cli_out/mod.rs b/src/cli_out/mod.rs index 5c37a6d..513cfbf 100644 --- a/src/cli_out/mod.rs +++ b/src/cli_out/mod.rs @@ -1 +1,2 @@ pub mod print_in_cli; +pub mod fuzzy_select; From ef1ef2c981825a8d5c45ff575e2eb6b8af746371 Mon Sep 17 00:00:00 2001 From: aragami3070 Date: Sat, 23 Aug 2025 01:04:28 +0400 Subject: [PATCH 11/14] Feat(cli_parse): add handle_get_from_list for handle_issue mod --- src/cli_parse/handle_commands/handle_issue.rs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/cli_parse/handle_commands/handle_issue.rs b/src/cli_parse/handle_commands/handle_issue.rs index 0731778..503668f 100644 --- a/src/cli_parse/handle_commands/handle_issue.rs +++ b/src/cli_parse/handle_commands/handle_issue.rs @@ -4,9 +4,11 @@ use std::error::Error; use crate::cli_in::issue_command::IssueCommand; use crate::cli_in::set_vars::IssuesListStates; use crate::cli_in::set_vars::States; +use crate::cli_out::fuzzy_select::choose_issue; use crate::cli_out::print_in_cli::print_comments; use crate::cli_out::print_in_cli::print_issue; use crate::cli_out::print_in_cli::print_issues; +use crate::cli_out::print_in_cli::print_simple_issue; use crate::git_utils::comments; use crate::git_utils::issues; use crate::git_utils::repo_info::Repo; @@ -153,6 +155,48 @@ async fn handle_get( Ok(()) } +async fn handle_get_form_list( + github_client: Client, + owner: Option, + repo: Option, + creator: String, + assignee: String, + state: IssuesListStates, + labels: String, + numb_of_page: i64, + iss_on_page: i64, +) -> Result<(), Box> { + let repo_info = match owner { + Some(_) => RepoInfo::new(Repo::Input, owner, repo)?, + None => RepoInfo::new(Repo::Current, None, None)?, + }; + + let list_issues = issues::get_list( + &github_client, + &repo_info, + &creator, + &assignee, + &state.0, + &labels, + &numb_of_page, + &iss_on_page, + ) + .await?; + + let choosed_issue = choose_issue(list_issues)?; + + if let Some(ch_i) = choosed_issue { + let list_comments = comments::get_all(&github_client, &repo_info, &ch_i.number).await?; + + print_simple_issue(ch_i); + print_comments(list_comments)?; + } else { + println!("Issue not choosed or not find"); + } + + Ok(()) +} + async fn handle_create( github_client: Client, owner: Option, From 84242e220207fe61ca22f1760c189f05114ae177 Mon Sep 17 00:00:00 2001 From: aragami3070 Date: Sat, 23 Aug 2025 01:04:48 +0400 Subject: [PATCH 12/14] Feat(cli_parse): add get-from-list issue handle --- src/cli_in/issue_command.rs | 30 ++++++++++++++++++- src/cli_parse/handle_commands/handle_issue.rs | 25 ++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/cli_in/issue_command.rs b/src/cli_in/issue_command.rs index 7f5d3d8..d4ebe5c 100644 --- a/src/cli_in/issue_command.rs +++ b/src/cli_in/issue_command.rs @@ -41,11 +41,39 @@ pub enum IssueCommand { /// Repo name (optional) #[clap(long, short, default_value = None)] repo: Option, - /// Update issue with number + /// Get issue with number #[clap(long, short)] number: i64, }, + /// Get issue with comment from issues list + GetFromList { + /// Repo owner (optional) + #[clap(long, short, default_value = None)] + owner: Option, + /// Repo name (optional) + #[clap(long, short, default_value = None)] + repo: Option, + /// The user that created the issues (optional) + #[clap(long, short, default_value = "")] + creator: String, + /// Can be the name of a user. Pass in `none` for issues with no assigned user, and `*` for issues assigned to any user (optional) + #[clap(long, short, default_value = "none")] + assignee: String, + /// Indicates the state of the issues to return. Can be either `open`, `closed`, or `all` (optional) + #[clap(long, short, default_value = "open")] + state: IssuesListStates, + /// A list of comma separated label names. Example: `bug,ui,@high` (optional) + #[clap(long, short, default_value = "")] + labels: String, + /// Page number of the results to fetch (optional) + #[clap(long, short, default_value = "1")] + numb_of_page: i64, + /// Results on page (max 100) (optional) + #[clap(long, short, default_value = "30", value_parser = clap::value_parser!(i64).range(1..=100))] + iss_on_page: i64, + }, + /// Create issue Create { /// Repo owner (optional) diff --git a/src/cli_parse/handle_commands/handle_issue.rs b/src/cli_parse/handle_commands/handle_issue.rs index 503668f..a7679d1 100644 --- a/src/cli_parse/handle_commands/handle_issue.rs +++ b/src/cli_parse/handle_commands/handle_issue.rs @@ -54,6 +54,31 @@ pub async fn handle_issue_command( Ok(()) } + IssueCommand::GetFromList { + owner, + repo, + creator, + assignee, + state, + labels, + numb_of_page, + iss_on_page, + } => { + handle_get_form_list( + github_client, + owner, + repo, + creator, + assignee, + state, + labels, + numb_of_page, + iss_on_page, + ) + .await?; + Ok(()) + } + IssueCommand::Create { owner, repo, From 4d37fa810cc8e5b4b5abfdf96cbd901698f378f6 Mon Sep 17 00:00:00 2001 From: aragami3070 Date: Sat, 23 Aug 2025 01:06:41 +0400 Subject: [PATCH 13/14] Chore(readme): update road map --- Readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 68c7774..6b140b1 100644 --- a/Readme.md +++ b/Readme.md @@ -60,7 +60,8 @@ github-cli release --help ### issue - [x] Сделать автораспознование гит репозитория - [x] Сделать получение всех issues -- [ ] Сделать выбор issue через fzf или аналоги из списка всех issues +- [x] Сделать получение issue +- [x] Сделать выбор issue через fzf из списка всех issues - [x] Сделать создание issue - [x] Сделать закрытие issue - [x] Сделать редактирование issue From a60ac302cb8e0ebb417364550718d7711137ae3c Mon Sep 17 00:00:00 2001 From: aragami3070 Date: Sat, 23 Aug 2025 01:07:18 +0400 Subject: [PATCH 14/14] Feat(cargo): update package version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b6cb215..7bacea6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -487,7 +487,7 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "github-cli" -version = "1.12.0" +version = "1.13.0" dependencies = [ "clap", "fzf-wrapped", diff --git a/Cargo.toml b/Cargo.toml index cab1999..c62f162 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "github-cli" -version = "1.12.0" +version = "1.13.0" edition = "2021" [dependencies]