@@ -30,6 +30,9 @@ func runInstall(cmd *cobra.Command) error {
3030 Bold (true ).
3131 Foreground (lipgloss .Color ("#00FF00" ))
3232
33+ stepStyle := lipgloss .NewStyle ().
34+ Foreground (lipgloss .Color ("#87D7FF" ))
35+
3336 // Get the path to the current executable
3437 exe , err := os .Executable ()
3538 if err != nil {
@@ -55,22 +58,19 @@ func runInstall(cmd *cobra.Command) error {
5558 }
5659 }
5760
58- // If we are in a temp directory or not in the expected location,
59- // we might want to copy ourselves?
60- // The script does the downloading, so we assume we are already in ~/.major/bin/major
61- // We just need to ensure ~/.major/bin is in PATH
62-
6361 home , err := os .UserHomeDir ()
6462 if err != nil {
6563 return fmt .Errorf ("failed to get user home dir: %w" , err )
6664 }
6765
6866 shell := os .Getenv ("SHELL" )
6967 var configFile string
68+ var shellType string
7069
7170 switch {
7271 case strings .Contains (shell , "zsh" ):
7372 configFile = filepath .Join (home , ".zshrc" )
73+ shellType = "zsh"
7474 case strings .Contains (shell , "bash" ):
7575 configFile = filepath .Join (home , ".bashrc" )
7676 // Check for .bash_profile on macOS
@@ -79,18 +79,77 @@ func runInstall(cmd *cobra.Command) error {
7979 configFile = filepath .Join (home , ".bash_profile" )
8080 }
8181 }
82+ shellType = "bash"
8283 default :
8384 // Fallback or skip
8485 cmd .Println ("Could not detect compatible shell (zsh/bash). Please add the following to your path manually:" )
8586 cmd .Printf (" export PATH=\" %s:$PATH\" \n " , binDir )
8687 return nil
8788 }
8889
89- // Check if already in config
90+ // Create completions directory
91+ completionsDir := filepath .Join (home , ".major" , "completions" )
92+ if err := os .MkdirAll (completionsDir , 0755 ); err != nil {
93+ return fmt .Errorf ("failed to create completions directory: %w" , err )
94+ }
95+
96+ // Generate completion script
97+ cmd .Println (stepStyle .Render ("▸ Generating shell completions..." ))
98+
99+ var completionEntry string
100+ switch shellType {
101+ case "zsh" :
102+ // For Zsh, we generate _major file and add directory to fpath
103+ completionFile := filepath .Join (completionsDir , "_major" )
104+ f , err := os .Create (completionFile )
105+ if err != nil {
106+ return fmt .Errorf ("failed to create zsh completion file: %w" , err )
107+ }
108+ defer f .Close ()
109+
110+ if err := cmd .Root ().GenZshCompletion (f ); err != nil {
111+ return fmt .Errorf ("failed to generate zsh completion: %w" , err )
112+ }
113+
114+ // We need to add fpath before compinit
115+ // But often users already have compinit in their .zshrc
116+ // The safest robust way is to append to fpath and ensure compinit is called
117+ completionEntry = fmt .Sprintf (`
118+ # Major CLI
119+ export PATH="%s:$PATH"
120+ export FPATH="%s:$FPATH"
121+ # Ensure compinit is loaded (if not already)
122+ autoload -U compinit && compinit
123+ ` , binDir , completionsDir )
124+
125+ case "bash" :
126+ completionFile := filepath .Join (completionsDir , "major.bash" )
127+ f , err := os .Create (completionFile )
128+ if err != nil {
129+ return fmt .Errorf ("failed to create bash completion file: %w" , err )
130+ }
131+ defer f .Close ()
132+
133+ if err := cmd .Root ().GenBashCompletion (f ); err != nil {
134+ return fmt .Errorf ("failed to generate bash completion: %w" , err )
135+ }
136+
137+ completionEntry = fmt .Sprintf (`
138+ # Major CLI
139+ export PATH="%s:$PATH"
140+ source "%s"
141+ ` , binDir , completionFile )
142+ }
143+
144+ // Check if already configured
90145 content , err := os .ReadFile (configFile )
91146 if err == nil {
92- if strings .Contains (string (content ), binDir ) {
93- cmd .Println (successStyle .Render ("Major CLI is already in your PATH!" ))
147+ // If we already see our marker or the bin path, we might want to update it or skip
148+ // But the user might have moved the directory.
149+ // Let's check for our specific comment
150+ if strings .Contains (string (content ), "# Major CLI" ) {
151+ cmd .Println (successStyle .Render ("Major CLI is already configured in your shell!" ))
152+ // We still re-generated the completion file above, which is good for updates.
94153 return nil
95154 }
96155 }
@@ -102,13 +161,12 @@ func runInstall(cmd *cobra.Command) error {
102161 }
103162 defer f .Close ()
104163
105- pathEntry := fmt .Sprintf ("\n # Major CLI\n export PATH=\" %s:$PATH\" \n " , binDir )
106- if _ , err := f .WriteString (pathEntry ); err != nil {
164+ if _ , err := f .WriteString (completionEntry ); err != nil {
107165 return fmt .Errorf ("failed to write to shell config file: %w" , err )
108166 }
109167
110- cmd .Println (successStyle .Render (fmt .Sprintf ("Added Major CLI to %s" , configFile )))
111- cmd .Println ("Please restart your shell or source your config file to start using 'major'" )
168+ cmd .Println (successStyle .Render (fmt .Sprintf ("Added Major CLI configuration to %s" , configFile )))
169+ cmd .Println ("Please restart your shell or run ' source " + configFile + "' to start using 'major'" )
112170
113171 return nil
114172}
0 commit comments