Merge pull request #81 from Slug-Boi/feat_config

This commit is contained in:
Theis
2025-06-03 20:17:02 +02:00
committed by GitHub
9 changed files with 342 additions and 31 deletions
+13 -1
View File
@@ -23,6 +23,8 @@ require (
github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b // indirect github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b // indirect
github.com/dlclark/regexp2 v1.11.0 // indirect github.com/dlclark/regexp2 v1.11.0 // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/gorilla/css v1.0.1 // indirect github.com/gorilla/css v1.0.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
@@ -34,15 +36,25 @@ require (
github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/reflow v0.3.0 // indirect github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/rivo/uniseg v0.4.7 // indirect github.com/rivo/uniseg v0.4.7 // indirect
github.com/sagikazarmark/locafero v0.7.0 // indirect
github.com/sahilm/fuzzy v0.1.1 // indirect github.com/sahilm/fuzzy v0.1.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.12.0 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/spf13/viper v1.20.1 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/yuin/goldmark v1.7.4 // indirect github.com/yuin/goldmark v1.7.4 // indirect
github.com/yuin/goldmark-emoji v1.0.3 // indirect github.com/yuin/goldmark-emoji v1.0.3 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/crypto v0.36.0 // indirect golang.org/x/crypto v0.36.0 // indirect
golang.org/x/net v0.38.0 // indirect golang.org/x/net v0.38.0 // indirect
golang.org/x/sync v0.12.0 // indirect golang.org/x/sync v0.12.0 // indirect
golang.org/x/sys v0.31.0 // indirect golang.org/x/sys v0.31.0 // indirect
golang.org/x/term v0.30.0 // indirect golang.org/x/term v0.30.0 // indirect
golang.org/x/text v0.23.0 // indirect golang.org/x/text v0.23.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
) )
+30 -1
View File
@@ -31,10 +31,16 @@ github.com/charmbracelet/x/exp/teatest v0.0.0-20241024145942-ad25fd0d5a9e/go.mod
github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0= github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0=
github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0= github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
@@ -64,22 +70,44 @@ github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a h1:2MaM6YC3mGu54x+RKAA6JiFFHlHDY1UbkxqppT7wYOg= github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a h1:2MaM6YC3mGu54x+RKAA6JiFFHlHDY1UbkxqppT7wYOg=
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a/go.mod h1:hxSnBBYLK21Vtq/PHd0S2FYCxBXzBua8ov5s1RobyRQ= github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a/go.mod h1:hxSnBBYLK21Vtq/PHd0S2FYCxBXzBua8ov5s1RobyRQ=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA= github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg= github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg=
github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
github.com/yuin/goldmark-emoji v1.0.3 h1:aLRkLHOuBR2czCY4R8olwMjID+tENfhyFDMCRhbIQY4= github.com/yuin/goldmark-emoji v1.0.3 h1:aLRkLHOuBR2czCY4R8olwMjID+tENfhyFDMCRhbIQY4=
github.com/yuin/goldmark-emoji v1.0.3/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U= github.com/yuin/goldmark-emoji v1.0.3/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
@@ -95,4 +123,5 @@ golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+2 -3
View File
@@ -6,8 +6,6 @@ import (
"os" "os"
"strings" "strings"
"testing" "testing"
"github.com/Slug-Boi/cocommit/src/cmd/utils"
) )
const author_data = ` const author_data = `
@@ -34,7 +32,7 @@ const author_data = `
} }
}` }`
var envVar = utils.Find_authorfile() var envVar string
func setup() { func setup() {
// setup test data // setup test data
@@ -50,6 +48,7 @@ func teardown() {
// remove test data // remove test data
os.Remove("author_file_test") os.Remove("author_file_test")
os.Setenv("author_file", envVar) os.Setenv("author_file", envVar)
os.Remove("config.toml")
} }
// Skip cobra cmd tests on CI causes problems apparenly idk why // Skip cobra cmd tests on CI causes problems apparenly idk why
+35 -7
View File
@@ -142,7 +142,7 @@ const (
type Model struct { type Model struct {
list list.Model list list.Model
swap_lists [][]list.Item swap_lists [3][]list.Item
keys *listKeyMap keys *listKeyMap
quitting bool quitting bool
scope int scope int
@@ -255,8 +255,8 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if m.scope == git_scope { if m.scope == git_scope {
m.scope = local_scope m.scope = local_scope
m.list.Title = title_text + local_scope_style.Render("Scope: LOCAL") m.list.Title = title_text + local_scope_style.Render("Scope: LOCAL")
if len(m.swap_lists) < 2 { if len(m.swap_lists[1]) == 0 {
m.swap_lists = append(m.swap_lists, generate_list(local_scope)) m.swap_lists[1] = generate_list(local_scope)
} }
m.list.SetItems(m.swap_lists[1]) m.list.SetItems(m.swap_lists[1])
m.list.ResetFilter() m.list.ResetFilter()
@@ -265,8 +265,8 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if m.scope == local_scope { if m.scope == local_scope {
m.scope = mixed_scope m.scope = mixed_scope
m.list.Title = title_text + mixed_scope_style.Render("Scope: MIXED") m.list.Title = title_text + mixed_scope_style.Render("Scope: MIXED")
if len(m.swap_lists) < 3 { if len(m.swap_lists[2]) == 0 {
m.swap_lists = append(m.swap_lists, generate_list(mixed_scope)) m.swap_lists[2] = generate_list(mixed_scope)
} }
m.list.SetItems(m.swap_lists[2]) m.list.SetItems(m.swap_lists[2])
m.list.ResetFilter() m.list.ResetFilter()
@@ -275,6 +275,9 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if m.scope == mixed_scope { if m.scope == mixed_scope {
m.scope = git_scope m.scope = git_scope
m.list.Title = title_text + git_scope_style.Render("Scope: GIT") m.list.Title = title_text + git_scope_style.Render("Scope: GIT")
if len(m.swap_lists[0]) == 0 {
m.swap_lists[0] = generate_list(git_scope)
}
m.list.SetItems(m.swap_lists[0]) m.list.SetItems(m.swap_lists[0])
m.list.ResetFilter() m.list.ResetFilter()
return m, nil return m, nil
@@ -360,6 +363,19 @@ func generate_list(scope int) []list.Item {
} }
func ConvertStringScopeToIOTA(scope string) int {
switch scope {
case "git":
return git_scope
case "local":
return local_scope
case "mixed":
return mixed_scope
default:
return -1
}
}
func (m Model) View() string { func (m Model) View() string {
if sub_model != nil { if sub_model != nil {
return sub_model.View() return sub_model.View()
@@ -391,6 +407,7 @@ func listModel(scope ...int) Model {
// Add items to the list // Add items to the list
if len(scope) == 0 { if len(scope) == 0 {
git_scope := ConvertStringScopeToIOTA(utils.ConfigVar.Settings.StartingScope)
scope = append(scope, git_scope) scope = append(scope, git_scope)
} }
items := generate_list(scope[0]) items := generate_list(scope[0])
@@ -402,7 +419,16 @@ func listModel(scope ...int) Model {
const defaultWidth = 20 const defaultWidth = 20
l := list.New(items, itemDelegate{}, defaultWidth, listHeight) l := list.New(items, itemDelegate{}, defaultWidth, listHeight)
l.Title = title_text + lipgloss.NewStyle().Foreground(lipgloss.Color("170")).Render("Scope: GIT")
switch scope[0] {
case git_scope:
l.Title = title_text + git_scope_style.Render("Scope: GIT")
case local_scope:
l.Title = title_text + local_scope_style.Render("Scope: LOCAL")
case mixed_scope:
l.Title = title_text + mixed_scope_style.Render("Scope: MIXED")
}
l.SetShowStatusBar(false) l.SetShowStatusBar(false)
l.SetFilteringEnabled(true) // Enable filtering l.SetFilteringEnabled(true) // Enable filtering
l.Styles.Title = titleStyle l.Styles.Title = titleStyle
@@ -427,7 +453,9 @@ func listModel(scope ...int) Model {
} }
l.Styles.HelpStyle = helpStyle l.Styles.HelpStyle = helpStyle
model := Model{list: l, swap_lists: [][]list.Item{items}, keys: listKeys, scope: git_scope} swapLists := [3][]list.Item{}
swapLists[scope[0]] = items
model := Model{list: l, swap_lists: swapLists, keys: listKeys, scope: scope[0]}
//TODO: figure out async create //TODO: figure out async create
// IDEA DO IT WITH CHANNELS // IDEA DO IT WITH CHANNELS
+4 -4
View File
@@ -610,8 +610,8 @@ func Test_ScopesLocal(t *testing.T) {
t.Errorf("Expected model, got %T", fm) t.Errorf("Expected model, got %T", fm)
} }
if m.scope!= local_scope { if m.scope!= mixed_scope {
t.Errorf("Expected scope to be %v, got %v", local_scope, m.scope) t.Errorf("Expected scope to be %v, got %v", mixed_scope, m.scope)
} }
} }
@@ -634,8 +634,8 @@ func Test_ScopesMixed(t *testing.T) {
t.Errorf("Expected model, got %T", fm) t.Errorf("Expected model, got %T", fm)
} }
if m.scope != mixed_scope { if m.scope != local_scope {
t.Errorf("Expected scope to be %v, got %v", mixed_scope, m.scope) t.Errorf("Expected scope to be %v, got %v", local_scope, m.scope)
} }
} }
+4 -1
View File
@@ -12,7 +12,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
var authorfile = utils.Find_authorfile() var authorfile string
// usersCmd represents the users command // usersCmd represents the users command
func UsersCmd() *cobra.Command { func UsersCmd() *cobra.Command {
@@ -21,6 +21,9 @@ func UsersCmd() *cobra.Command {
Short: "Displays all users from the author file located at:\n" + authorfile, Short: "Displays all users from the author file located at:\n" + authorfile,
Long: `Displays all users from the author file located at:` + "\n" + authorfile, Long: `Displays all users from the author file located at:` + "\n" + authorfile,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if authorfile == "" {
authorfile = utils.Find_authorfile()
}
if update { if update {
update_msg() update_msg()
} }
+37 -4
View File
@@ -13,12 +13,45 @@ import (
// that contains the names and emails of the users that are allowed to commit // that contains the names and emails of the users that are allowed to commit
// An example of the author file can be found in the examples folder of the repo // An example of the author file can be found in the examples folder of the repo
func Find_authorfile() string { func Find_authorfile() string {
var file string
if os.Getenv("author_file") == "" { if os.Getenv("author_file") == "" {
dirs, err := os.UserConfigDir() if ConfigVar == nil {
if err != nil { cfg, _ := LoadConfig()
panic(fmt.Sprintf("Error getting user config directory: %v", err)) if cfg == nil {
// mimic the default config structure
cfg = &Config{
Settings: struct {
AuthorFile string `mapstructure:"author_file"`
StartingScope string `mapstructure:"starting_scope"`
Editor string `mapstructure:"editor"`
}{
AuthorFile: "",
StartingScope: "git",
Editor: "built-in",
},
}
cfg.SetGlobalConfig()
}
} }
return (dirs + "/cocommit/authors.json")
if ConfigVar.Settings.AuthorFile != "" {
file = ConfigVar.Settings.AuthorFile
} else if os.Getenv("author_file") != "" {
file = os.Getenv("author_file")
} else {
userconf, err :=os.UserConfigDir()
if err != nil {
panic(fmt.Sprintf("Error getting user config dir: %v", err))
}
if _, err := os.Stat(userconf+"/cocommit/authors.json"); os.IsNotExist(err) {
panic(fmt.Sprintf("No author file set, please set the author_file environment variable or create a config file using the command: cocommit config -c"))
} else {
file = userconf + "/cocommit/authors.json"
}
}
return file
} else { } else {
return os.Getenv("author_file") return os.Getenv("author_file")
} }
+182
View File
@@ -0,0 +1,182 @@
package utils
import (
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/spf13/viper"
)
var ConfigVar *Config
var (
defaultConfigLocations = []string{
"",
os.Getenv("COCOMMIT_CONFIG"),
os.Getenv("HOME") + "/.config/cocommit",
os.Getenv("HOME") + "/cocommit",
"/etc/cocommit",
"/usr/local/etc/cocommit",
}
configName = "config"
configType = "toml"
)
type Config struct {
Settings struct {
AuthorFile string `mapstructure:"author_file"`
StartingScope string `mapstructure:"starting_scope"`
Editor string `mapstructure:"editor"`
} `mapstructure:"settings"`
}
func init() {
configDir, err := os.UserConfigDir()
if err == nil {
defaultConfigLocations[0] = filepath.Join(configDir, "cocommit")
}
}
func LoadConfig() (*Config, error) {
// TODO: create if and give param as default config location
v := viper.New()
v.SetConfigName(configName)
v.SetConfigType(configType)
// Set default values
v.SetDefault("settings.author_file", defaultConfigLocations[0]+"/authors.json")
v.SetDefault("settings.starting_scope", "git")
v.SetDefault("settings.editor", "built-in")
// Add search paths
for _, path := range defaultConfigLocations {
if path != "" {
v.AddConfigPath(path)
}
}
// Try to read config
if err := v.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
return nil, nil
}
// if _, ok := err.(viper.ConfigFileNotFoundError); ok {
// if err := handleMissingConfig(v); err != nil {
// return nil, err
// }
// } else {
// return nil, fmt.Errorf("config error: %w", err)
// }
}
var cfg Config
if err := v.Unmarshal(&cfg); err != nil {
return nil, fmt.Errorf("config unmarshal error: %w", err)
}
if cfg.Settings.AuthorFile == "" {
cfg.Settings.AuthorFile = defaultConfigLocations[0] + "/authors.json"
}
return &cfg, nil
}
func (c *Config) SetGlobalConfig() {
if ConfigVar == nil {
ConfigVar = c
// This doesnt really do much right now but might be useful later
viper.WatchConfig()
}
}
func handleMissingConfig(v *viper.Viper) error {
fmt.Println("Config file not found. Would you like to create one? (y/n)")
var response string
if _, err := fmt.Scanln(&response); err != nil {
return fmt.Errorf("error reading response: %w", err)
}
yesResponses := map[string]bool{"y": true, "Y": true, "yes": true, "Yes": true, "YES": true}
if !yesResponses[strings.TrimSpace(response)] {
return fmt.Errorf("config file not found")
}
return createConfig(v)
}
func createConfig(v *viper.Viper) error {
fmt.Println("Where would you like to create the config file?")
for i, path := range defaultConfigLocations {
fmt.Printf("%d. %s\n", i, path)
}
fmt.Println("Please enter the number of the location or a custom path:")
var response string
if _, err := fmt.Scanln(&response); err != nil {
return fmt.Errorf("error reading response: %w", err)
}
var configPath string
if num, err := strconv.Atoi(response); err == nil && num >= 0 && num < len(defaultConfigLocations) {
configPath = defaultConfigLocations[num]
} else {
configPath = response
}
// Ensure directory exists
if err := os.MkdirAll(configPath, 0755); err != nil {
return fmt.Errorf("failed to create config directory: %w", err)
}
// Set the config file path
fullPath := filepath.Join(configPath, fmt.Sprintf("%s.%s", configName, configType))
v.SetConfigFile(fullPath)
// Write default config
if err := v.SafeWriteConfig(); err != nil {
return fmt.Errorf("failed to write config: %w", err)
}
fmt.Printf("Config file created at: %s\n", fullPath)
return nil
}
func (c *Config) Save() error {
v := viper.New()
// Set all configuration values from the struct
v.Set("settings.author_file", c.Settings.AuthorFile)
v.Set("settings.starting_scope", c.Settings.StartingScope)
v.Set("settings.editor", c.Settings.Editor)
v.SetConfigName(configName)
v.SetConfigType(configType)
// Try to determine the original config file location
if viper.ConfigFileUsed() != "" {
v.SetConfigFile(viper.ConfigFileUsed())
} else {
// Fall back to first default location if no existing config
if len(defaultConfigLocations) > 0 && defaultConfigLocations[0] != "" {
v.SetConfigFile(filepath.Join(defaultConfigLocations[0], fmt.Sprintf("%s.%s", configName, configType)))
} else {
return fmt.Errorf("no config file location available")
}
}
// Ensure the directory exists
configDir := filepath.Dir(v.ConfigFileUsed())
if err := os.MkdirAll(configDir, 0755); err != nil {
return fmt.Errorf("failed to create config directory: %w", err)
}
// Write the config file
if err := v.WriteConfig(); err != nil {
return fmt.Errorf("failed to save config: %w", err)
}
return nil
}
+34 -9
View File
@@ -38,10 +38,27 @@ const author_data = `
} }
}` }`
const config_data = `[settings]
author_file = "author_file_test"
starting_scope = "git"
editor = "built-in"
`
var envVar = os.Getenv("author_file") var envVar = os.Getenv("author_file")
func setup() { func setup() {
os.Setenv("author_file", "")
// setup test data // setup test data
err := os.WriteFile("config.toml", []byte(config_data), 0644)
if err != nil {
panic(err)
}
os.Setenv("COCOMMIT_CONFIG", "config.toml")
os.WriteFile("author_file_test", []byte(author_data), 0644) os.WriteFile("author_file_test", []byte(author_data), 0644)
os.Setenv("author_file", "author_file_test") os.Setenv("author_file", "author_file_test")
} }
@@ -50,6 +67,7 @@ func teardown() {
// remove test data // remove test data
os.Remove("author_file_test") os.Remove("author_file_test")
os.Setenv("author_file", envVar) os.Setenv("author_file", envVar)
os.Remove("config.toml")
} }
// Author tests BEGIN // Author tests BEGIN
@@ -124,6 +142,8 @@ func Test_CreateAuthor(t *testing.T) {
} }
func Test_FindAuthorFilePanic(t *testing.T) { func Test_FindAuthorFilePanic(t *testing.T) {
setup()
defer teardown()
// Save original environment variables // Save original environment variables
originalAuthorFile := os.Getenv("author_file") originalAuthorFile := os.Getenv("author_file")
originalHome := os.Getenv("HOME") originalHome := os.Getenv("HOME")
@@ -153,16 +173,21 @@ func Test_FindAuthorFileEnv(t *testing.T) {
// Test Find_authorfile with env var // Test Find_authorfile with env var
setup() setup()
defer teardown() defer teardown()
os.Setenv("author_file", "")
authorfile := utils.Find_authorfile()
configdir, err := os.UserConfigDir()
if err != nil {
t.Fatalf("Failed to get user config directory: %v", err)
}
if authorfile != configdir+"/cocommit/authors.json" {
t.Errorf("Find_authorfile() = %v; want %v", authorfile, configdir+"/cocommit/authors.json")
}
originalAuthorFile := os.Getenv("author_file")
defer func() {
os.Setenv("author_file", originalAuthorFile)
if r := recover(); r == nil {
t.Errorf("Find_authorfile() did not panic")
}
}()
// Set an invalid environment variable to trigger panic
os.Setenv("author_file", "")
utils.Find_authorfile()
} }
func Test_CreateAuthorPanicOnFileError(t *testing.T) { func Test_CreateAuthorPanicOnFileError(t *testing.T) {