Skip to content

Commit ea4a01a

Browse files
committed
"Generate a commit message using AI. By default, it launches an interactive flow. Use --yes or -y to skip the prompt and commit directly."
1 parent 69e8b63 commit ea4a01a

2 files changed

Lines changed: 113 additions & 36 deletions

File tree

cmd/generate.go

Lines changed: 113 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,130 @@
1+
// File: cmd/generate.go
12
package cmd
23

34
import (
45
"fmt"
6+
"os"
57
"os/exec"
68
"strings"
7-
8-
"github.com/spf13/cobra"
9+
"time"
910

1011
"smartcommit/config"
1112
"smartcommit/diff"
1213
"smartcommit/llm"
14+
15+
"github.com/manifoldco/promptui"
16+
"github.com/spf13/cobra"
1317
)
1418

19+
var yesFlag bool
20+
1521
var generateCmd = &cobra.Command{
16-
Use: "generate",
17-
Short: "Generate & commit a message from your diff",
18-
Run: func(cmd *cobra.Command, args []string) {
19-
cfg := config.LoadOrDefault()
20-
21-
d, err := diff.GetStagedDiff()
22-
if err != nil || d == "" {
23-
fmt.Println("❌ No staged changes.")
24-
return
25-
}
26-
27-
provider, err := llm.GetProvider(cfg)
28-
if err != nil {
29-
fmt.Println("❌", err)
30-
return
31-
}
32-
33-
prompt := cfg.SystemPrompt + "\n\nDiff:\n" + d
34-
msg, err := provider.Generate(prompt)
35-
if err != nil {
36-
fmt.Println("❌ Generation failed:", err)
37-
return
38-
}
39-
msg = strings.TrimSpace(msg)
40-
41-
fmt.Println("\n💡 Commit message:\n\n", msg, "\n")
42-
git := exec.Command("git", "commit", "-m", msg)
43-
git.Stdout = cmd.OutOrStdout()
44-
git.Stderr = cmd.OutOrStderr()
45-
if err := git.Run(); err != nil {
46-
fmt.Println("❌ Git commit failed:", err)
47-
}
48-
},
22+
Use: "generate",
23+
Short: "Generate a commit message using AI",
24+
Long: `Generate a commit message from staged Git changes using a local or remote LLM.
25+
26+
By default, it launches an interactive flow.
27+
Use --yes or -y to skip the prompt and commit directly.`,
28+
Run: func(cmd *cobra.Command, args []string) {
29+
cfg := config.LoadOrDefault()
30+
31+
d, err := diff.GetStagedDiff()
32+
if err != nil || strings.TrimSpace(d) == "" {
33+
fmt.Println("❌ No staged changes found.")
34+
return
35+
}
36+
37+
prompt := cfg.SystemPrompt + "\n\nDiff:\n" + d
38+
39+
provider, err := llm.GetProvider(cfg)
40+
if err != nil {
41+
fmt.Println("❌", err)
42+
return
43+
}
44+
45+
message, err := provider.Generate(prompt)
46+
if err != nil {
47+
fmt.Println("❌ Generation failed:", err)
48+
return
49+
}
50+
message = strings.TrimSpace(message)
51+
52+
if yesFlag {
53+
fmt.Println("💡 Generated Commit Message:")
54+
fmt.Println("----------------------------------")
55+
fmt.Println(message)
56+
fmt.Println("----------------------------------")
57+
commit(message)
58+
return
59+
}
60+
61+
// Interactive loop
62+
for {
63+
fmt.Println("\n💡 Generated Commit Message:")
64+
fmt.Println("----------------------------------")
65+
fmt.Println(message)
66+
fmt.Println("----------------------------------")
67+
fmt.Print("Choose [c]ommit, [e]dit, [r]egenerate, [q]uit: ")
68+
69+
var choice string
70+
fmt.Scanln(&choice)
71+
72+
switch choice {
73+
case "c":
74+
commit(message)
75+
return
76+
case "e":
77+
message = edit(message)
78+
case "r":
79+
fmt.Print("\n🔄 Regenerating")
80+
for i := 0; i < 3; i++ {
81+
fmt.Print(".")
82+
time.Sleep(200 * time.Millisecond)
83+
}
84+
msg, err := provider.Generate(prompt)
85+
if err != nil {
86+
fmt.Println("\n❌ Regeneration failed:", err)
87+
} else {
88+
message = strings.TrimSpace(msg)
89+
}
90+
case "q":
91+
fmt.Println("👋 Aborted.")
92+
return
93+
default:
94+
fmt.Println("❓ Invalid choice.")
95+
}
96+
}
97+
},
4998
}
5099

51100
func init() {
52-
rootCmd.AddCommand(generateCmd)
101+
generateCmd.Flags().BoolVarP(&yesFlag, "yes", "y", false, "Autogenerate and commit without prompting")
102+
rootCmd.AddCommand(generateCmd)
103+
}
104+
105+
func commit(msg string) {
106+
fmt.Println("✅ Committing with:")
107+
fmt.Println(msg)
108+
cmd := exec.Command("git", "commit", "-m", msg)
109+
cmd.Stdin = os.Stdin
110+
cmd.Stdout = os.Stdout
111+
cmd.Stderr = os.Stderr
112+
err := cmd.Run()
113+
if err != nil {
114+
fmt.Println("❌ Git commit failed:", err)
115+
}
116+
}
117+
118+
func edit(current string) string {
119+
prompt := promptui.Prompt{
120+
Label: "Edit Commit Message",
121+
Default: current,
122+
AllowEdit: true,
123+
}
124+
result, err := prompt.Run()
125+
if err != nil {
126+
fmt.Println("⚠️ Edit cancelled.")
127+
return current
128+
}
129+
return result
53130
}

smartcommit

5.5 KB
Binary file not shown.

0 commit comments

Comments
 (0)