aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2018-07-31 15:18:09 +0200
committerMichael Muré <batolettre@gmail.com>2018-07-31 16:44:23 +0200
commiteb39c5c29bc0e9b5e15a940a1b71bdac688b6535 (patch)
tree5ef9b827f4a3097e4eb1367097d0059f895befbe
parent8a4e373e7b1c093abeb967d9a6a43c5ed533edb8 (diff)
downloadgit-bug-eb39c5c29bc0e9b5e15a940a1b71bdac688b6535.tar.gz
cli: rework new and comment command to better use the editor
a nice templace is now provided with explanations new: title and message can now be provided from the editor. Title will be the first non-empty line
-rw-r--r--bug/operation.go3
-rw-r--r--commands/comment.go12
-rw-r--r--commands/new.go36
-rw-r--r--doc/bash_completion/git-bug3
-rw-r--r--doc/man/git-bug-new.36
-rw-r--r--doc/md/git-bug_new.md3
-rw-r--r--input/input.go (renamed from commands/input/input.go)111
7 files changed, 146 insertions, 28 deletions
diff --git a/bug/operation.go b/bug/operation.go
index 9e31637a..74be2fac 100644
--- a/bug/operation.go
+++ b/bug/operation.go
@@ -17,6 +17,9 @@ type Operation interface {
OpType() OperationType
Time() time.Time
Apply(snapshot Snapshot) Snapshot
+
+ // TODO: data validation (ex: a title is a single line)
+ // Validate() bool
}
type OpBase struct {
diff --git a/commands/comment.go b/commands/comment.go
index ebbeaa77..cebf729c 100644
--- a/commands/comment.go
+++ b/commands/comment.go
@@ -2,9 +2,10 @@ package commands
import (
"errors"
+ "fmt"
"github.com/MichaelMure/git-bug/bug"
"github.com/MichaelMure/git-bug/bug/operations"
- "github.com/MichaelMure/git-bug/commands/input"
+ "github.com/MichaelMure/git-bug/input"
"github.com/spf13/cobra"
)
@@ -32,8 +33,13 @@ func runComment(cmd *cobra.Command, args []string) error {
return err
}
}
- if commentMessageFile == "" && commentMessage == "" {
- commentMessage, err = input.LaunchEditor(repo, messageFilename)
+
+ if commentMessage == "" {
+ commentMessage, err = input.BugCommentEditorInput(repo, messageFilename)
+ if err == input.ErrEmptyMessage {
+ fmt.Println("Empty message, aborting.")
+ return nil
+ }
if err != nil {
return err
}
diff --git a/commands/new.go b/commands/new.go
index 4168453e..88e7cd81 100644
--- a/commands/new.go
+++ b/commands/new.go
@@ -1,39 +1,36 @@
package commands
import (
- "errors"
"fmt"
"github.com/MichaelMure/git-bug/bug"
"github.com/MichaelMure/git-bug/bug/operations"
- "github.com/MichaelMure/git-bug/commands/input"
+ "github.com/MichaelMure/git-bug/input"
"github.com/spf13/cobra"
)
var (
- newMessageFile string
+ newTitle string
newMessage string
+ newMessageFile string
)
func runNewBug(cmd *cobra.Command, args []string) error {
var err error
- if len(args) == 0 {
- return errors.New("No title provided")
- }
- if len(args) > 1 {
- return errors.New("Only accepting one title is supported")
- }
-
- title := args[0]
-
if newMessageFile != "" && newMessage == "" {
newMessage, err = input.FromFile(newMessageFile)
if err != nil {
return err
}
}
- if newMessageFile == "" && newMessage == "" {
- newMessage, err = input.LaunchEditor(repo, messageFilename)
+
+ if newMessage == "" || newTitle == "" {
+ newTitle, newMessage, err = input.BugCreateEditorInput(repo, messageFilename, newTitle, newMessage)
+
+ if err == input.ErrEmptyTitle {
+ fmt.Println("Empty title, aborting.")
+ return nil
+ }
if err != nil {
return err
}
@@ -44,7 +41,7 @@ func runNewBug(cmd *cobra.Command, args []string) error {
return err
}
- newBug, err := operations.Create(author, title, newMessage)
+ newBug, err := operations.Create(author, newTitle, newMessage)
if err != nil {
return err
}
@@ -61,7 +58,7 @@ func runNewBug(cmd *cobra.Command, args []string) error {
}
var newCmd = &cobra.Command{
- Use: "new <title> [<option>...]",
+ Use: "new [<option>...]",
Short: "Create a new bug",
RunE: runNewBug,
}
@@ -69,10 +66,13 @@ var newCmd = &cobra.Command{
func init() {
RootCmd.AddCommand(newCmd)
- newCmd.Flags().StringVarP(&newMessageFile, "file", "F", "",
- "Take the message from the given file. Use - to read the message from the standard input",
+ newCmd.Flags().StringVarP(&newTitle, "title", "t", "",
+ "Provide a title to describe the issue",
)
newCmd.Flags().StringVarP(&newMessage, "message", "m", "",
"Provide a message to describe the issue",
)
+ newCmd.Flags().StringVarP(&newMessageFile, "file", "F", "",
+ "Take the message from the given file. Use - to read the message from the standard input",
+ )
}
diff --git a/doc/bash_completion/git-bug b/doc/bash_completion/git-bug
index 0be168de..d8505868 100644
--- a/doc/bash_completion/git-bug
+++ b/doc/bash_completion/git-bug
@@ -375,6 +375,9 @@ _git-bug_new()
flags+=("--message=")
two_word_flags+=("-m")
local_nonpersistent_flags+=("--message=")
+ flags+=("--title=")
+ two_word_flags+=("-t")
+ local_nonpersistent_flags+=("--title=")
must_have_one_flag=()
must_have_one_noun=()
diff --git a/doc/man/git-bug-new.3 b/doc/man/git-bug-new.3
index ea64be68..e184c34a 100644
--- a/doc/man/git-bug-new.3
+++ b/doc/man/git-bug-new.3
@@ -10,7 +10,7 @@ git\-bug\-new \- Create a new bug
.SH SYNOPSIS
.PP
-\fBgit\-bug new <title> [<option>\&...] [flags]\fP
+\fBgit\-bug new [<option>\&...] [flags]\fP
.SH DESCRIPTION
@@ -31,6 +31,10 @@ Create a new bug
\fB\-m\fP, \fB\-\-message\fP=""
Provide a message to describe the issue
+.PP
+\fB\-t\fP, \fB\-\-title\fP=""
+ Provide a title to describe the issue
+
.SH SEE ALSO
.PP
diff --git a/doc/md/git-bug_new.md b/doc/md/git-bug_new.md
index 1a17fcc9..92edeb12 100644
--- a/doc/md/git-bug_new.md
+++ b/doc/md/git-bug_new.md
@@ -7,7 +7,7 @@ Create a new bug
Create a new bug
```
-git-bug new <title> [<option>...] [flags]
+git-bug new [<option>...] [flags]
```
### Options
@@ -16,6 +16,7 @@ git-bug new <title> [<option>...] [flags]
-F, --file string Take the message from the given file. Use - to read the message from the standard input
-h, --help help for new
-m, --message string Provide a message to describe the issue
+ -t, --title string Provide a title to describe the issue
```
### SEE ALSO
diff --git a/commands/input/input.go b/input/input.go
index 531a4386..49d3501d 100644
--- a/commands/input/input.go
+++ b/input/input.go
@@ -1,4 +1,4 @@
-// Taken from the git-appraise project
+// Originally taken from the git-appraise project
package input
@@ -7,11 +7,111 @@ import (
"bytes"
"fmt"
"github.com/MichaelMure/git-bug/repository"
+ "github.com/pkg/errors"
"io/ioutil"
"os"
"os/exec"
+ "strings"
)
+var ErrEmptyMessage = errors.New("empty message")
+var ErrEmptyTitle = errors.New("empty title")
+
+const bugTitleCommentTemplate = `%s%s
+
+# Please enter the title and comment message. The first non-empty line will be
+# used as the title. Lines starting with '#' will be ignored.
+# An empty title aborts the operation.
+`
+
+func BugCreateEditorInput(repo repository.Repo, fileName string, preTitle string, preMessage string) (string, string, error) {
+ if preMessage != "" {
+ preMessage = "\n\n" + preMessage
+ }
+
+ template := fmt.Sprintf(bugTitleCommentTemplate, preTitle, preMessage)
+
+ raw, err := LaunchEditorWithTemplate(repo, fileName, template)
+
+ if err != nil {
+ return "", "", err
+ }
+
+ lines := strings.Split(raw, "\n")
+
+ var title string
+ var b strings.Builder
+ for _, line := range lines {
+ if strings.HasPrefix(line, "#") {
+ continue
+ }
+
+ if title == "" {
+ trimmed := strings.TrimSpace(line)
+ if trimmed != "" {
+ title = trimmed
+ }
+ continue
+ }
+
+ b.WriteString(line)
+ b.WriteString("\n")
+ }
+
+ if title == "" {
+ return "", "", ErrEmptyTitle
+ }
+
+ message := strings.TrimSpace(b.String())
+
+ return title, message, nil
+}
+
+const bugCommentTemplate = `
+
+# Please enter the comment message. Lines starting with '#' will be ignored,
+# and an empty message aborts the operation.
+`
+
+func BugCommentEditorInput(repo repository.Repo, fileName string) (string, error) {
+ raw, err := LaunchEditorWithTemplate(repo, fileName, bugCommentTemplate)
+
+ if err != nil {
+ return "", err
+ }
+
+ lines := strings.Split(raw, "\n")
+
+ var b strings.Builder
+ for _, line := range lines {
+ if strings.HasPrefix(line, "#") {
+ continue
+ }
+ b.WriteString(line)
+ b.WriteString("\n")
+ }
+
+ message := strings.TrimSpace(b.String())
+
+ if message == "" {
+ return "", ErrEmptyMessage
+ }
+
+ return message, nil
+}
+
+func LaunchEditorWithTemplate(repo repository.Repo, fileName string, template string) (string, error) {
+ path := fmt.Sprintf("%s/.git/%s", repo.GetPath(), fileName)
+
+ err := ioutil.WriteFile(path, []byte(template), 0644)
+
+ if err != nil {
+ return "", err
+ }
+
+ return LaunchEditor(repo, fileName)
+}
+
// LaunchEditor launches the default editor configured for the given repo. This
// method blocks until the editor command has returned.
//
@@ -22,13 +122,14 @@ import (
// This method returns the text that was read from the temporary file, or
// an error if any step in the process failed.
func LaunchEditor(repo repository.Repo, fileName string) (string, error) {
+ path := fmt.Sprintf("%s/.git/%s", repo.GetPath(), fileName)
+ defer os.Remove(path)
+
editor, err := repo.GetCoreEditor()
if err != nil {
return "", fmt.Errorf("Unable to detect default git editor: %v\n", err)
}
- path := fmt.Sprintf("%s/.git/%s", repo.GetPath(), fileName)
-
cmd, err := startInlineCommand(editor, path)
if err != nil {
// Running the editor directly did not work. This might mean that
@@ -50,11 +151,11 @@ func LaunchEditor(repo repository.Repo, fileName string) (string, error) {
}
output, err := ioutil.ReadFile(path)
+
if err != nil {
- os.Remove(path)
return "", fmt.Errorf("Error reading edited file: %v\n", err)
}
- os.Remove(path)
+
return string(output), err
}