Skip to content

Commit e4f5cf8

Browse files
kitsunoffclaude
authored andcommitted
fix: skip config loading for __complete command
The __complete command is cobra's internal hidden command used for shell autocompletion (triggered when user presses Tab). It was not included in the skip list after PR #109, causing autocompletion to fail outside project directories. Bug reproduction: $ talm __complete ini "" error loading configuration: error reading configuration file: open Chart.yaml: no such file or directory Changes: - Add "__complete" to skipConfigCommands list - Extract command list to a variable for testability and documentation - Add unit tests for isCommandOrParent and skipConfigCommands 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: ZverGuy <maximbel2003@gmail.com>
1 parent 2ba7459 commit e4f5cf8

2 files changed

Lines changed: 133 additions & 1 deletion

File tree

main.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ import (
1919

2020
var Version = "dev"
2121

22+
// skipConfigCommands lists commands that should not load Chart.yaml config.
23+
// - init: creates the config, so it doesn't exist yet
24+
// - completion: generates shell completion scripts
25+
// - __complete: cobra's internal command for shell autocompletion (Tab key)
26+
var skipConfigCommands = []string{"init", "completion", "__complete"}
27+
2228
// rootCmd represents the base command when called without any subcommands.
2329
var rootCmd = &cobra.Command{
2430
Use: "talm",
@@ -87,7 +93,7 @@ func init() {
8793
}
8894

8995
// Load config after root detection (skip for init and completion commands)
90-
if !isCommandOrParent(cmd, "init", "completion") {
96+
if !isCommandOrParent(cmd, skipConfigCommands...) {
9197
configFile := filepath.Join(commands.Config.RootDir, "Chart.yaml")
9298
if err := loadConfig(configFile); err != nil {
9399
return fmt.Errorf("error loading configuration: %w", err)

main_test.go

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package main
2+
3+
import (
4+
"testing"
5+
6+
"github.com/spf13/cobra"
7+
)
8+
9+
// buildCommandHierarchy creates a cobra command hierarchy from a path like
10+
// ["talm", "completion", "bash"] and returns the leaf command.
11+
func buildCommandHierarchy(path []string) *cobra.Command {
12+
if len(path) == 0 {
13+
return nil
14+
}
15+
16+
root := &cobra.Command{Use: path[0]}
17+
parent := root
18+
19+
for _, name := range path[1:] {
20+
child := &cobra.Command{Use: name}
21+
parent.AddCommand(child)
22+
parent = child
23+
}
24+
25+
return parent
26+
}
27+
28+
func TestIsCommandOrParent(t *testing.T) {
29+
tests := []struct {
30+
name string
31+
cmdPath []string
32+
names []string
33+
expected bool
34+
}{
35+
{
36+
name: "direct completion command",
37+
cmdPath: []string{"talm", "completion"},
38+
names: []string{"init", "completion"},
39+
expected: true,
40+
},
41+
{
42+
name: "completion bash subcommand",
43+
cmdPath: []string{"talm", "completion", "bash"},
44+
names: []string{"init", "completion"},
45+
expected: true,
46+
},
47+
{
48+
name: "init command",
49+
cmdPath: []string{"talm", "init"},
50+
names: []string{"init", "completion"},
51+
expected: true,
52+
},
53+
{
54+
name: "apply command should not match",
55+
cmdPath: []string{"talm", "apply"},
56+
names: []string{"init", "completion"},
57+
expected: false,
58+
},
59+
}
60+
61+
for _, tt := range tests {
62+
t.Run(tt.name, func(t *testing.T) {
63+
leaf := buildCommandHierarchy(tt.cmdPath)
64+
result := isCommandOrParent(leaf, tt.names...)
65+
if result != tt.expected {
66+
t.Errorf("isCommandOrParent() = %v, want %v", result, tt.expected)
67+
}
68+
})
69+
}
70+
}
71+
72+
func TestSkipConfigCommands(t *testing.T) {
73+
tests := []struct {
74+
name string
75+
cmdPath []string
76+
expected bool // true = should skip config loading
77+
}{
78+
{
79+
name: "completion command",
80+
cmdPath: []string{"talm", "completion"},
81+
expected: true,
82+
},
83+
{
84+
name: "completion bash",
85+
cmdPath: []string{"talm", "completion", "bash"},
86+
expected: true,
87+
},
88+
{
89+
name: "completion zsh",
90+
cmdPath: []string{"talm", "completion", "zsh"},
91+
expected: true,
92+
},
93+
{
94+
name: "__complete (cobra internal for shell autocompletion)",
95+
cmdPath: []string{"talm", "__complete"},
96+
expected: true,
97+
},
98+
{
99+
name: "init command",
100+
cmdPath: []string{"talm", "init"},
101+
expected: true,
102+
},
103+
{
104+
name: "apply command should load config",
105+
cmdPath: []string{"talm", "apply"},
106+
expected: false,
107+
},
108+
{
109+
name: "template command should load config",
110+
cmdPath: []string{"talm", "template"},
111+
expected: false,
112+
},
113+
}
114+
115+
for _, tt := range tests {
116+
t.Run(tt.name, func(t *testing.T) {
117+
leaf := buildCommandHierarchy(tt.cmdPath)
118+
// This uses the actual skipConfigCommands from main.go
119+
result := isCommandOrParent(leaf, skipConfigCommands...)
120+
if result != tt.expected {
121+
t.Errorf("skipConfigCommands check = %v, want %v (skipConfigCommands = %v)",
122+
result, tt.expected, skipConfigCommands)
123+
}
124+
})
125+
}
126+
}

0 commit comments

Comments
 (0)