posh/cmd/root.go
Kevin Franklin Kim e2ad376b6c initial commit
2023-01-03 15:37:15 +01:00

135 lines
3.3 KiB
Go

package cmd
import (
"context"
"fmt"
"os"
"os/signal"
"strings"
"github.com/foomo/posh/pkg/log"
"github.com/foomo/posh/pkg/plugin"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
const (
EnvProjectRoot = "PROJECT_ROOT"
)
var (
l log.Logger
m *plugin.Manager
flagLevel string
flagConfig string
flagNoColor bool
)
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "posh",
Short: "Start the Project Oriented Shell",
Long: `Start the Project Oriented Shell in interactive mode.`,
Run: func(cmd *cobra.Command, args []string) {
// use the hypothetical UnknownArgs() pflag API
fmt.Println(args)
return
},
}
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
osInterrupt := make(chan os.Signal, 1)
signal.Notify(osInterrupt, os.Interrupt)
ctx, cancel := context.WithCancel(context.Background())
defer func() {
signal.Stop(osInterrupt)
cancel()
}()
go func() {
<-osInterrupt
l.Debug("received interrupt")
cancel()
}()
if err := rootCmd.ExecuteContext(ctx); errors.Is(err, context.Canceled) {
l.Warn(err.Error())
os.Exit(0)
} else if err != nil {
l.Error(err.Error())
os.Exit(1)
}
}
func init() {
cobra.OnInitialize(initialize)
// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.
rootCmd.PersistentFlags().BoolVar(&flagNoColor, "no-color", false, "disabled colors (default is false)")
rootCmd.PersistentFlags().StringVar(&flagLevel, "level", "info", "set log level (default is warn)")
rootCmd.PersistentFlags().StringVar(&flagConfig, "config", "", "config file (default is $HOME/.posh.yaml)")
// Cobra also supports local flags, which will only run
// when this action is called directly.
rootCmd.Flags().Bool("no-validate", false, "Skip validation")
}
// initialize reads in config file and ENV variables if set.
func initialize() {
// setup logger
if value, err := log.NewPTerm(
log.PTermWithDisableColor(flagNoColor),
log.PTermWithLevel(log.GetLevel(flagLevel)),
); err != nil {
cobra.CheckErr(err)
} else {
l = value
}
// setup viper
if flagConfig != "" {
// Use config file from the flag.
viper.SetConfigFile(flagConfig)
} else {
wd, err := os.Getwd()
l.Must(err)
viper.AddConfigPath(wd)
viper.SetConfigType("yaml")
viper.SetConfigName(".posh")
}
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv()
l.Must(viper.ReadInConfig())
l.Debug("using config file:", viper.ConfigFileUsed())
// validate version
if v := viper.GetString("version"); v != "v1.0" {
l.Must(fmt.Errorf("invalid config version: %s (v1.0)", v))
}
// setup env
if value := os.Getenv(EnvProjectRoot); value != "" {
// continue
} else if value, err := os.Getwd(); err != nil {
l.Must(errors.Wrap(err, "failed to retrieve project root"))
} else if err := os.Setenv(EnvProjectRoot, value); err != nil {
l.Must(errors.Wrap(err, "failed to set project root env"))
}
for key, value := range viper.GetStringMapString("env") {
l.Must(os.Setenv(key, os.ExpandEnv(value)))
}
// setup manager
var err error
m, err = plugin.NewManager(l)
l.Must(err)
}