diff options
-rw-r--r-- | commands/comment_add.go | 2 | ||||
-rw-r--r-- | input/input.go | 7 | ||||
-rw-r--r-- | termui/show_bug.go | 39 | ||||
-rw-r--r-- | termui/termui.go | 38 |
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, |