aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--commands/comment_add.go2
-rw-r--r--input/input.go7
-rw-r--r--termui/show_bug.go39
-rw-r--r--termui/termui.go38
4 files changed, 78 insertions, 8 deletions
diff --git a/commands/comment_add.go b/commands/comment_add.go
index 0a83eb65..8736f9c2 100644
--- a/commands/comment_add.go
+++ b/commands/comment_add.go
@@ -29,7 +29,7 @@ func runCommentAdd(cmd *cobra.Command, args []string) error {
}
if commentAddMessage == "" {
- commentAddMessage, err = input.BugCommentEditorInput(backend)
+ commentAddMessage, err = input.BugCommentEditorInput(backend, "")
if err == input.ErrEmptyMessage {
fmt.Println("Empty message, aborting.")
return nil
diff --git a/input/input.go b/input/input.go
index 6a7c8c7c..07148acc 100644
--- a/input/input.go
+++ b/input/input.go
@@ -78,7 +78,7 @@ func BugCreateEditorInput(repo repository.RepoCommon, preTitle string, preMessag
return title, message, nil
}
-const bugCommentTemplate = `
+const bugCommentTemplate = `%s
# Please enter the comment message. Lines starting with '#' will be ignored,
# and an empty message aborts the operation.
@@ -86,8 +86,9 @@ const bugCommentTemplate = `
// BugCommentEditorInput will open the default editor in the terminal with a
// template for the user to fill. The file is then processed to extract a comment.
-func BugCommentEditorInput(repo repository.RepoCommon) (string, error) {
- raw, err := launchEditorWithTemplate(repo, messageFilename, bugCommentTemplate)
+func BugCommentEditorInput(repo repository.RepoCommon, preMessage string) (string, error) {
+ template := fmt.Sprintf(bugCommentTemplate, preMessage)
+ raw, err := launchEditorWithTemplate(repo, messageFilename, template)
if err != nil {
return "", err
diff --git a/termui/show_bug.go b/termui/show_bug.go
index 4ca987bd..72bcfe2f 100644
--- a/termui/show_bug.go
+++ b/termui/show_bug.go
@@ -9,6 +9,7 @@ import (
"github.com/MichaelMure/git-bug/cache"
"github.com/MichaelMure/git-bug/util/colors"
"github.com/MichaelMure/git-bug/util/text"
+ "github.com/MichaelMure/git-bug/util/git"
"github.com/jroimartin/gocui"
)
@@ -99,7 +100,7 @@ func (sb *showBug) layout(g *gocui.Gui) error {
if sb.isOnSide {
fmt.Fprint(v, "[a] Add label [r] Remove label")
} else {
- fmt.Fprint(v, "[o] Toggle open/close [c] Comment [t] Change title")
+ fmt.Fprint(v, "[o] Toggle open/close [e] Edit [c] Comment [t] Change title")
}
_, err = g.SetViewOnTop(showBugInstructionView)
@@ -183,6 +184,12 @@ func (sb *showBug) keybindings(g *gocui.Gui) error {
return err
}
+ // Edit
+ if err := g.SetKeybinding(showBugView, 'e', gocui.ModNone,
+ sb.edit); err != nil {
+ return err
+ }
+
// Labels
if err := g.SetKeybinding(showBugView, 'a', gocui.ModNone,
sb.addLabel); err != nil {
@@ -240,8 +247,8 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error {
fmt.Fprint(v, bugHeader)
y0 += lines + 1
- for i, op := range snap.Timeline {
- viewName := fmt.Sprintf("op%d", i)
+ for _, op := range snap.Timeline {
+ viewName := op.Hash().String()
// TODO: me might skip the rendering of blocks that are outside of the view
// but to do that we need to rework how sb.mainSelectableView is maintained
@@ -620,6 +627,32 @@ func (sb *showBug) toggleOpenClose(g *gocui.Gui, v *gocui.View) error {
}
}
+func (sb *showBug) edit(g *gocui.Gui, v *gocui.View) error {
+ if sb.isOnSide {
+ ui.msgPopup.Activate(msgPopupErrorTitle, "Selected field is not editable.")
+ return nil
+ }
+
+ snap := sb.bug.Snapshot()
+
+ op, err := snap.SearchTimelineItem(git.Hash(sb.selected))
+ if err != nil {
+ return err
+ }
+
+ switch op.(type) {
+ case *bug.AddCommentTimelineItem:
+ message := op.(*bug.AddCommentTimelineItem).Message
+ return editCommentWithEditor(sb.bug, op.Hash(), message)
+ case *bug.CreateTimelineItem:
+ preMessage := op.(*bug.CreateTimelineItem).Message
+ return editCommentWithEditor(sb.bug, op.Hash(), preMessage)
+ }
+
+ ui.msgPopup.Activate(msgPopupErrorTitle, "Selected field is not editable.")
+ return nil
+}
+
func (sb *showBug) addLabel(g *gocui.Gui, v *gocui.View) error {
c := ui.inputPopup.Activate("Add labels")
diff --git a/termui/termui.go b/termui/termui.go
index f2163d96..5c39869b 100644
--- a/termui/termui.go
+++ b/termui/termui.go
@@ -4,6 +4,7 @@ package termui
import (
"github.com/MichaelMure/git-bug/cache"
"github.com/MichaelMure/git-bug/input"
+ "github.com/MichaelMure/git-bug/util/git"
"github.com/jroimartin/gocui"
"github.com/pkg/errors"
)
@@ -210,7 +211,7 @@ func addCommentWithEditor(bug *cache.BugCache) error {
ui.g.Close()
ui.g = nil
- message, err := input.BugCommentEditorInput(ui.cache)
+ message, err := input.BugCommentEditorInput(ui.cache, "")
if err != nil && err != input.ErrEmptyMessage {
return err
@@ -230,6 +231,41 @@ func addCommentWithEditor(bug *cache.BugCache) error {
return errTerminateMainloop
}
+func editCommentWithEditor(bug *cache.BugCache, target git.Hash, preMessage string) error {
+ // This is somewhat hacky.
+ // As there is no way to pause gocui, run the editor and restart gocui,
+ // we have to stop it entirely and start a new one later.
+ //
+ // - an error channel is used to route the returned error of this new
+ // instance into the original launch function
+ // - a custom error (errTerminateMainloop) is used to terminate the original
+ // instance's mainLoop. This error is then filtered.
+
+ ui.g.Close()
+ ui.g = nil
+
+ message, err := input.BugCommentEditorInput(ui.cache, preMessage)
+ if err != nil && err != input.ErrEmptyMessage {
+ return err
+ }
+
+ if err == input.ErrEmptyMessage {
+ // TODO: Allow comments to be deleted?
+ ui.msgPopup.Activate(msgPopupErrorTitle, "Empty message, aborting.")
+ } else if message == preMessage {
+ ui.msgPopup.Activate(msgPopupErrorTitle, "No changes found, aborting.")
+ } else {
+ err := bug.EditComment(target, message)
+ if err != nil {
+ return err
+ }
+ }
+
+ initGui(nil)
+
+ return errTerminateMainloop
+}
+
func setTitleWithEditor(bug *cache.BugCache) error {
// This is somewhat hacky.
// As there is no way to pause gocui, run the editor and restart gocui,