diff --git a/README.md b/README.md index a95aea4..80796e4 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ Available Commands: list List all .gitignore files in the root template repository Flags: + -c, --config string config file (default is $HOME/.config/gignore/config.yaml) -h, --help help for gignore -l, --loglevel string Log level (trace, debug, info, warn, error, fatal, panic) (default "warn") -r, --root string Root directory to search for .gitignore files (default "gitignoreio") @@ -51,19 +52,19 @@ gignore create go It's possible to add your own custom templates, simply create a directory in `internal/registry/templates`. You'll need to [reinstall](https://github.com/onyx-and-iris/gignore?tab=readme-ov-file#install) the project before you can load the new templates. -Then pass the dir name as a flag, for example: +Then pass the new template root with the `--root` flag, for example: ```bash -gignore -root=custom create go +gignore --root=custom create go ``` -You may set an environment variable `GIGNORE_TEMPLATE_ROOT` to avoid passing the `-root` flag each time. +You may set an environment variable `GIGNORE_ROOT` to avoid passing the `--root` flag each time. If a template is requested but not found in the custom directory then the gitignoreio registry will act as a fallback. ## Logging -The `-loglevel` flag allows you to control the verbosity of the application's logging output. +The `--loglevel` flag allows you to control the verbosity of the application's logging output. Acceptable values for this flag are: @@ -78,7 +79,7 @@ Acceptable values for this flag are: For example, to set the log level to `debug`, you can use: ```bash -gignore -loglevel=debug create python +gignore --loglevel=debug create python ``` The default log level is `warn` if the flag is not specified. diff --git a/cmd/gignore/main.go b/cmd/gignore/main.go index 9be2b17..3763e0e 100644 --- a/cmd/gignore/main.go +++ b/cmd/gignore/main.go @@ -5,10 +5,13 @@ package main import ( "context" "os" + "path/filepath" + "strings" + "github.com/charmbracelet/log" "github.com/onyx-and-iris/gignore" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" + "github.com/spf13/viper" ) // rootCmd is the root command for the gignore CLI tool. @@ -18,18 +21,18 @@ var rootCmd = &cobra.Command{ Long: `gignore is a command line tool that helps you manage your .gitignore files. You can use it to list available templates and create new .gitignore files. It supports various programming languages. - Example: - gignore list - gignore create python`, +Example: + gignore list + gignore create python`, PersistentPreRun: func(cmd *cobra.Command, _ []string) { // Initialise the logger - loglevel, err := log.ParseLevel(cmd.Flag("loglevel").Value.String()) + level, err := log.ParseLevel(viper.GetString("loglevel")) cobra.CheckErr(err) - log.SetLevel(loglevel) + log.SetLevel(level) // Initialise the gignore client client := gignore.New( - gignore.WithTemplateDirectory(cmd.Flag("root").Value.String()), + gignore.WithTemplateDirectory(viper.GetString("root")), ) // Set the client in the context @@ -42,20 +45,52 @@ It supports various programming languages. }, } +var cfgFile string + // init initialises the root command and adds global flags. func init() { - getEnv := func(key, defaultValue string) string { - value := os.Getenv(key) - if value == "" { - return defaultValue - } - return value - } + cobra.OnInitialize(initConfig) rootCmd.PersistentFlags(). - StringP("root", "r", getEnv("GIGNORE_TEMPLATE_ROOT", gignore.DefaultTemplateDirectory), "Root directory to search for .gitignore files") + StringVarP(&cfgFile, "config", "c", "", "config file (default is $HOME/.config/gignore/config.yaml)") rootCmd.PersistentFlags(). - StringP("loglevel", "l", getEnv("GIGNORE_LOGLEVEL", "warn"), "Log level (trace, debug, info, warn, error, fatal, panic)") + StringP("root", "r", gignore.DefaultTemplateDirectory, "Root directory to search for .gitignore files") + rootCmd.PersistentFlags(). + StringP("loglevel", "l", "warn", "Log level (trace, debug, info, warn, error, fatal, panic)") + + replacer := strings.NewReplacer("-", "_") + viper.SetEnvKeyReplacer(replacer) + viper.SetEnvPrefix("GIGNORE") + viper.BindPFlag("root", rootCmd.PersistentFlags().Lookup("root")) + viper.BindPFlag("loglevel", rootCmd.PersistentFlags().Lookup("loglevel")) +} + +// initConfig reads in config file and ENV variables if set. +// It first checks if a config file is provided via the --config flag. +// If not, it looks for a config file in the user's config directory. +// The config file is expected to be in YAML format and named "config.yaml". +func initConfig() { + if cfgFile != "" { + viper.SetConfigFile(cfgFile) + } else { + configDir, err := os.UserConfigDir() + cobra.CheckErr(err) + + viper.AddConfigPath(filepath.Join(configDir, "gignore")) + viper.SetConfigName("config") + viper.SetConfigType("yaml") + } + + if err := viper.ReadInConfig(); err != nil { + // If the config file is not found, we ignore the error + // as it is not mandatory to have a config file. + // However, if there is any other error, we log it and exit. + // This includes errors like invalid syntax in the config file. + if _, ok := err.(viper.ConfigFileNotFoundError); !ok { + log.Fatal("Error reading config file: ", err) + } + } + viper.AutomaticEnv() } func main() {