Add output formatters

This commit is contained in:
Daan Boerlage 2025-01-21 22:03:11 +01:00
parent 476fa90200
commit f05461f1f7
Signed by: daan
GPG key ID: FCE070E1E4956606
5 changed files with 62 additions and 47 deletions

View file

@ -78,8 +78,8 @@ Find issues currently assigned to you
Usage: jirac list [OPTIONS]
Options:
--json Print json rather than pretty print
-h, --help Print help
-o, --output <OUTPUT> Pick an output formatter [default: pretty] [possible values: pretty, json]
-h, --help Print help
```
### Search for issues
@ -93,8 +93,8 @@ Arguments:
<JQL> A JQL string
Options:
--json Print JSON rather than pretty print
-h, --help Print help
-o, --output <OUTPUT> Pick an output formatter [default: pretty] [possible values: pretty, json]
-h, --help Print help
```
Use [JQL](https://support.atlassian.com/jira-software-cloud/docs/use-advanced-search-with-jira-query-language-jql/) to search for Issues.
@ -116,8 +116,8 @@ Arguments:
<ISSUE> An issue key, for example, KEY-123
Options:
--json Print JSON rather than pretty print
-h, --help Print help
-o, --output <OUTPUT> Pick an output formatter [default: pretty] [possible values: pretty, json]
-h, --help Print help
```
```sh

View file

@ -1,4 +1,4 @@
use clap::{Parser, Subcommand};
use clap::{Parser, Subcommand, ValueEnum};
use std::path::PathBuf;
#[derive(Parser)]
@ -8,12 +8,27 @@ pub struct Cli {
pub command: Commands,
}
#[derive(ValueEnum, Debug, Copy, Clone, Eq, PartialEq)]
pub enum FormatMode {
Pretty,
Json,
}
impl std::fmt::Display for FormatMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.to_possible_value()
.expect("no values are skipped")
.get_name()
.fmt(f)
}
}
#[derive(Subcommand)]
pub enum Commands {
/// Create an issue
Create {
/// The project key in which to create the issue
#[arg(long)]
#[arg(short, long)]
project: Option<String>,
/// Open the new issue in a browser
@ -26,15 +41,15 @@ pub enum Commands {
},
/// Find issues currently assigned to you
List {
/// Print JSON rather than pretty print
#[arg(long)]
json: bool,
/// Pick an output formatter
#[arg(short, long, default_value_t = FormatMode::Pretty)]
output: FormatMode,
},
/// Search for issues
Search {
/// Print JSON rather than pretty print
#[arg(long)]
json: bool,
/// Pick an output formatter
#[arg(short, long, default_value_t = FormatMode::Pretty)]
output: FormatMode,
/// A JQL string
#[arg(value_name = "JQL")]
@ -42,9 +57,9 @@ pub enum Commands {
},
/// View an issue
View {
/// Print JSON rather than pretty print
#[arg(long)]
json: bool,
/// Pick an output formatter
#[arg(short, long, default_value_t = FormatMode::Pretty)]
output: FormatMode,
/// An issue key, for example, KEY-123
#[arg(value_name = "ISSUE")]

View file

@ -1,31 +1,31 @@
use crate::cli::FormatMode;
use crate::jira_config::JiraConfig;
use crate::types::issue::{display_issues_json, display_issues_pretty};
pub async fn exec(json: bool, jql: &str) -> Result<(), Box<dyn std::error::Error>> {
pub async fn exec(output: FormatMode, jql: &str) -> Result<(), Box<dyn std::error::Error>> {
let config = JiraConfig::load().map_err(|e| format!("Configuration error: {}", e))?;
if !json {
if output != FormatMode::Json {
println!("Searching for issues...");
}
match crate::jql::run(&config, jql).await {
Ok(response) => {
if json {
if response.issues.is_empty() {
println!("[]");
} else {
display_issues_json(&response.issues)?;
}
} else if response.issues.is_empty() {
println!("No results found for query.");
} else {
display_issues_pretty(&response.issues)?;
println!("Total issues: {}", response.total);
}
}
Err(e) => {
eprintln!("Error fetching issues: {}", e);
let result = match crate::jql::run(&config, jql).await {
Ok(x) => x,
Err(reason) => {
eprintln!("Error fetching issues: {}", reason);
std::process::exit(1);
}
};
match (output, result.issues.is_empty()) {
(FormatMode::Pretty, false) => {
display_issues_pretty(&result.issues)?;
println!("Total issues: {}", result.total);
}
(FormatMode::Pretty, true) => {
println!("No results found for query.");
}
(FormatMode::Json, false) => display_issues_json(&result.issues)?,
(FormatMode::Json, true) => println!("[]"),
}
Ok(())

View file

@ -1,3 +1,4 @@
use crate::cli::FormatMode;
use crate::jira_config::JiraConfig;
use crate::types::issue::JiraIssue;
use crossterm::style::{Color, Stylize};
@ -112,9 +113,9 @@ pub fn json_print(issues: &JiraIssue) -> Result<(), Box<dyn std::error::Error>>
Ok(())
}
pub async fn exec(json: bool, issue_key: &str) -> Result<(), Box<dyn std::error::Error>> {
pub async fn exec(output: FormatMode, issue_key: &str) -> Result<(), Box<dyn std::error::Error>> {
let config = JiraConfig::load().map_err(|e| format!("Configuration error: {}", e))?;
if !json {
if output != FormatMode::Json {
println!("Loading issue data");
}
@ -138,11 +139,10 @@ pub async fn exec(json: bool, issue_key: &str) -> Result<(), Box<dyn std::error:
let fetched_issue = fetch_issue(&config, &matched_issue.href).await?;
if json {
json_print(&fetched_issue)?;
} else {
pretty_print(&fetched_issue)?;
};
match output {
FormatMode::Pretty => pretty_print(&fetched_issue)?,
FormatMode::Json => json_print(&fetched_issue)?,
}
Ok(())
}

View file

@ -18,12 +18,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
open,
markdown_file,
} => cmd::create::create(project, open, markdown_file).await?,
Commands::List { json } => {
Commands::List { output } => {
let jql = "assignee = currentUser() AND resolution = Unresolved order by updated DESC";
cmd::search::exec(json, jql).await?
cmd::search::exec(output, jql).await?
}
Commands::Search { json, jql } => cmd::search::exec(json, &jql).await?,
Commands::View { json, issue } => cmd::view::exec(json, &issue).await?,
Commands::Search { output, jql } => cmd::search::exec(output, &jql).await?,
Commands::View { output, issue } => cmd::view::exec(output, &issue).await?,
Commands::Init { url, email, token } => {
JiraConfig::init(url, email, token).await?;
println!("Configuration initialized successfully!");