gh_cli_rs/commands/
issue.rs

1use crate::command::{BaseCommand, CommandBuilder, GhCommand};
2use crate::error::Result;
3use crate::executor::GhExecutor;
4use std::sync::Arc;
5
6/// Issue commands namespace
7#[derive(Clone)]
8pub struct IssueCommands {
9    executor: Arc<GhExecutor>,
10}
11
12impl IssueCommands {
13    pub(crate) fn new(executor: Arc<GhExecutor>) -> Self {
14        Self { executor }
15    }
16
17    /// Create a new issue
18    pub fn create(&self) -> IssueCreateCommand {
19        IssueCreateCommand::new(self.executor.clone())
20    }
21
22    /// List issues
23    pub fn list(&self) -> IssueListCommand {
24        IssueListCommand::new(self.executor.clone())
25    }
26
27    /// View an issue
28    pub fn view(&self, number: u32) -> IssueViewCommand {
29        IssueViewCommand::new(self.executor.clone(), number)
30    }
31
32    /// Close an issue
33    pub fn close(&self, number: u32) -> IssueCloseCommand {
34        IssueCloseCommand::new(self.executor.clone(), number)
35    }
36
37    /// Reopen an issue
38    pub fn reopen(&self, number: u32) -> IssueReopenCommand {
39        IssueReopenCommand::new(self.executor.clone(), number)
40    }
41}
42
43/// Command for creating an issue
44pub struct IssueCreateCommand {
45    executor: Arc<GhExecutor>,
46    cmd: BaseCommand,
47}
48
49impl IssueCreateCommand {
50    fn new(executor: Arc<GhExecutor>) -> Self {
51        Self {
52            executor,
53            cmd: BaseCommand::with_subcommands(&["issue", "create"]),
54        }
55    }
56
57    /// Set the issue title
58    pub fn title(mut self, title: &str) -> Self {
59        self.cmd = self.cmd.option("--title", title);
60        self
61    }
62
63    /// Set the issue body
64    pub fn body(mut self, body: &str) -> Self {
65        self.cmd = self.cmd.option("--body", body);
66        self
67    }
68
69    /// Add labels
70    pub fn label(mut self, label: &str) -> Self {
71        self.cmd = self.cmd.option("--label", label);
72        self
73    }
74
75    /// Assign to user
76    pub fn assignee(mut self, assignee: &str) -> Self {
77        self.cmd = self.cmd.option("--assignee", assignee);
78        self
79    }
80
81    /// Open in web browser
82    pub fn web(mut self) -> Self {
83        self.cmd = self.cmd.flag("--web");
84        self
85    }
86
87    /// Execute the create command
88    pub fn execute(&self) -> Result<String> {
89        GhCommand::execute(self, self.executor.as_ref())
90    }
91}
92
93impl GhCommand for IssueCreateCommand {
94    fn build_args(&self) -> Vec<String> {
95        self.cmd.build_args()
96    }
97}
98
99/// Command for listing issues
100pub struct IssueListCommand {
101    executor: Arc<GhExecutor>,
102    cmd: BaseCommand,
103}
104
105impl IssueListCommand {
106    fn new(executor: Arc<GhExecutor>) -> Self {
107        Self {
108            executor,
109            cmd: BaseCommand::with_subcommands(&["issue", "list"]),
110        }
111    }
112
113    /// Filter by state (open, closed, all)
114    pub fn state(mut self, state: &str) -> Self {
115        self.cmd = self.cmd.option("--state", state);
116        self
117    }
118
119    /// Limit the number of results
120    pub fn limit(mut self, limit: u32) -> Self {
121        self.cmd = self.cmd.option("--limit", &limit.to_string());
122        self
123    }
124
125    /// Filter by author
126    pub fn author(mut self, author: &str) -> Self {
127        self.cmd = self.cmd.option("--author", author);
128        self
129    }
130
131    /// Filter by assignee
132    pub fn assignee(mut self, assignee: &str) -> Self {
133        self.cmd = self.cmd.option("--assignee", assignee);
134        self
135    }
136
137    /// Filter by label
138    pub fn label(mut self, label: &str) -> Self {
139        self.cmd = self.cmd.option("--label", label);
140        self
141    }
142
143    /// Execute and get raw output
144    pub fn execute(&self) -> Result<String> {
145        GhCommand::execute(self, self.executor.as_ref())
146    }
147}
148
149impl GhCommand for IssueListCommand {
150    fn build_args(&self) -> Vec<String> {
151        self.cmd.build_args()
152    }
153}
154
155/// Command for viewing an issue
156pub struct IssueViewCommand {
157    executor: Arc<GhExecutor>,
158    cmd: BaseCommand,
159}
160
161impl IssueViewCommand {
162    fn new(executor: Arc<GhExecutor>, number: u32) -> Self {
163        Self {
164            executor,
165            cmd: BaseCommand::with_subcommands(&["issue", "view"]).arg(&number.to_string()),
166        }
167    }
168
169    /// Open in web browser
170    pub fn web(mut self) -> Self {
171        self.cmd = self.cmd.flag("--web");
172        self
173    }
174
175    /// Execute and get raw output
176    pub fn execute(&self) -> Result<String> {
177        GhCommand::execute(self, self.executor.as_ref())
178    }
179}
180
181impl GhCommand for IssueViewCommand {
182    fn build_args(&self) -> Vec<String> {
183        self.cmd.build_args()
184    }
185}
186
187/// Command for closing an issue
188pub struct IssueCloseCommand {
189    executor: Arc<GhExecutor>,
190    cmd: BaseCommand,
191}
192
193impl IssueCloseCommand {
194    fn new(executor: Arc<GhExecutor>, number: u32) -> Self {
195        Self {
196            executor,
197            cmd: BaseCommand::with_subcommands(&["issue", "close"]).arg(&number.to_string()),
198        }
199    }
200
201    /// Execute the close command
202    pub fn execute(&self) -> Result<String> {
203        GhCommand::execute(self, self.executor.as_ref())
204    }
205}
206
207impl GhCommand for IssueCloseCommand {
208    fn build_args(&self) -> Vec<String> {
209        self.cmd.build_args()
210    }
211}
212
213/// Command for reopening an issue
214pub struct IssueReopenCommand {
215    executor: Arc<GhExecutor>,
216    cmd: BaseCommand,
217}
218
219impl IssueReopenCommand {
220    fn new(executor: Arc<GhExecutor>, number: u32) -> Self {
221        Self {
222            executor,
223            cmd: BaseCommand::with_subcommands(&["issue", "reopen"]).arg(&number.to_string()),
224        }
225    }
226
227    /// Execute the reopen command
228    pub fn execute(&self) -> Result<String> {
229        GhCommand::execute(self, self.executor.as_ref())
230    }
231}
232
233impl GhCommand for IssueReopenCommand {
234    fn build_args(&self) -> Vec<String> {
235        self.cmd.build_args()
236    }
237}