Merge pull request #97 from github/issue-create-editor

Use survey when creating issues
This commit is contained in:
Nate Smith 2019-11-25 11:34:11 -06:00 committed by GitHub
commit 89700216c6
4 changed files with 150 additions and 111 deletions

View file

@ -2,15 +2,14 @@ package command
import (
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
"github.com/github/gh-cli/api"
"github.com/github/gh-cli/utils"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"golang.org/x/crypto/ssh/terminal"
)
func init() {
@ -29,7 +28,10 @@ func init() {
},
)
issueCmd.AddCommand(issueCreateCmd)
issueCreateCmd.Flags().StringArrayP("message", "m", nil, "set title and body")
issueCreateCmd.Flags().StringP("title", "t", "",
"Supply a title. Will prompt for one otherwise.")
issueCreateCmd.Flags().StringP("body", "b", "",
"Supply a body. Will prompt for one otherwise.")
issueCreateCmd.Flags().BoolP("web", "w", false, "open the web browser to create an issue")
issueListCmd := &cobra.Command{
@ -205,44 +207,39 @@ func issueCreate(cmd *cobra.Command, args []string) error {
return utils.OpenInBrowser(openURL)
}
var title string
var body string
message, err := cmd.Flags().GetStringArray("message")
if err != nil {
return err
}
apiClient, err := apiClientForContext(ctx)
if err != nil {
return err
}
if len(message) > 0 {
title = message[0]
body = strings.Join(message[1:], "\n\n")
} else {
// TODO: open the text editor for issue title & body
input := os.Stdin
if terminal.IsTerminal(int(input.Fd())) {
cmd.Println("Enter the issue title and body; press Enter + Ctrl-D when done:")
}
inputBytes, err := ioutil.ReadAll(input)
if err != nil {
return err
}
parts := strings.SplitN(string(inputBytes), "\n\n", 2)
if len(parts) > 0 {
title = parts[0]
}
if len(parts) > 1 {
body = parts[1]
}
title, err := cmd.Flags().GetString("title")
if err != nil {
return errors.Wrap(err, "could not parse title")
}
body, err := cmd.Flags().GetString("body")
if err != nil {
return errors.Wrap(err, "could not parse body")
}
if title == "" {
return fmt.Errorf("aborting due to empty title")
interactive := title == "" || body == ""
if interactive {
tb, err := titleBodySurvey(cmd, title, body)
if err != nil {
return errors.Wrap(err, "could not collect title and/or body")
}
if tb == nil {
// editing was canceled, we can just leave
return nil
}
if title == "" {
title = tb.Title
}
if body == "" {
body = tb.Body
}
}
params := map[string]interface{}{
"title": title,

View file

@ -144,7 +144,7 @@ func TestIssueCreate(t *testing.T) {
out := bytes.Buffer{}
issueCreateCmd.SetOut(&out)
RootCmd.SetArgs([]string{"issue", "create", "-m", "hello", "-m", "ab", "-m", "cd"})
RootCmd.SetArgs([]string{"issue", "create", "-t", "hello", "-b", "cash rules everything around me"})
_, err := RootCmd.ExecuteC()
if err != nil {
t.Errorf("error running command `issue create`: %v", err)
@ -164,7 +164,7 @@ func TestIssueCreate(t *testing.T) {
eq(t, reqBody.Variables.Input.RepositoryID, "REPOID")
eq(t, reqBody.Variables.Input.Title, "hello")
eq(t, reqBody.Variables.Input.Body, "ab\n\ncd")
eq(t, reqBody.Variables.Input.Body, "cash rules everything around me")
eq(t, out.String(), "https://github.com/OWNER/REPO/issues/12\n")
}

View file

@ -5,7 +5,6 @@ import (
"os"
"runtime"
"github.com/AlecAivazis/survey/v2"
"github.com/github/gh-cli/api"
"github.com/github/gh-cli/context"
"github.com/github/gh-cli/git"
@ -55,86 +54,25 @@ func prCreate(cmd *cobra.Command, _ []string) error {
interactive := title == "" || body == ""
inProgress := struct {
Body string
Title string
}{}
if interactive {
confirmed := false
editor := determineEditor()
tb, err := titleBodySurvey(cmd, title, body)
if err != nil {
return errors.Wrap(err, "could not collect title and/or body")
}
for !confirmed {
titleQuestion := &survey.Question{
Name: "title",
Prompt: &survey.Input{
Message: "Pull request title",
Default: inProgress.Title,
},
}
bodyQuestion := &survey.Question{
Name: "body",
Prompt: &survey.Editor{
Message: fmt.Sprintf("Pull request body (%s)", editor),
FileName: "*.md",
Default: inProgress.Body,
AppendDefault: true,
Editor: editor,
},
}
if tb == nil {
// editing was canceled, we can just leave
return nil
}
qs := []*survey.Question{}
if title == "" {
qs = append(qs, titleQuestion)
}
if body == "" {
qs = append(qs, bodyQuestion)
}
err := survey.Ask(qs, &inProgress)
if err != nil {
return errors.Wrap(err, "could not prompt")
}
confirmAnswers := struct {
Confirmation string
}{}
confirmQs := []*survey.Question{
{
Name: "confirmation",
Prompt: &survey.Select{
Message: "Submit?",
Options: []string{
"Yes",
"Edit",
"Cancel",
},
},
},
}
err = survey.Ask(confirmQs, &confirmAnswers)
if err != nil {
return errors.Wrap(err, "could not prompt")
}
switch confirmAnswers.Confirmation {
case "Yes":
confirmed = true
case "Edit":
continue
case "Cancel":
cmd.Println("Discarding pull request")
return nil
}
if title == "" {
title = tb.Title
}
if body == "" {
body = tb.Body
}
}
if title == "" {
title = inProgress.Title
}
if body == "" {
body = inProgress.Body
}
base, err := cmd.Flags().GetString("base")
if err != nil {
return errors.Wrap(err, "could not parse base")

View file

@ -0,0 +1,104 @@
package command
import (
"fmt"
"github.com/AlecAivazis/survey/v2"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
type titleBody struct {
Body string
Title string
}
const (
_confirmed = iota
_unconfirmed = iota
_cancel = iota
)
func confirm() (int, error) {
confirmAnswers := struct {
Confirmation int
}{}
confirmQs := []*survey.Question{
{
Name: "confirmation",
Prompt: &survey.Select{
Message: "Submit?",
Options: []string{
"Yes",
"Edit",
"Cancel",
},
},
},
}
err := survey.Ask(confirmQs, &confirmAnswers)
if err != nil {
return -1, errors.Wrap(err, "could not prompt")
}
return confirmAnswers.Confirmation, nil
}
func titleBodySurvey(cmd *cobra.Command, providedTitle string, providedBody string) (*titleBody, error) {
inProgress := titleBody{}
confirmed := false
editor := determineEditor()
for !confirmed {
titleQuestion := &survey.Question{
Name: "title",
Prompt: &survey.Input{
Message: "Title",
Default: inProgress.Title,
},
}
bodyQuestion := &survey.Question{
Name: "body",
Prompt: &survey.Editor{
Message: fmt.Sprintf("Body (%s)", editor),
FileName: "*.md",
Default: inProgress.Body,
AppendDefault: true,
Editor: editor,
},
}
qs := []*survey.Question{}
if providedTitle == "" {
qs = append(qs, titleQuestion)
}
if providedBody == "" {
qs = append(qs, bodyQuestion)
}
err := survey.Ask(qs, &inProgress)
if err != nil {
return nil, errors.Wrap(err, "could not prompt")
}
confirmA, err := confirm()
if err != nil {
return nil, errors.Wrap(err, "unable to confirm")
}
switch confirmA {
case _confirmed:
confirmed = true
case _unconfirmed:
continue
case _cancel:
cmd.Println("Discarding.")
return nil, nil
default:
panic("reached unreachable case")
}
}
return &inProgress, nil
}