diff --git a/cmd/gi_gen.go b/cmd/gi_gen.go index 7d4926e..42170d2 100644 --- a/cmd/gi_gen.go +++ b/cmd/gi_gen.go @@ -1,6 +1,8 @@ package cmd import ( + "flag" + "fmt" "log" "os" "path/filepath" @@ -9,6 +11,43 @@ import ( ) func RunMainCmd() { + helpCommand() + + shouldReturn := cleanCommand() + if shouldReturn { + return + } + + RunGIGen() +} + +func cleanCommand() bool { + var clean *bool = flag.Bool("cache-clean", false, "Clear the .gitignore cache directory, for troubleshooting or for removing trace files of this program.") + flag.Parse() + + if *clean { + RemoveCacheDir() + return true + } + return false +} + +func helpCommand() { + flag.Usage = func() { + w := flag.CommandLine.Output() + + fmt.Fprint(w, "Usage: gi_gen [options]\n\n") + fmt.Fprint(w, "This program generates .gitignore files for any project. You may clean unused\nlines from the generated file, and the program auto-discovers relevant\n.gitignore templates unless asked not to when the prompt appears.\n\n") + fmt.Fprint(w, "Run without arguments to use the normal functionality of gi_gen.\n\n") + fmt.Fprint(w, "Available flags:\n\n") + flag.PrintDefaults() + fmt.Fprintf(w, "\nCopyright © 2022 - Chen Asraf\nhttps://casraf.blog\nhttps://github.com/chenasraf/gi_gen\n") + } + + flag.Bool("help", false, "Display help message") +} + +func RunGIGen() { wd, err := os.Getwd() HandleErr(err) @@ -16,13 +55,13 @@ func RunMainCmd() { allFiles, err := PrepareGitignores() HandleErr(err) - fileNames, files := GetRelevantFiles(allFiles) + fileNames, files := DiscoverRelevantFiles(allFiles) log.Println("Done.") selected, selectedKeys := GetLanguageSelections(files, fileNames) - cleanupSelection := GetCleanupSelection() - outContents := Ternary(cleanupSelection, CleanupMultiple(selected, selectedKeys), GetAllRaw(selected, selectedKeys)) + cleanupSelection := AskCleanup() + outContents := Ternary(cleanupSelection, CleanupMultipleFiles(selected, selectedKeys), GetAllRaw(selected, selectedKeys)) if FileExists(outFile) { HandleFileOverwrite(outFile, outContents) diff --git a/internal/core.go b/internal/ask.go similarity index 76% rename from internal/core.go rename to internal/ask.go index 3527cc1..3845861 100644 --- a/internal/core.go +++ b/internal/ask.go @@ -2,50 +2,10 @@ package internal import ( "fmt" - "log" - "os" "github.com/AlecAivazis/survey/v2" ) -func HandleFileOverwrite(path string, contents string) { - overwriteSelection := AskOverwrite() - switch overwriteSelection { - case "": - Quit() - break - case "Overwrite": - log.Printf("Writing to %s", path) - WriteFile(path, contents, true) - break - case "Append": - log.Printf("Appending to %s", path) - WriteFile(path, contents, false) - break - } -} - -func AskOverwrite() string { - overwritePrompt := &survey.Select{ - Message: ".gitignore file found in this directory. Please pick an option:", - Options: []string{"Overwrite", "Append", "Skip"}, - } - overwriteSelection := "" - survey.AskOne(overwritePrompt, &overwriteSelection) - return overwriteSelection -} - -func GetCleanupSelection() bool { - cleanupPrompt := &survey.Confirm{ - Message: "Do you want to remove patterns not existing in your project?", - Default: true, - } - - var cleanupSelection bool - survey.AskOne(cleanupPrompt, &cleanupSelection) - return cleanupSelection -} - func AskLanguage(fileNames []string, selected []string, files map[string]string) ([]string, []string) { langPrompt := &survey.MultiSelect{ Message: "Found " + fmt.Sprint(len(fileNames)) + @@ -79,6 +39,23 @@ func AskDiscovery() bool { return answer } -func Quit() { - os.Exit(1) +func AskOverwrite() string { + overwritePrompt := &survey.Select{ + Message: ".gitignore file found in this directory. Please pick an option:", + Options: []string{"Overwrite", "Append", "Skip"}, + } + overwriteSelection := "" + survey.AskOne(overwritePrompt, &overwriteSelection) + return overwriteSelection +} + +func AskCleanup() bool { + cleanupPrompt := &survey.Confirm{ + Message: "Do you want to remove patterns not existing in your project?\nThis might produce incomplete files on new projects.", + Default: false, + } + + var cleanupSelection bool + survey.AskOne(cleanupPrompt, &cleanupSelection) + return cleanupSelection } diff --git a/internal/ignore_files.go b/internal/ignore_files.go index fb9d534..b24deec 100644 --- a/internal/ignore_files.go +++ b/internal/ignore_files.go @@ -17,9 +17,7 @@ func PrepareGitignores() ([]string, error) { if !FileExists(gitignoresDir) { log.Println("Getting gitignore files...") RunCmd("git", "clone", "--depth=1", repoUrl, gitignoresDir) - } - - if GetNeedsUpdate() { + } else if GetNeedsUpdate() { log.Println("Updating gitignore files...") RunCmd("git", "-C", gitignoresDir, "pull", "origin", "master") } @@ -27,6 +25,13 @@ func PrepareGitignores() ([]string, error) { return GetGitignores(gitignoresDir) } +func RemoveCacheDir() { + cacheDir := GetCacheDir() + log.Printf("Removing cache directory: %s...\n", cacheDir) + os.RemoveAll(cacheDir) + log.Println("Done") +} + func GetCacheDir() string { homeDir, _ := os.UserHomeDir() return filepath.Join(homeDir, ".github.gitignore") @@ -75,10 +80,12 @@ func FindFileMatches(patterns string) bool { continue } idx := strings.Index(line, "#") + // ignore comments at end of line if idx > -1 && (idx == 0 || line[idx-1] != '\\') { line = strings.TrimSpace(line[0:idx]) } + if len(line) == 0 || Contains(ignoreLines, line) { continue } @@ -166,7 +173,7 @@ func GetLanguageSelections(files map[string]string, fileNames []string) ([]strin return selected, selectedKeys } -func GetRelevantFiles(allFiles []string) ([]string, map[string]string) { +func DiscoverRelevantFiles(allFiles []string) ([]string, map[string]string) { files := make(map[string]string) fileNames := []string{} @@ -199,20 +206,20 @@ func LangHeader(langName string) string { func GetAllRaw(selected []string, selectedKeys []string) string { for i, selection := range selected { - header := LangHeader(selectedKeys[i]) + header := Ternary(len(selected) > 1, LangHeader(selectedKeys[i]), "") selected[i] = header + selection } return strings.Join(selected, "\n") } -func CleanupMultiple(selected []string, keys []string) string { +func CleanupMultipleFiles(files []string, langKeys []string) string { out := []string{} - for i, selection := range selected { + for i, selection := range files { cleanSelection := RemoveUnusedPatterns(selection) if strings.TrimSpace(cleanSelection) == "" { continue } - header := LangHeader(keys[i]) + header := LangHeader(langKeys[i]) prefixNewline := Ternary(i > 0, "\n", "") contents := prefixNewline + header + cleanSelection out = append(out, contents) diff --git a/internal/utils.go b/internal/utils.go index 84d9083..f22722c 100644 --- a/internal/utils.go +++ b/internal/utils.go @@ -82,3 +82,24 @@ func Ternary[T any](cond bool, whenTrue T, whenFalse T) T { func ToString[T any](obj T) string { return fmt.Sprint(obj) } + +func HandleFileOverwrite(path string, contents string) { + overwriteSelection := AskOverwrite() + switch overwriteSelection { + case "": + Quit() + break + case "Overwrite": + log.Printf("Writing to %s", path) + WriteFile(path, contents, true) + break + case "Append": + log.Printf("Appending to %s", path) + WriteFile(path, contents, false) + break + } +} + +func Quit() { + os.Exit(1) +}