|
1 | 1 | package comment |
2 | 2 |
|
3 | 3 | import ( |
4 | | - "errors" |
5 | | - "fmt" |
6 | 4 | "net/http" |
7 | 5 |
|
8 | | - "github.com/AlecAivazis/survey/v2" |
9 | 6 | "github.com/MakeNowJust/heredoc" |
10 | 7 | "github.com/cli/cli/api" |
11 | | - "github.com/cli/cli/internal/config" |
12 | 8 | "github.com/cli/cli/internal/ghrepo" |
13 | | - "github.com/cli/cli/pkg/cmd/issue/shared" |
| 9 | + issueShared "github.com/cli/cli/pkg/cmd/issue/shared" |
| 10 | + prShared "github.com/cli/cli/pkg/cmd/pr/shared" |
14 | 11 | "github.com/cli/cli/pkg/cmdutil" |
15 | | - "github.com/cli/cli/pkg/iostreams" |
16 | | - "github.com/cli/cli/pkg/surveyext" |
17 | 12 | "github.com/cli/cli/utils" |
18 | 13 | "github.com/spf13/cobra" |
19 | 14 | ) |
20 | 15 |
|
21 | | -type CommentOptions struct { |
22 | | - HttpClient func() (*http.Client, error) |
23 | | - IO *iostreams.IOStreams |
24 | | - BaseRepo func() (ghrepo.Interface, error) |
25 | | - EditSurvey func() (string, error) |
26 | | - InputTypeSurvey func() (inputType, error) |
27 | | - ConfirmSubmitSurvey func() (bool, error) |
28 | | - OpenInBrowser func(string) error |
29 | | - |
30 | | - SelectorArg string |
31 | | - Interactive bool |
32 | | - InputType inputType |
33 | | - Body string |
34 | | -} |
35 | | - |
36 | | -type inputType int |
37 | | - |
38 | | -const ( |
39 | | - inputTypeEditor inputType = iota |
40 | | - inputTypeInline |
41 | | - inputTypeWeb |
42 | | -) |
43 | | - |
44 | | -func NewCmdComment(f *cmdutil.Factory, runF func(*CommentOptions) error) *cobra.Command { |
45 | | - opts := &CommentOptions{ |
46 | | - IO: f.IOStreams, |
47 | | - HttpClient: f.HttpClient, |
48 | | - EditSurvey: editSurvey(f.Config, f.IOStreams), |
49 | | - InputTypeSurvey: inputTypeSurvey, |
50 | | - ConfirmSubmitSurvey: confirmSubmitSurvey, |
51 | | - OpenInBrowser: utils.OpenInBrowser, |
| 16 | +func NewCmdComment(f *cmdutil.Factory, runF func(*prShared.CommentableOptions) error) *cobra.Command { |
| 17 | + opts := &prShared.CommentableOptions{ |
| 18 | + IO: f.IOStreams, |
| 19 | + HttpClient: f.HttpClient, |
| 20 | + EditSurvey: prShared.CommentableEditSurvey(f.Config, f.IOStreams), |
| 21 | + InteractiveEditSurvey: prShared.CommentableInteractiveEditSurvey(f.Config, f.IOStreams), |
| 22 | + ConfirmSubmitSurvey: prShared.CommentableConfirmSubmitSurvey, |
| 23 | + OpenInBrowser: utils.OpenInBrowser, |
52 | 24 | } |
53 | 25 |
|
54 | | - var webMode bool |
55 | | - var editorMode bool |
56 | | - |
57 | 26 | cmd := &cobra.Command{ |
58 | 27 | Use: "comment {<number> | <url>}", |
59 | 28 | Short: "Create a new issue comment", |
60 | 29 | Example: heredoc.Doc(` |
61 | 30 | $ gh issue comment 22 --body "I was able to reproduce this issue, lets fix it." |
62 | 31 | `), |
63 | 32 | Args: cobra.ExactArgs(1), |
64 | | - RunE: func(cmd *cobra.Command, args []string) error { |
65 | | - // support `-R, --repo` override |
66 | | - opts.BaseRepo = f.BaseRepo |
67 | | - opts.SelectorArg = args[0] |
68 | | - |
69 | | - inputFlags := 0 |
70 | | - if cmd.Flags().Changed("body") { |
71 | | - opts.InputType = inputTypeInline |
72 | | - inputFlags++ |
73 | | - } |
74 | | - if webMode { |
75 | | - opts.InputType = inputTypeWeb |
76 | | - inputFlags++ |
77 | | - } |
78 | | - if editorMode { |
79 | | - opts.InputType = inputTypeEditor |
80 | | - inputFlags++ |
81 | | - } |
82 | | - |
83 | | - if inputFlags == 0 { |
84 | | - if !opts.IO.CanPrompt() { |
85 | | - return &cmdutil.FlagError{Err: errors.New("--body or --web required when not running interactively")} |
86 | | - } |
87 | | - opts.Interactive = true |
88 | | - } else if inputFlags == 1 { |
89 | | - if !opts.IO.CanPrompt() && opts.InputType == inputTypeEditor { |
90 | | - return &cmdutil.FlagError{Err: errors.New("--body or --web required when not running interactively")} |
91 | | - } |
92 | | - } else if inputFlags > 1 { |
93 | | - return &cmdutil.FlagError{Err: fmt.Errorf("specify only one of --body, --editor, or --web")} |
94 | | - } |
95 | | - |
| 33 | + PreRunE: func(cmd *cobra.Command, args []string) error { |
| 34 | + opts.RetrieveCommentable = retrieveIssue(f.HttpClient, f.BaseRepo, args[0]) |
| 35 | + return prShared.CommentablePreRun(cmd, opts) |
| 36 | + }, |
| 37 | + RunE: func(_ *cobra.Command, args []string) error { |
96 | 38 | if runF != nil { |
97 | 39 | return runF(opts) |
98 | 40 | } |
99 | | - return commentRun(opts) |
| 41 | + return prShared.CommentableRun(opts) |
100 | 42 | }, |
101 | 43 | } |
102 | 44 |
|
103 | 45 | cmd.Flags().StringVarP(&opts.Body, "body", "b", "", "Supply a body. Will prompt for one otherwise.") |
104 | | - cmd.Flags().BoolVarP(&editorMode, "editor", "e", false, "Add body using editor") |
105 | | - cmd.Flags().BoolVarP(&webMode, "web", "w", false, "Add body in browser") |
| 46 | + cmd.Flags().BoolP("editor", "e", false, "Add body using editor") |
| 47 | + cmd.Flags().BoolP("web", "w", false, "Add body in browser") |
106 | 48 |
|
107 | 49 | return cmd |
108 | 50 | } |
109 | 51 |
|
110 | | -func commentRun(opts *CommentOptions) error { |
111 | | - httpClient, err := opts.HttpClient() |
112 | | - if err != nil { |
113 | | - return err |
114 | | - } |
115 | | - apiClient := api.NewClientFromHTTP(httpClient) |
116 | | - |
117 | | - issue, baseRepo, err := shared.IssueFromArg(apiClient, opts.BaseRepo, opts.SelectorArg) |
118 | | - if err != nil { |
119 | | - return err |
120 | | - } |
121 | | - |
122 | | - if opts.Interactive { |
123 | | - inputType, err := opts.InputTypeSurvey() |
| 52 | +func retrieveIssue(httpClient func() (*http.Client, error), |
| 53 | + baseRepo func() (ghrepo.Interface, error), |
| 54 | + selector string) func() (prShared.Commentable, ghrepo.Interface, error) { |
| 55 | + return func() (prShared.Commentable, ghrepo.Interface, error) { |
| 56 | + httpClient, err := httpClient() |
124 | 57 | if err != nil { |
125 | | - return err |
| 58 | + return nil, nil, err |
126 | 59 | } |
127 | | - opts.InputType = inputType |
128 | | - } |
| 60 | + apiClient := api.NewClientFromHTTP(httpClient) |
129 | 61 |
|
130 | | - switch opts.InputType { |
131 | | - case inputTypeWeb: |
132 | | - openURL := issue.URL + "#issuecomment-new" |
133 | | - if opts.IO.IsStdoutTTY() { |
134 | | - fmt.Fprintf(opts.IO.ErrOut, "Opening %s in your browser.\n", utils.DisplayURL(openURL)) |
135 | | - } |
136 | | - return opts.OpenInBrowser(openURL) |
137 | | - case inputTypeEditor: |
138 | | - body, err := opts.EditSurvey() |
| 62 | + issue, repo, err := issueShared.IssueFromArg(apiClient, baseRepo, selector) |
139 | 63 | if err != nil { |
140 | | - return err |
| 64 | + return nil, nil, err |
141 | 65 | } |
142 | | - opts.Body = body |
143 | | - } |
144 | | - |
145 | | - if opts.Interactive { |
146 | | - cont, err := opts.ConfirmSubmitSurvey() |
147 | | - if err != nil { |
148 | | - return err |
149 | | - } |
150 | | - if !cont { |
151 | | - return fmt.Errorf("Discarding...") |
152 | | - } |
153 | | - } |
154 | | - |
155 | | - params := api.CommentCreateInput{Body: opts.Body, SubjectId: issue.ID} |
156 | | - url, err := api.CommentCreate(apiClient, baseRepo.RepoHost(), params) |
157 | | - if err != nil { |
158 | | - return err |
159 | | - } |
160 | | - fmt.Fprintln(opts.IO.Out, url) |
161 | | - return nil |
162 | | -} |
163 | | - |
164 | | -var inputTypeSurvey = func() (inputType, error) { |
165 | | - var result int |
166 | | - inputTypeQuestion := &survey.Select{ |
167 | | - Message: "Where do you want to draft your comment?", |
168 | | - Options: []string{"Editor", "Web"}, |
169 | | - } |
170 | | - err := survey.AskOne(inputTypeQuestion, &result) |
171 | | - if err != nil { |
172 | | - return 0, err |
173 | | - } |
174 | | - |
175 | | - if result == 0 { |
176 | | - return inputTypeEditor, nil |
177 | | - } else { |
178 | | - return inputTypeWeb, nil |
179 | | - } |
180 | | -} |
181 | 66 |
|
182 | | -var confirmSubmitSurvey = func() (bool, error) { |
183 | | - var confirm bool |
184 | | - submit := &survey.Confirm{ |
185 | | - Message: "Submit?", |
186 | | - Default: true, |
187 | | - } |
188 | | - err := survey.AskOne(submit, &confirm) |
189 | | - return confirm, err |
190 | | -} |
191 | | - |
192 | | -var editSurvey = func(cf func() (config.Config, error), io *iostreams.IOStreams) func() (string, error) { |
193 | | - return func() (string, error) { |
194 | | - editorCommand, err := cmdutil.DetermineEditor(cf) |
195 | | - if err != nil { |
196 | | - return "", err |
197 | | - } |
198 | | - return surveyext.Edit(editorCommand, "*.md", "", io.In, io.Out, io.ErrOut, nil) |
| 67 | + return issue, repo, nil |
199 | 68 | } |
200 | 69 | } |
0 commit comments