11package cmd
22
33import (
4+ "bytes"
5+ "fmt"
6+ "io/ioutil"
7+ "os"
8+ "path/filepath"
9+ "strings"
10+
411 "github.com/nao1215/gup/internal/assets"
12+ "github.com/nao1215/gup/internal/completion"
13+ "github.com/nao1215/gup/internal/file"
514 "github.com/nao1215/gup/internal/print"
615 "github.com/spf13/cobra"
716)
@@ -15,7 +24,206 @@ If you update all binaries, just run '$ gup update'`,
1524// Execute run gup process.
1625func Execute () {
1726 assets .DeployIconIfNeeded ()
27+ deployShellCompletionFileIfNeeded (rootCmd )
28+
29+ rootCmd .CompletionOptions .DisableDefaultCmd = true
1830 if err := rootCmd .Execute (); err != nil {
1931 print .Err (err )
2032 }
2133}
34+
35+ // deleteShellCompletionFileIfNeeded creates the shell completion file.
36+ // If the file with the same contents already exists, it is not created.
37+ func deployShellCompletionFileIfNeeded (cmd * cobra.Command ) {
38+ makeBashCompletionFileIfNeeded (cmd )
39+ makeFishCompletionFileIfNeeded (cmd )
40+ makeZshCompletionFileIfNeeded (cmd )
41+ }
42+
43+ func makeBashCompletionFileIfNeeded (cmd * cobra.Command ) {
44+ if existSameBashCompletionFile (cmd ) {
45+ return
46+ }
47+
48+ path := completion .BashCompletionFilePath ()
49+ bashCompletion := new (bytes.Buffer )
50+ if err := cmd .GenBashCompletion (bashCompletion ); err != nil {
51+ print .Err (fmt .Errorf ("can not generate bash completion content: %w" , err ))
52+ return
53+ }
54+
55+ if ! file .IsFile (path ) {
56+ fp , err := os .OpenFile (path , os .O_RDWR | os .O_CREATE , 0664 )
57+ if err != nil {
58+ print .Err (fmt .Errorf ("can not create .bash_completion: %w" , err ))
59+ return
60+ }
61+ defer fp .Close ()
62+
63+ if _ , err := fp .WriteString (bashCompletion .String ()); err != nil {
64+ print .Err (fmt .Errorf ("can not write .bash_completion %w" , err ))
65+ }
66+ print .Info ("create bash-completion file: " + path )
67+ return
68+ }
69+
70+ fp , err := os .OpenFile (path , os .O_RDWR | os .O_APPEND , 0664 )
71+ if err != nil {
72+ print .Err (fmt .Errorf ("can not append .bash_completion for gup: %w" , err ))
73+ return
74+ }
75+ defer fp .Close ()
76+
77+ if _ , err := fp .WriteString (bashCompletion .String ()); err != nil {
78+ print .Err (fmt .Errorf ("can not append .bash_completion for gup: %w" , err ))
79+ return
80+ }
81+
82+ print .Info ("append bash-completion for gup: " + path )
83+ }
84+
85+ func makeFishCompletionFileIfNeeded (cmd * cobra.Command ) {
86+ if isSameFishCompletionFile (cmd ) {
87+ return
88+ }
89+
90+ path := completion .FishCompletionFilePath ()
91+ if err := os .MkdirAll (filepath .Dir (path ), 0775 ); err != nil {
92+ print .Err (fmt .Errorf ("can not create fish-completion file: %w" , err ))
93+ return
94+ }
95+
96+ if err := cmd .GenFishCompletionFile (path , false ); err != nil {
97+ print .Err (fmt .Errorf ("can not create fish-completion file: %w" , err ))
98+ return
99+ }
100+ print .Info ("create fish-completion file: " + path )
101+ }
102+
103+ func makeZshCompletionFileIfNeeded (cmd * cobra.Command ) {
104+ if isSameZshCompletionFile (cmd ) {
105+ return
106+ }
107+
108+ path := completion .ZshCompletionFilePath ()
109+ if err := os .MkdirAll (filepath .Dir (path ), 0775 ); err != nil {
110+ print .Err (fmt .Errorf ("can not create zsh-completion file: %w" , err ))
111+ return
112+ }
113+
114+ if err := cmd .GenZshCompletionFile (path ); err != nil {
115+ print .Err (fmt .Errorf ("can not create zsh-completion file: %w" , err ))
116+ return
117+ }
118+ print .Info ("create zsh-completion file: " + path )
119+
120+ const zshFpath = `
121+ # setting for gup command (auto generate)
122+ fpath=(~/.zsh/completion $fpath)
123+ autoload -Uz compinit && compinit -i
124+ `
125+ zshrcPath := completion .ZshrcPath ()
126+ if ! file .IsFile (zshrcPath ) {
127+ fp , err := os .OpenFile (zshrcPath , os .O_RDWR | os .O_CREATE , 0664 )
128+ if err != nil {
129+ print .Err (fmt .Errorf ("can not add zsh $fpath in .zshrc: %w" , err ))
130+ return
131+ }
132+ defer fp .Close ()
133+
134+ if _ , err := fp .WriteString (zshFpath ); err != nil {
135+ print .Err (fmt .Errorf ("can not add zsh $fpath in .zshrc: %w" , err ))
136+ }
137+ return
138+ }
139+
140+ zshrc , err := ioutil .ReadFile (zshrcPath )
141+ if err != nil {
142+ print .Err (fmt .Errorf ("can not read .zshrc: %w" , err ))
143+ return
144+ }
145+
146+ if strings .Contains (string (zshrc ), zshFpath ) {
147+ return
148+ }
149+
150+ fp , err := os .OpenFile (zshrcPath , os .O_RDWR | os .O_APPEND , 0664 )
151+ if err != nil {
152+ print .Err (fmt .Errorf ("can not add zsh $fpath in .zshrc: %w" , err ))
153+ return
154+ }
155+ defer fp .Close ()
156+
157+ if _ , err := fp .WriteString (zshFpath ); err != nil {
158+ print .Err (fmt .Errorf ("can not add zsh $fpath in .zshrc: %w" , err ))
159+ return
160+ }
161+ }
162+
163+ func existSameBashCompletionFile (cmd * cobra.Command ) bool {
164+ if ! file .IsFile (completion .BashCompletionFilePath ()) {
165+ return false
166+ }
167+ return hasSameBashCompletionContent (cmd )
168+ }
169+
170+ func hasSameBashCompletionContent (cmd * cobra.Command ) bool {
171+ bashCompletionFileInLocal , err := ioutil .ReadFile (completion .BashCompletionFilePath ())
172+ if err != nil {
173+ print .Err (fmt .Errorf ("can not read .bash_completion: %w" , err ))
174+ return false
175+ }
176+
177+ currentBashCompletion := new (bytes.Buffer )
178+ if err := cmd .GenBashCompletion (currentBashCompletion ); err != nil {
179+ return false
180+ }
181+ if ! strings .Contains (string (bashCompletionFileInLocal ), currentBashCompletion .String ()) {
182+ return false
183+ }
184+ return true
185+ }
186+
187+ func isSameFishCompletionFile (cmd * cobra.Command ) bool {
188+ path := completion .FishCompletionFilePath ()
189+ if ! file .IsFile (path ) {
190+ return false
191+ }
192+
193+ currentFishCompletion := new (bytes.Buffer )
194+ if err := cmd .GenFishCompletion (currentFishCompletion , false ); err != nil {
195+ return false
196+ }
197+
198+ fishCompletionInLocal , err := ioutil .ReadFile (path )
199+ if err != nil {
200+ return false
201+ }
202+
203+ if bytes .Compare (currentFishCompletion .Bytes (), fishCompletionInLocal ) != 0 {
204+ return false
205+ }
206+ return true
207+ }
208+
209+ func isSameZshCompletionFile (cmd * cobra.Command ) bool {
210+ path := completion .ZshCompletionFilePath ()
211+ if ! file .IsFile (path ) {
212+ return false
213+ }
214+
215+ currentZshCompletion := new (bytes.Buffer )
216+ if err := cmd .GenZshCompletion (currentZshCompletion ); err != nil {
217+ return false
218+ }
219+
220+ zshCompletionInLocal , err := ioutil .ReadFile (path )
221+ if err != nil {
222+ return false
223+ }
224+
225+ if bytes .Compare (currentZshCompletion .Bytes (), zshCompletionInLocal ) != 0 {
226+ return false
227+ }
228+ return true
229+ }
0 commit comments