diff --git a/embed/scaffold/init/$.posh/go.mod.gotext b/embed/scaffold/init/$.posh/go.mod.gotext index d8cb393..3aa789f 100644 --- a/embed/scaffold/init/$.posh/go.mod.gotext +++ b/embed/scaffold/init/$.posh/go.mod.gotext @@ -1,6 +1,6 @@ module {{ .module }}/posh -go 1.19 +go 1.21 replace ( github.com/c-bata/go-prompt v0.2.6 => github.com/franklinkim/go-prompt v0.2.7-0.20210427061716-a8f4995d7aa5 diff --git a/embed/scaffold/init/$.posh/pkg/command/welcome.go.gotext b/embed/scaffold/init/$.posh/internal/command/welcome.go.gotext similarity index 97% rename from embed/scaffold/init/$.posh/pkg/command/welcome.go.gotext rename to embed/scaffold/init/$.posh/internal/command/welcome.go.gotext index b87a405..88c1788 100644 --- a/embed/scaffold/init/$.posh/pkg/command/welcome.go.gotext +++ b/embed/scaffold/init/$.posh/internal/command/welcome.go.gotext @@ -3,7 +3,7 @@ package command import ( "context" - "{{.module}}/posh/pkg/config" + "{{.module}}/posh/internal/config" "github.com/foomo/posh/pkg/log" "github.com/foomo/posh/pkg/readline" "github.com/spf13/viper" diff --git a/embed/scaffold/init/$.posh/pkg/config/welcome.go.gotext b/embed/scaffold/init/$.posh/internal/config/welcome.go.gotext similarity index 100% rename from embed/scaffold/init/$.posh/pkg/config/welcome.go.gotext rename to embed/scaffold/init/$.posh/internal/config/welcome.go.gotext diff --git a/embed/scaffold/init/$.posh/pkg/plugin.go.gotext b/embed/scaffold/init/$.posh/internal/plugin.go.gotext similarity index 95% rename from embed/scaffold/init/$.posh/pkg/plugin.go.gotext rename to embed/scaffold/init/$.posh/internal/plugin.go.gotext index 7dc9b4d..00e6d9e 100644 --- a/embed/scaffold/init/$.posh/pkg/plugin.go.gotext +++ b/embed/scaffold/init/$.posh/internal/plugin.go.gotext @@ -1,4 +1,4 @@ -package pkg +package internal import ( "context" @@ -15,7 +15,7 @@ import ( "github.com/foomo/posh/pkg/prompt/history" "github.com/foomo/posh/pkg/readline" "github.com/foomo/posh/pkg/require" - pkgcommand "{{.module}}/posh/pkg/command" + icommand "{{.module}}/posh/internal/command" ) type Plugin struct { @@ -39,8 +39,8 @@ func New(l log.Logger) (plugin.Plugin, error) { // Welcome inst.commands.MustAdd( - pkgcommand.NewWelcome(l, - pkgcommand.WelcomeWithConfigKey("welcome"), + icommand.NewWelcome(l, + icommand.WelcomeWithConfigKey("welcome"), ), ) diff --git a/embed/scaffold/init/$.posh/main.go.gotext b/embed/scaffold/init/$.posh/main.go.gotext index 0c6b5f8..0b32162 100644 --- a/embed/scaffold/init/$.posh/main.go.gotext +++ b/embed/scaffold/init/$.posh/main.go.gotext @@ -1,12 +1,12 @@ package main import ( - "{{.module}}/posh/pkg" + "{{.module}}/posh/internal" "github.com/foomo/posh/cmd" ) func init() { - cmd.Init(pkg.New) + cmd.Init(internal.New) } func main() { diff --git a/pkg/command/cache.go b/pkg/command/cache.go index 94d2baa..737e038 100644 --- a/pkg/command/cache.go +++ b/pkg/command/cache.go @@ -33,11 +33,11 @@ func NewCache(l log.Logger, cache cache.Cache) *Cache { } inst.tree = tree.New(&tree.Node{ Name: "cache", - Description: "manage the internal cache", + Description: "Manage the internal cache", Nodes: tree.Nodes{ { Name: "clear", - Description: "clear caches", + Description: "Clear caches", Args: tree.Args{ { Name: "Namespace", @@ -53,7 +53,7 @@ func NewCache(l log.Logger, cache cache.Cache) *Cache { }, { Name: "list", - Description: "list all caches", + Description: "List all caches", Execute: inst.list, }, }, diff --git a/pkg/command/env.go b/pkg/command/env.go new file mode 100644 index 0000000..febe7bc --- /dev/null +++ b/pkg/command/env.go @@ -0,0 +1,111 @@ +package command + +import ( + "context" + "os" + "strings" + + "github.com/foomo/posh/pkg/command/tree" + "github.com/foomo/posh/pkg/log" + "github.com/foomo/posh/pkg/prompt/goprompt" + "github.com/foomo/posh/pkg/readline" + "github.com/pterm/pterm" +) + +type Env struct { + l log.Logger + tree tree.Root +} + +// ------------------------------------------------------------------------------------------------ +// ~ Constructor +// ------------------------------------------------------------------------------------------------ + +func NewEnv(l log.Logger) *Env { + inst := &Env{ + l: l, + } + inst.tree = tree.New(&tree.Node{ + Name: "env", + Description: "Manage internal environment variables", + Nodes: tree.Nodes{ + { + Name: "list", + Description: "List all environment variables", + Execute: inst.list, + }, + { + Name: "set", + Description: "Set an internal environment variable", + Args: tree.Args{ + { + Name: "Key", + Description: "Key of the environment variable.", + }, + { + Name: "Value", + Optional: true, + Description: "Value of the environment variable.", + }, + }, + Execute: inst.set, + }, + { + Name: "unset", + Description: "Unset an environment variable", + Args: tree.Args{ + { + Name: "Key", + Description: "Key of the environment variable.", + }, + }, + Execute: inst.unset, + }, + }, + }) + return inst +} + +// ------------------------------------------------------------------------------------------------ +// ~ Public methods +// ------------------------------------------------------------------------------------------------ + +func (c *Env) Name() string { + return c.tree.Node().Name +} + +func (c *Env) Description() string { + return c.tree.Node().Description +} + +func (c *Env) Complete(ctx context.Context, r *readline.Readline) []goprompt.Suggest { + return c.tree.Complete(ctx, r) +} + +func (c *Env) Execute(ctx context.Context, r *readline.Readline) error { + return c.tree.Execute(ctx, r) +} + +func (c *Env) Help(ctx context.Context, r *readline.Readline) string { + return c.tree.Help(ctx, r) +} + +// ------------------------------------------------------------------------------------------------ +// ~ Private methods +// ------------------------------------------------------------------------------------------------ + +func (c *Env) set(ctx context.Context, r *readline.Readline) error { + return os.Setenv(r.Args().At(0), r.Args().AtDefault(1, "")) +} + +func (c *Env) unset(ctx context.Context, r *readline.Readline) error { + return os.Unsetenv(r.Args().At(0)) +} + +func (c *Env) list(ctx context.Context, r *readline.Readline) error { + data := pterm.TableData{{"Name", "Value"}} + for _, s := range os.Environ() { + data = append(data, strings.SplitN(s, "=", 2)) + } + return pterm.DefaultTable.WithHasHeader(true).WithData(data).Render() +} diff --git a/pkg/command/tree/node.go b/pkg/command/tree/node.go index b9e38e9..e6e2b5b 100644 --- a/pkg/command/tree/node.go +++ b/pkg/command/tree/node.go @@ -134,19 +134,20 @@ func (c *Node) find(ctx context.Context, r *readline.Readline, i int) (*Node, in } func (c *Node) help(ctx context.Context, r *readline.Readline) string { + pad := " " ret := c.Description if len(c.Nodes) > 0 { ret += "\n\nUsage:\n" - ret += " " + c.Name + " [command]" + ret += pad + c.Name + " [command]" ret += "\n\nAvailable Commands:\n" for _, node := range c.Nodes { - ret += " " + xstrings.PadEnd(node.Name, " ", 30) + node.Description + "\n" + ret += pad + xstrings.PadEnd(node.Name, " ", 30) + node.Description + "\n" } } else { ret += "\n\nUsage:\n" - ret += " " + c.Name + ret += pad + c.Name for _, arg := range c.Args { ret += " " @@ -167,7 +168,7 @@ func (c *Node) help(ctx context.Context, r *readline.Readline) string { if len(c.Args) > 0 { ret += "\n\nArguments:\n" for _, arg := range c.Args { - ret += " " + xstrings.PadEnd(arg.Name, " ", 30) + arg.Description + "\n" + ret += pad + xstrings.PadEnd(arg.Name, " ", 30) + arg.Description + "\n" } } diff --git a/pkg/command/tree/root_test.go b/pkg/command/tree/root_test.go index f65d6f3..39c21a7 100644 --- a/pkg/command/tree/root_test.go +++ b/pkg/command/tree/root_test.go @@ -31,7 +31,7 @@ func TestRoot(t *testing.T) { r := tree.New(&tree.Node{ Name: "root", - Description: "root tree", + Description: "Root tree", Execute: func(ctx context.Context, r *readline.Readline) error { return ErrRoot }, diff --git a/pkg/prompt/flair/flair.go b/pkg/prompt/flair/flair.go index 886acf3..06f5b9e 100644 --- a/pkg/prompt/flair/flair.go +++ b/pkg/prompt/flair/flair.go @@ -11,7 +11,7 @@ func DefaultFlair(title string) error { pterm.FgGray.Println() if err := pterm.DefaultBigText.WithLetters( putils.LettersFromStringWithStyle(strings.ToUpper(title), pterm.NewStyle(pterm.FgCyan)), - putils.LettersFromStringWithStyle("$H", pterm.NewStyle(pterm.FgGreen))). + ). Render(); err != nil { return err } diff --git a/pkg/prompt/prompt.go b/pkg/prompt/prompt.go index e68d698..b5d532d 100644 --- a/pkg/prompt/prompt.go +++ b/pkg/prompt/prompt.go @@ -289,7 +289,7 @@ func (s *Prompt) complete(d prompt.Document) []prompt.Suggest { if s.readline.IsModeDefault() && s.readline.Args().LenIs(0) { var suggests []prompt.Suggest for key, value := range s.aliases { - suggests = append(suggests, prompt.Suggest{Text: key, Description: "alias: " + value}) + suggests = append(suggests, prompt.Suggest{Text: key, Description: "Alias: " + value}) } for _, inst := range s.Commands().List() { suggests = append(suggests, prompt.Suggest{Text: inst.Name(), Description: inst.Description()}) diff --git a/pkg/readline/args.go b/pkg/readline/args.go index 021de72..ec61c3c 100644 --- a/pkg/readline/args.go +++ b/pkg/readline/args.go @@ -14,6 +14,14 @@ func (a Args) At(v int) string { } } +func (a Args) AtDefault(v int, fallback string) string { + if a.HasIndex(v) { + return a[v] + } else { + return fallback + } +} + func (a Args) Shift() (string, Args) { if a.HasIndex(0) { return a[0], a[1:]