package cmd import ( "bytes" "fmt" "os" "github.com/pterm/pterm" "github.com/spf13/cobra" "github.com/spf13/viper" "gopkg.in/yaml.v3" "gitea.libretechconsulting.com/rmcguire/git-project-manager/internal/config" "gitea.libretechconsulting.com/rmcguire/git-project-manager/internal/remotes/info" ) var configGenerateCmd = &cobra.Command{ Use: "generate", Short: "Generate a default configuration", Aliases: []string{"gen", "new", "default"}, Long: configGenCmdLong, Run: runConfigGenerateCmd, } func runConfigGenerateCmd(cmd *cobra.Command, args []string) { var configFile string if viper.ConfigFileUsed() != "" { configFile = viper.ConfigFileUsed() } else { configFile = defConfigPath } plog.Debug("Using config file " + configFile) configFile, _ = resolvePath(configFile) newConf := promptConfigSettings(&conf) if write, _ := cmd.Flags().GetBool(FlagWrite); write { write, _ := pterm.DefaultInteractiveContinue. WithDefaultText("Really write config file?"). WithOptions([]string{"yes", "no"}). Show() if write != "yes" { plog.Fatal("Aborting config file write") } writeConfigFile(newConf, configFile) plog.Info("Wrote config to file", plog.Args("file", configFile)) } else { var c bytes.Buffer enc := yaml.NewEncoder(&c) enc.SetIndent(2) enc.Encode(newConf) plog.Info("Suggest running with --write or redirect (> " + configFile + ")") fmt.Print(c.String()) } } func writeConfigFile(c *config.Config, path string) { file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o640) if err != nil { plog.Error("Failed to prepare config for writing", plog.Args("error", err)) } enc := yaml.NewEncoder(file) if err := enc.Encode(c); err != nil { plog.Fatal("Failed writing config file", plog.Args("file", path)) } } func promptConfigSettings(c *config.Config) *config.Config { var gitRemote *info.RemoteInfo // Just pick the first if we have one, considering this // is meant to be a first-time use tool if len(c.Remotes) > 0 { gitRemote = &c.Remotes[0] } else { gitRemote = &config.DefaultConfig.Remotes[0] c.Remotes = append(c.Remotes, *gitRemote) } if host, err := pterm.DefaultInteractiveTextInput. WithDefaultValue(gitRemote.Host). WithDefaultText("Enter remote URL"). Show(); err == nil { gitRemote.Host = host } if name, err := pterm.DefaultInteractiveTextInput. WithDefaultValue(gitRemote.Name). WithDefaultText("Enter remote name (e.g. My Private remote)"). Show(); err == nil { gitRemote.Name = name } if token, err := pterm.DefaultInteractiveTextInput. WithMask("*"). WithDefaultValue(gitRemote.Token). WithDefaultText("Enter remote Token"). Show(); err == nil { gitRemote.Token = token } if remoteType, err := pterm.DefaultInteractiveSelect. WithOptions(info.RemoteTypesAll.Strings()). WithDefaultText("Git Clone Protocol"). Show(); err == nil { gitRemote.Type = info.GetRemoteTypeFromString(remoteType) } if proto, err := pterm.DefaultInteractiveSelect. WithOptions([]string{string(info.CloneProtoHTTP), string(info.CloneProtoSSH)}). WithDefaultText("Git Clone Protocol"). Show(); err == nil { if proto == "ssh" { gitRemote.CloneProto = info.CloneProtoSSH } else { gitRemote.CloneProto = info.CloneProtoHTTP } } if pPath, err := pterm.DefaultInteractiveTextInput. WithDefaultValue(c.ProjectPath). WithDefaultText("Enter path for projects and cache"). Show(); err == nil { c.ProjectPath = pPath } if ownerOnly, err := pterm.DefaultInteractiveConfirm. WithDefaultText("Only cache projects you are owner of?"). Show(); err == nil { if ownerOnly { c.Cache.Load.OwnerOnly = true } else { c.Cache.Load.OwnerOnly = false } } if dirMode, err := pterm.DefaultInteractiveConfirm. WithDefaultValue(true). WithDefaultText("Open project directories instead of main files (yes for vscode)?"). Show(); err == nil { c.Editor.OpenDirectory = dirMode } return c } func init() { configCmd.AddCommand(configGenerateCmd) configGenerateCmd.PersistentFlags().Bool(FlagPrompt, false, "Prompt for settings") configGenerateCmd.PersistentFlags().Bool(FlagWrite, false, "Write config to file") }