gr_bin/formatters/
formatter.rs1use super::utils::to_fixed_length;
2use crate::vcs::common::{PullRequest, PullRequestState, Repository};
3use colored::Colorize;
4
5pub enum FormatterType {
6 Json,
7 Normal,
8 Short,
9}
10
11pub trait Formatter {
12 fn show_json(&self) -> String;
13 fn show_normal(&self) -> String;
14 fn show_short(&self) -> String;
15 fn show(&self, formatter_type: FormatterType) -> String {
16 match formatter_type {
17 FormatterType::Json => self.show_json(),
18 FormatterType::Normal => self.show_normal(),
19 FormatterType::Short => self.show_short(),
20 }
21 }
22}
23
24const FULL_SIZE: usize = 80;
25const ID_SIZE: usize = 6;
26const TITLE_SIZE: usize = FULL_SIZE - ID_SIZE - 1;
27const SHORT_BRANCH_SIZE: usize = 20;
28const SHORT_TITLE_SIZE: usize = FULL_SIZE - ID_SIZE - 1 - SHORT_BRANCH_SIZE - 1;
29
30impl Formatter for PullRequest {
31 fn show_json(&self) -> String {
32 serde_json::to_string(&self).unwrap()
33 }
34 fn show_normal(&self) -> String {
35 let title = to_fixed_length(&self.title, TITLE_SIZE, true);
36 let title = match self.state {
37 PullRequestState::Open => title.bold(),
38 PullRequestState::Closed => title.bold().red(),
39 PullRequestState::Merged => title.bold().green(),
40 PullRequestState::Locked => title.bold().magenta(),
41 };
42 let colored_id = format!("#{}", self.id).dimmed();
43 let title_line = format!("{} {:>width$}", title, colored_id, width = ID_SIZE);
44 let details_line = format!(
45 "{} {} {} {} {} {}",
46 "opened by".dimmed(),
47 self.author.username,
48 "on".dimmed(),
49 self.created_at.date(),
50 "updated on".dimmed(),
51 self.updated_at.date(),
52 );
53 let branch_line = format!("{} -> {}", self.source.blue(), self.target.blue());
54 let description = if !self.description.is_empty() {
55 format!("\n{}\n---", self.description)
56 } else {
57 "".to_string()
58 };
59 let url_line = format!("{}", self.url.dimmed());
60
61 format!(
62 "{title_line}
63{details_line}
64{branch_line}
65{description}
66{url_line}
67"
68 )
69 }
70 fn show_short(&self) -> String {
71 let title = to_fixed_length(&self.title, SHORT_TITLE_SIZE, true);
72 let title = match self.state {
73 PullRequestState::Open => title.bold(),
74 PullRequestState::Closed => title.bold().red(),
75 PullRequestState::Merged => title.bold().green(),
76 PullRequestState::Locked => title.bold().magenta(),
77 };
78 let branch = to_fixed_length(&self.source, SHORT_BRANCH_SIZE, true).blue();
79 let colored_id = format!("#{}", self.id).dimmed();
80 format!("{} {} {:>6}\n", title, branch, colored_id)
81 }
82}
83
84impl Formatter for Repository {
85 fn show_json(&self) -> String {
86 serde_json::to_string(&self).unwrap()
87 }
88 fn show_normal(&self) -> String {
89 let title_line = to_fixed_length(&self.full_name, TITLE_SIZE, true).bold();
90 let forked_line = if let Some(ref forked) = self.forked_from {
91 format!("{} {}\n", "forked from".dimmed(), forked.full_name)
92 } else {
93 String::new()
94 };
95 let counts_line = format!(
96 "{} stars, {} forks",
97 self.stars_count.to_string().yellow(),
98 self.forks_count.to_string().yellow(),
99 );
100 let description = if !self.description.is_empty() {
101 format!("\n{}\n---", self.description)
102 } else {
103 "".to_string()
104 };
105 let url_line = format!("{}", self.html_url.dimmed());
106
107 format!(
108 "{title_line}
109{forked_line}{counts_line}
110{description}
111{url_line}
112"
113 )
114 }
115 fn show_short(&self) -> String {
116 let title = to_fixed_length(&self.full_name, SHORT_TITLE_SIZE, true);
117 format!("{}\n", title)
118 }
119}