Skip to content

Commit afb3c6e

Browse files
author
{cocoide}
committed
feat: add interactive UI for commit message suggestion
1 parent 2b78b19 commit afb3c6e

File tree

1 file changed

+71
-16
lines changed

1 file changed

+71
-16
lines changed

cmd/suggest.go

+71-16
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,92 @@ import (
44
"context"
55
"fmt"
66
"log"
7-
"os/exec"
7+
"strings"
88

9+
tea "github.com/charmbracelet/bubbletea"
910
"github.com/cocoide/commitify/internal/gateway"
11+
"github.com/cocoide/commitify/internal/service"
1012
"github.com/cocoide/commitify/util"
13+
"github.com/fatih/color"
1114
"github.com/spf13/cobra"
1215
)
1316

14-
const (
15-
CommitMessagePrompt = "Generate commit message for [%s]"
16-
FormatNotice = ", format your commit as:\n- feat: [feature description]\n- bugfix: [bugfix description]"
17-
)
17+
type model struct {
18+
choices []string
19+
currentIdx int
20+
errorMsg string
21+
}
22+
23+
func (m model) Init() tea.Cmd {
24+
return nil
25+
}
26+
27+
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
28+
switch msg := msg.(type) {
29+
case tea.KeyMsg:
30+
switch msg.Type {
31+
case tea.KeyUp:
32+
if m.currentIdx > 0 {
33+
m.currentIdx--
34+
}
35+
case tea.KeyDown:
36+
if m.currentIdx < len(m.choices)-1 {
37+
m.currentIdx++
38+
}
39+
case tea.KeyEnter:
40+
if err := util.ExecCommitMessage(m.choices[m.currentIdx]); err != nil {
41+
m.errorMsg = err.Error()
42+
return m, nil
43+
}
44+
return m, tea.Quit
45+
case tea.KeyCtrlC, tea.KeyEsc:
46+
return m, tea.Quit
47+
}
48+
}
49+
return m, nil
50+
}
51+
52+
func (m model) View() string {
53+
var b strings.Builder
54+
if m.errorMsg != "" {
55+
// エラーメッセージを赤色で表示
56+
red := color.New(color.FgRed).SprintFunc()
57+
b.WriteString(red(m.errorMsg) + "\n\n")
58+
}
59+
b.WriteString("Please select an option:\n\n")
60+
61+
for i, choice := range m.choices {
62+
blue := color.New(color.FgCyan).SprintFunc()
63+
if i == m.currentIdx {
64+
b.WriteString(fmt.Sprintf(blue("-> %s\n"), choice))
65+
} else {
66+
b.WriteString(fmt.Sprintf(" %s\n", choice))
67+
}
68+
}
69+
70+
b.WriteString("\nUse the arrow keys to navigate and press Enter to select.")
71+
return b.String()
72+
}
1873

1974
var suggestCmd = &cobra.Command{
20-
Use: "suggest",
21-
Short: "Suggestion of commit message for staging repository",
75+
Use: "suggest",
76+
Short: "Suggestion of commit message for staging repository",
77+
Aliases: []string{"s", "suggest"},
2278
Run: func(cmd *cobra.Command, args []string) {
2379
util.LoadEnv()
2480
ctx := context.Background()
2581
og := gateway.NewOpenAIGateway(ctx)
26-
result, err := exec.Command("git", "diff", "--staged").Output()
27-
if err != nil {
28-
log.Fatal(err.Error())
29-
}
30-
// 設定に応じてPromptは動的に変化させる
31-
prompt := fmt.Sprintf(CommitMessagePrompt, string(result))
32-
answer, err := og.GetAnswerFromPrompt(prompt, 0.01)
33-
// 生成中のUIを非同期で表示
82+
ms := service.NewMessageService(og)
83+
msgCh, err := ms.AsyncGenerateCommitMessage()
3484
if err != nil {
3585
log.Fatal(err.Error())
3686
}
37-
fmt.Println(answer)
87+
suggestMsg := <-msgCh
88+
fmt.Println(suggestMsg)
89+
choices := []string{"32", "!", "!#!"}
90+
m := model{choices: choices}
91+
p := tea.NewProgram(m)
92+
p.Run()
3893
},
3994
}
4095

0 commit comments

Comments
 (0)