Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 203 additions & 0 deletions cmd/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
package cmd

import (
"fmt"
"strings"

"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/cocoide/commitify/util"
"github.com/fatih/color"
"github.com/spf13/cobra"
)

var (
configKey = [...]string{"api-key", "language", "format"}
configOption = [][]string{
{},
{"Japanese", "English"},
{"Format 1", "Format 2"},
}
)
Comment on lines +14 to +21
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

他のpackageでも参照する予定だから、enumパッケージ等作成して(objectでもいいかな)欲しいかも!

type Format int
const(
PrefixFormat Format = itoa
EmojiFormat
)


これを
enum.PrefixFormatみたいに使う感じ
あとentityにも結びつけられたらいいかな


type configModel struct {
configKeyIndex int
configOptionIndex int
configKeySelected bool
err error
textInput textinput.Model
}

func initConfigModel() configModel {
ti := textinput.New()
ti.Focus()

return configModel{
textInput: ti,
err: nil,
}
}

func (cm configModel) Init() tea.Cmd {
return textinput.Blink
}

func (cm configModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch cm.configKeySelected {
// 設定項目を選択する
case false:
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.Type {
case tea.KeyUp:
if cm.configKeyIndex > 0 {
cm.configKeyIndex--
}
case tea.KeyDown:
if cm.configKeyIndex < len(configKey)-1 {
cm.configKeyIndex++
}
case tea.KeyEnter:
cm.configKeySelected = true
return cm, nil
case tea.KeyCtrlC, tea.KeyEsc:
return cm, tea.Quit
}
}

// 設定項目に値をセットする
case true:
switch len(configOption[cm.configKeyIndex]) {
// 選択肢のない項目は入力を受け付ける
case 0:
var cmd tea.Cmd
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.Type {
case tea.KeyEnter:
saveConfig(cm)
return cm, tea.Quit
case tea.KeyCtrlC, tea.KeyEsc:
return cm, tea.Quit
}
case error:
cm.err = msg
return cm, nil
}

cm.textInput, cmd = cm.textInput.Update(msg)
return cm, cmd

// 選択肢がある場合はセレクターで表示する
default:
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.Type {
case tea.KeyUp:
if cm.configOptionIndex > 0 {
cm.configOptionIndex--
}
case tea.KeyDown:
if cm.configOptionIndex < len(configOption[cm.configKeyIndex])-1 {
cm.configOptionIndex++
}
case tea.KeyEnter:
saveConfig(cm)
return cm, tea.Quit
case tea.KeyCtrlC, tea.KeyEsc:
return cm, tea.Quit
}
}
}
}

return cm, nil
}

func (cm configModel) View() string {
var b strings.Builder

switch cm.configKeySelected {
// 設定項目を選んでいない時
case false:
white := color.New(color.FgWhite).SprintFunc()
b.WriteString(white("設定項目を選んでください:\n"))
b.WriteString(white(" ↑↓の矢印キーで項目を移動、Enterで選択\n"))

for i, choice := range configKey {
cyan := color.New(color.FgCyan).SprintFunc()
hiCyan := color.New(color.FgHiCyan).SprintFunc()
if i == cm.configKeyIndex {
b.WriteString(fmt.Sprintf(hiCyan("➡️ %s\n"), choice))
} else {
b.WriteString(fmt.Sprintf(cyan(" %s\n"), choice))
}
}

// 設定項目に値をセットする
case true:
// 選択肢のない項目はテキストエリアを表示
switch len(configOption[cm.configKeyIndex]) {
case 0:
white := color.New(color.FgWhite).SprintFunc()
b.WriteString(white(fmt.Sprintf(
"ここに%sを入力: %s\n",
configKey[cm.configKeyIndex],
cm.textInput.View(),
)))
b.WriteString(white(" Enterキーで確定"))

default:
white := color.New(color.FgWhite).SprintFunc()
b.WriteString(white("設定内容を選んでください:\n"))
b.WriteString(white(" ↑↓の矢印キーで項目を移動、Enterで選択\n"))

for i, option := range configOption[cm.configKeyIndex] {
cyan := color.New(color.FgCyan).SprintFunc()
hiCyan := color.New(color.FgHiCyan).SprintFunc()
if i == cm.configOptionIndex {
b.WriteString(fmt.Sprintf(hiCyan("➡️ %s\n"), option))
} else {
b.WriteString(fmt.Sprintf(cyan(" %s\n"), option))
}
}
}
}

return b.String()
}

var configCmd = &cobra.Command{
Use: "config",
Short: "設定を変更します",
Long: `設定を変更します。設定項目はコマンドを実行すると表示されます。`,
Run: func(cmd *cobra.Command, args []string) {
p := tea.NewProgram(initConfigModel())
p.Run()
},
}

func init() {
rootCmd.AddCommand(configCmd)
}

func saveConfig(cm configModel) {
currentConfig, err := util.ReadConfig()
if err != nil {
fmt.Println(err)
}

switch cm.configKeyIndex {
case 0:
currentConfig.ChatGptApiKey = cm.textInput.Value()
case 1:
currentConfig.UseLanguage = configOption[cm.configKeyIndex][cm.configOptionIndex]
case 2:
currentConfig.CommitFormat = configOption[cm.configKeyIndex][cm.configOptionIndex]
}

err = util.WriteConfig(currentConfig)
if err != nil {
fmt.Println(err)
}
}
44 changes: 0 additions & 44 deletions cmd/settings.go

This file was deleted.

1 change: 0 additions & 1 deletion cmd/suggest.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ type generateMessages struct {

func (m model) Init() tea.Cmd {
return func() tea.Msg {
util.LoadEnv()
ctx := context.Background()
og := gateway.NewOpenAIGateway(ctx)
ms := service.NewMessageService(og)
Expand Down
12 changes: 12 additions & 0 deletions doc/command_list.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## コマンドリスト

### コマンド
- `suggest`:コミットメッセージの生成
- `config`:各種の設定
- 選択肢を出して設定項目を選んでもらう
- 設定項目はAPIキー、日本語/英語、など

### フラッグ
- `--help` `-h`:CLIのコマンドとオプション一覧を表示
- `--docs` `-d`:コミットメッセージに関するドキュメント
- `--version` `-v`:アプリのバージョン表示
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ require (
)

require (
github.com/atotto/clipboard v0.1.4 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/bubbles v0.16.1 // indirect
github.com/charmbracelet/lipgloss v0.7.1 // indirect
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
github.com/mattn/go-localereader v0.0.1 // indirect
Expand All @@ -41,7 +43,6 @@ require (
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.15.1 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/term v0.6.0 // indirect
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,17 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/charmbracelet/bubbles v0.16.1 h1:6uzpAAaT9ZqKssntbvZMlksWHruQLNxg49H5WdeuYSY=
github.com/charmbracelet/bubbles v0.16.1/go.mod h1:2QCp9LFlEsBQMvIYERr7Ww2H2bA7xen1idUDIzm/+Xc=
github.com/charmbracelet/bubbletea v0.24.2 h1:uaQIKx9Ai6Gdh5zpTbGiWpytMU+CfsPp06RaW2cx/SY=
github.com/charmbracelet/bubbletea v0.24.2/go.mod h1:XdrNrV4J8GiyshTtx3DNuYkR1FDaJmO3l2nejekbsgg=
github.com/charmbracelet/lipgloss v0.7.1 h1:17WMwi7N1b1rVWOjMT+rCh7sQkvDU75B2hbZpc5Kc1E=
github.com/charmbracelet/lipgloss v0.7.1/go.mod h1:yG0k3giv8Qj8edTCbbg6AlQ5e8KNWpFujkNawKNhE2c=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
Expand Down
4 changes: 3 additions & 1 deletion internal/entity/config.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package entity

type Config struct {
ChatGptToken string `json:"chatGptToken"`
ChatGptApiKey string `json:"chatGptApiKey"`
UseLanguage string `json:"UseLanguage"`
CommitFormat string `json:"CommitFormat"`
}
2 changes: 1 addition & 1 deletion internal/gateway/openai.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func NewOpenAIGateway(ctx context.Context) OpenAIGateway {
if err != nil {
log.Fatalf("Failed to read config: %v", err)
}
client := openai.NewClient(config.ChatGptToken)
client := openai.NewClient(config.ChatGptApiKey)
return &openAIGateway{client: client, ctx: ctx}
}

Expand Down
17 changes: 8 additions & 9 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
package main

import (
"log"
"fmt"
"os"

"github.com/cocoide/commitify/cmd"
"github.com/spf13/viper"
)

func main() {
viper.SetConfigName("config")
viper.AddConfigPath(".")
viper.SetConfigType("yaml")
viper.AutomaticEnv()

if err := viper.ReadInConfig(); err != nil {
log.Println("An error occurred while reading the configuration file:", err)
// configファイルがあるかどうかを確認
_, err := os.Stat("config.yaml")
if os.IsNotExist(err) {
if _, err := os.Create("config.yaml"); err != nil {
fmt.Printf("error creating config file, %s", err.Error())
}
}

cmd.Execute()
Expand Down
11 changes: 6 additions & 5 deletions util/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ import (

func ReadConfig() (*entity.Config, error) {
var result entity.Config

viper.AddConfigPath(".")
viper.SetConfigName("config")
viper.SetConfigType("yaml")
if err := viper.ReadInConfig(); err != nil {
return &result, fmt.Errorf("Error reading config file, %s", err.Error())
return &result, fmt.Errorf("error reading config file, %s", err.Error())
}
if err := viper.Unmarshal(&result); err != nil {
return &result, fmt.Errorf("Unable to decode into struct, %v", err.Error())
return &result, fmt.Errorf("unable to decode into struct, %v", err.Error())
}
return &result, nil
}
Expand All @@ -29,17 +30,17 @@ func WriteConfig(config *entity.Config) error {
configMap := make(map[string]interface{})
configBytes, err := json.Marshal(config)
if err != nil {
return fmt.Errorf("Error marshalling config: %s", err.Error())
return fmt.Errorf("error marshalling config: %s", err.Error())
}
err = json.Unmarshal(configBytes, &configMap)
if err != nil {
return fmt.Errorf("Error unmarshalling config: %s", err.Error())
return fmt.Errorf("error unmarshalling config: %s", err.Error())
}
if err := viper.MergeConfigMap(configMap); err != nil {
return err
}
if err := viper.WriteConfig(); err != nil {
return fmt.Errorf("Error saving config file, %s", err.Error())
return fmt.Errorf("error saving config file, %s", err.Error())
}
return nil
}
Loading