From 6f3c68f6b08acc16d059bc1d32de2306192a052e Mon Sep 17 00:00:00 2001 From: Hedzr Yeh Date: Fri, 13 Sep 2024 09:03:52 +0800 Subject: [PATCH] removing AddCmd/AddFlg since them took obsess behavior to Cmd/Flg --- builder/builder_test.go | 95 ++- builder/commandbuilders.go | 153 +++-- builder/flagbuilder.go | 9 +- cli/commandbuilder.go | 48 +- cli/examples/cmn.go | 243 +++---- cli/examples/more.go | 1278 +++++++++++++++++------------------- cli/worker/builtins.go | 234 ++++--- cli/worker/i_test.go | 154 ++--- cli/worker/worker_test.go | 57 ++ 9 files changed, 1167 insertions(+), 1104 deletions(-) create mode 100644 cli/worker/worker_test.go diff --git a/builder/builder_test.go b/builder/builder_test.go index 77a2009..372a8c2 100644 --- a/builder/builder_test.go +++ b/builder/builder_test.go @@ -23,13 +23,81 @@ func TestFfb_NewFlagBuilder(t *testing.T) { testNewFlagBuilder(t) } +func TestCcb_NewCommandBuilderPanics(t *testing.T) { + deferTest := func(t *testing.T, cb func(bb *ccb)) { + defer func() { + if r := recover(); r == nil { + t.Logf("test for %q is ok.", t.Name()) + return + } + t.Fatalf("test for %q is bad: expecting a panic but it isn't threw", t.Name()) + }() + + b := buildable(nil) + bb := newCommandBuilderShort(b, "help", "h", "info") + cb(bb) + } + + t.Run("inCmd == true and Cmd panics", func(t *testing.T) { + deferTest(t, func(bb *ccb) { + bb.AddCmd(func(b cli.CommandBuilder) { + b.OnMatched(nil) + + cb := b.Cmd("dash", "d") + + cb.UseShell("/bin/dash") + }) + }) + }) + + t.Run("inCmd == true and AddCmd panics", func(t *testing.T) { + deferTest(t, func(bb *ccb) { + bb.AddCmd(func(b cli.CommandBuilder) { + b.OnMatched(nil) + + b.AddCmd(func(b cli.CommandBuilder) { + b.OnMatched(nil) + b.UseShell("/bin/dash") + }) + }) + }) + }) + + t.Run("Cmd panics", func(t *testing.T) { + deferTest(t, func(bb *ccb) { + cb := bb.Cmd("dash", "d") + cb.UseShell("/bin/dash") + }) + }) + t.Run("Flg panics", func(t *testing.T) { + deferTest(t, func(bb *ccb) { + fb := bb.Flg("cool", "c") + fb.OnMatched(nil) + }) + }) + t.Run("AddCmd panics", func(t *testing.T) { + deferTest(t, func(bb *ccb) { + bb.AddCmd(func(b cli.CommandBuilder) { + b.OnMatched(nil) + }) + }) + }) + t.Run("AddFlg panics", func(t *testing.T) { + deferTest(t, func(bb *ccb) { + bb.AddFlg(func(b cli.FlagBuilder) { + b.OnMatched(nil) + }) + }) + }) +} + func TestCcb_NewCommandBuilder(t *testing.T) { testNewCommandBuilder(t) } func testNewCommandBuilder(t *testing.T) { b := buildable(nil) - bb := newCommandBuilderShort(b, "help", "h", "info") + bb := newCommandBuilderShort(b, "help", "h", "info", "tip", "whatsthis") bb.Titles("verbose", "v", "verbose-mode", "non-quiet-mode") bb.ExtraShorts("V") @@ -49,14 +117,6 @@ func testNewCommandBuilder(t *testing.T) { bb.InvokeShell("") bb.UseShell("/bin/bash") - cb := bb.NewCommandBuilder("command", "c", "cc", "cmd") - cb.UseShell("/bin/zsh") - - fb := bb.NewFlagBuilder("flag", "f", "ff", "flg") - fb.OnMatched(nil) - - bb.Build() - bb.AddCmd(func(b cli.CommandBuilder) { b.OnMatched(nil) }) @@ -64,16 +124,27 @@ func testNewCommandBuilder(t *testing.T) { b.OnMatched(nil) }) - cb = bb.Cmd("dash", "d") + bb.Build() + + cb := bb.Cmd("dash", "d") cb.UseShell("/bin/dash") + cb.Build() - fb = bb.Flg("cool", "c") + fb := bb.Flg("cool", "c") fb.OnMatched(nil) + fb.Build() + + // cb := bb.NewCommandBuilder("command", "c", "cc", "cmd") + // cb.UseShell("/bin/zsh") + // + // fb := bb.NewFlagBuilder("flag", "f", "ff", "flg") + // fb.OnMatched(nil) + } func testNewFlagBuilder(t *testing.T) { b := buildable(nil) - bb := newFlagBuilderShort(b, "verbose", "v", "verbose-mode") + bb := newFlagBuilderShort(b, "verbose", "v", "verbose-mode", "test-mode", "debug-mode") app := buildable(nil) bb.SetApp(app) diff --git a/builder/commandbuilders.go b/builder/commandbuilders.go index 20488c5..c0decbb 100644 --- a/builder/commandbuilders.go +++ b/builder/commandbuilders.go @@ -3,6 +3,8 @@ package builder import ( + "sync/atomic" + "github.com/hedzr/cmdr/v2/cli" ) @@ -29,7 +31,7 @@ func newCommandBuilderFrom(from *cli.Command, b buildable, longTitle string, tit s := &ccb{ b, from, new(cli.Command), - false, false, + 0, 0, } s.Long, s.Short, s.Aliases = theTitles(longTitle, titles...) return s @@ -39,21 +41,94 @@ type ccb struct { buildable parent *cli.Command *cli.Command - inCmd bool - inFlg bool + inCmd int32 + inFlg int32 } func (s *ccb) Build() { if a, ok := s.buildable.(adder); ok { a.addCommand(s.Command) } - if s.parent != nil { - s.parent.AddSubCommand(s.Command) + // if s.parent != nil { + // s.parent.AddSubCommand(s.Command) + // // if a, ok := s.b.(adder); ok { + // // a.addCommand(s.Command) + // // } + // } + + atomic.StoreInt32(&s.inCmd, 0) + atomic.StoreInt32(&s.inFlg, 0) +} + +// addCommand adds a in-building Cmd into current Command as a child-/sub-command. +// used by adder when ccb.Build. +func (s *ccb) addCommand(child *cli.Command) { + atomic.AddInt32(&s.inCmd, -1) // reset increased inCmd at AddCmd or Cmd + s.AddSubCommand(child) +} + +// addFlag adds a in-building Flg into current Command as its flag. +// used by adder when ccb.Build. +func (s *ccb) addFlag(child *cli.Flag) { + atomic.AddInt32(&s.inFlg, -1) + s.AddFlag(child) +} + +func (s *ccb) NewCommandBuilder(longTitle string, titles ...string) cli.CommandBuilder { + return s.Cmd(longTitle, titles...) +} + +func (s *ccb) NewFlagBuilder(longTitle string, titles ...string) cli.FlagBuilder { + return s.Flg(longTitle, titles...) +} + +func (s *ccb) Cmd(longTitle string, titles ...string) cli.CommandBuilder { + if atomic.LoadInt32(&s.inCmd) != 0 { + panic("cannot call Cmd() without Build() last Cmd()/AddCmd()") } + atomic.AddInt32(&s.inCmd, 1) + return newCommandBuilderShort(s, longTitle, titles...) +} + +func (s *ccb) Flg(longTitle string, titles ...string) cli.FlagBuilder { + if atomic.LoadInt32(&s.inFlg) != 0 { + panic("cannot call Flg() without Build() last Flg()") + } + atomic.AddInt32(&s.inFlg, 1) + return newFlagBuilderShort(s, longTitle, titles...) +} + +func (s *ccb) AddCmd(cb func(b cli.CommandBuilder)) cli.CommandBuilder { + // if atomic.LoadInt32(&s.inCmd) != 0 { + // panic("cannot call AddCmd() without Build() last Cmd()/AddCmd()") + // } + + bc := newCommandBuilderShort(s, "new-command") + defer bc.Build() // `Build' will add `bc'(Command) to s.Command as its SubCommand + cb(bc) + atomic.AddInt32(&s.inCmd, 1) + return s +} + +func (s *ccb) AddFlg(cb func(b cli.FlagBuilder)) cli.CommandBuilder { + // if atomic.LoadInt32(&s.inFlg) != 0 { + // panic("cannot call AddFlg() without Build() last Flg()/AddFlg()") + // } - s.inCmd, s.inFlg = false, false + bc := newFlagBuilderShort(s, "new-flag") + defer bc.Build() // `Build' will add `bc'(Flag) to s.Command as its Flag + // atomic.AddInt32(&s.inFlg, 1) + // defer func() { atomic.AddInt32(&s.inFlg, -1) }() + cb(bc) + return s } +// + +// + +// + func (s *ccb) Titles(longTitle string, titles ...string) cli.CommandBuilder { s.Long, s.Short, s.Aliases = theTitles(longTitle, titles...) return s @@ -139,72 +214,6 @@ func (s *ccb) UseShell(shellPath string) cli.CommandBuilder { return s } -// -// -// - -func (s *ccb) NewCommandBuilder(longTitle string, titles ...string) cli.CommandBuilder { - return s.Cmd(longTitle, titles...) -} - -func (s *ccb) NewFlagBuilder(longTitle string, titles ...string) cli.FlagBuilder { - return s.Flg(longTitle, titles...) -} - -func (s *ccb) Cmd(longTitle string, titles ...string) cli.CommandBuilder { - if s.inCmd { - panic("cannot call Cmd() without Build() last Cmd()/AddCmd()") - } - s.inCmd = true - return newCommandBuilderShort(s, longTitle, titles...) -} - -func (s *ccb) Flg(longTitle string, titles ...string) cli.FlagBuilder { - if s.inFlg { - panic("cannot call Flg() without Build() last Flg()") - } - s.inFlg = true - return newFlagBuilderShort(s, longTitle, titles...) -} - -func (s *ccb) AddCmd(cb func(b cli.CommandBuilder)) cli.CommandBuilder { - if s.inCmd { - panic("cannot call AddCmd() without Build() last Cmd()/AddCmd()") - } - s.inCmd = true - defer func() { s.inCmd = false }() - - b := newCommandBuilderShort(s, "") - defer b.Build() - cb(b) - return s -} - -func (s *ccb) AddFlg(cb func(b cli.FlagBuilder)) cli.CommandBuilder { - if s.inFlg { - panic("cannot call Flg() without Build() last Flg()/AddFlg()") - } - s.inFlg = true - defer func() { s.inFlg = false }() - - b := newFlagBuilderShort(s, "") - defer b.Build() - cb(b) - return s -} - -// addCommand adds a in-building Cmd into current Command as a child-/sub-command. -func (s *ccb) addCommand(child *cli.Command) { - s.inCmd = false - s.AddSubCommand(child) -} - -// addFlag adds a in-building Flg into current Command as a child flag. -func (s *ccb) addFlag(child *cli.Flag) { - s.inFlg = false - s.AddFlag(child) -} - func theTitles(longTitle string, titles ...string) (lt, st string, aliases []string) { lt = longTitle switch len(titles) { diff --git a/builder/flagbuilder.go b/builder/flagbuilder.go index 89bf2cb..20e1d45 100644 --- a/builder/flagbuilder.go +++ b/builder/flagbuilder.go @@ -40,9 +40,12 @@ func (s *ffb) Build() { if a, ok := s.buildable.(adder); ok { a.addFlag(s.Flag) } - if s.parent != nil { - s.parent.AddFlag(s.Flag) - } + // if s.parent != nil { + // s.parent.AddFlag(s.Flag) + // // if a, ok := s.b.(adder); ok { + // // a.addFlag(s.Flag) + // // } + // } } func (s *ffb) SetApp(app buildable) { s.buildable = app } diff --git a/cli/commandbuilder.go b/cli/commandbuilder.go index 8071715..f4016da 100644 --- a/cli/commandbuilder.go +++ b/cli/commandbuilder.go @@ -131,22 +131,64 @@ type CommandBuilder interface { // // It can only be called after current command builder built // (Build() called). + // + // The right usage of Cmd is: + // + // b := newCommandBuilderShort(parent, "help", "h", "helpme", "info") + // nb := b.Cmd("command", "c", "cmd", "commands") + // nb.ExtraShorts("cc") + // nb.Build() + // // ... + // b.Build() + // + // You may prefer to use AddCmd and Closure: + // + // b := newCommandBuilderShort(parent, "help", "h", "helpme", "info") + // b.AddCmd(func(b CommandBuilder){ + // b.Titles("command", "c", "cmd", "commands") + // b.ExtraShorts("cc") + // }) + // // ... + // b.Build() + // Cmd(longTitle string, titles ...string) CommandBuilder // Flg is a shortcut to NewFlagBuilder and starts a stream // building for a new flag. // // It can only be called after current command builder built // (Build() called). + // + // The right usage of Flg is: + // + // b := newCommandBuilderShort(parent, "help", "h", "helpme", "info") + // nb := b.Flg("use-less", "l", "less", "more") + // nb.ExtraShorts("m") + // nb.Build() + // // ... + // b.Build() + // + // You may prefer to use AddFlg and Closure: + // + // b := newCommandBuilderShort(parent, "help", "h", "helpme", "info") + // b.AddFlg(func(b FlagBuilder){ + // b.Titles("use-less", "l", "less", "more") + // b.ExtraShorts("m") + // }) + // // ... + // b.Build() + // Flg(longTitle string, titles ...string) FlagBuilder // AddCmd starts a closure to build a new sub-command and its children. - // After the closure invoked, Build() will be called implicitly. + // After the closure invoked, new command's Build() will be called + // implicitly. // // It can only be called after current command builder built // (Build() called). AddCmd(func(b CommandBuilder)) CommandBuilder - // AddFlg starts a closure to build a flag - // After the closure invoked, Build() will be called implicitly. + // AddFlg starts a closure to build a new flag. + // After the closure invoked, new flag's Build() will be + // called implicitly. // // It can only be called after current command builder built // (Build() called). diff --git a/cli/examples/cmn.go b/cli/examples/cmn.go index c14800a..a5981d1 100644 --- a/cli/examples/cmn.go +++ b/cli/examples/cmn.go @@ -7,143 +7,118 @@ import ( ) func AttachModifyFlags(bdr cli.CommandBuilder) { - bdr.AddFlg(func(b cli.FlagBuilder) { - b.Default("="). - Titles("delim", "d", "delimiter"). - Description("delimiter char in `non-plain` mode."). - PlaceHolder(""). - CompJustOnce(true). - Build() - }) - - bdr.AddFlg(func(b cli.FlagBuilder) { - b.Default(false). - Titles("clear", "c", "clr"). - Description("clear all tags."). - PlaceHolder(""). - Group("Operate"). - Hidden(false, false). - Build() - }) - - bdr.AddFlg(func(b cli.FlagBuilder) { - b.Default(false). - Titles("string", "g", "string-mode"). - Description("In 'String Mode', default will be disabled: default, a tag string will be split by comma(,), and treated as a string list."). - PlaceHolder(""). - ToggleGroup("Mode"). - Build() - }) - - bdr.AddFlg(func(b cli.FlagBuilder) { - b.Default(false). - Titles("meta", "m", "meta-mode"). - Description("In 'Meta Mode', service 'NodeMeta' field will be updated instead of 'Tags'. (--plain assumed false)."). - PlaceHolder(""). - ToggleGroup("Mode"). - Build() - }) - - bdr.AddFlg(func(b cli.FlagBuilder) { - b.Default(false). - Titles("both", "2", "both-mode"). - Description("In 'Both Mode', both of 'NodeMeta' and 'Tags' field will be updated."). - PlaceHolder(""). - ToggleGroup("Mode"). - Build() - }) - - bdr.AddFlg(func(b cli.FlagBuilder) { - b.Default(false). - Titles("plain", "p", "plain-mode"). - Description("In 'Plain Mode', a tag be NOT treated as `key=value` or `key:value`, and modify with the `key`."). - ToggleGroup("Mode"). - Build() - }) - - bdr.AddFlg(func(b cli.FlagBuilder) { - b.Default(false). - Titles("tag", "t", "tag-mode"). - Description("In 'Tag Mode', a tag be treated as `key=value` or `key:value`, and modify with the `key`."). - ToggleGroup("Mode"). - Build() - }) + bdr.Flg("delim", "d", "delimiter"). + Default("="). + Description("delimiter char in `non-plain` mode."). + PlaceHolder(""). + CompJustOnce(true). + Build() + + bdr.Flg("clear", "c", "clr"). + Default(false). + Description("clear all tags."). + PlaceHolder(""). + Group("Operate"). + Hidden(false, false). + Build() + + bdr.Flg("string", "g", "string-mode"). + Default(false). + Description("In 'String Mode', default will be disabled: default, a tag string will be split by comma(,), and treated as a string list."). + PlaceHolder(""). + ToggleGroup("Mode"). + Build() + + bdr.Flg("meta", "m", "meta-mode"). + Default(false). + Description("In 'Meta Mode', service 'NodeMeta' field will be updated instead of 'Tags'. (--plain assumed false)."). + PlaceHolder(""). + ToggleGroup("Mode"). + Build() + + bdr.Flg("both", "2", "both-mode"). + Default(false). + Description("In 'Both Mode', both of 'NodeMeta' and 'Tags' field will be updated."). + PlaceHolder(""). + ToggleGroup("Mode"). + Build() + + bdr.Flg("plain", "p", "plain-mode"). + Default(false). + Description("In 'Plain Mode', a tag be NOT treated as `key=value` or `key:value`, and modify with the `key`."). + ToggleGroup("Mode"). + Build() + + bdr.Flg("tag", "t", "tag-mode"). + Default(false). + Description("In 'Tag Mode', a tag be treated as `key=value` or `key:value`, and modify with the `key`."). + ToggleGroup("Mode"). + Build() } func AttachConsulConnectFlags(bdr cli.CommandBuilder) { - bdr.AddFlg(func(b cli.FlagBuilder) { - b.Default("localhost"). - Titles("addr", "a"). - Description("Consul ip/host and port: HOST[:PORT] (No leading 'http(s)://')", ``). - PlaceHolder("HOST[:PORT]"). - Group("Consul") - }) - - bdr.AddFlg(func(b cli.FlagBuilder) { - b.Default(8500). - Titles("port", "p"). - Description("Consul port", ``). - PlaceHolder("PORT"). - Group("Consul") - }) - bdr.AddFlg(func(b cli.FlagBuilder) { - b.Default(false). - Titles("insecure", "K"). - Description("Skip TLS host verification", ``). - PlaceHolder(""). - Group("Consul") - }) - bdr.AddFlg(func(b cli.FlagBuilder) { - b.Default("/"). - Titles("prefix", "px"). - Description("Root key prefix", ``). - PlaceHolder("ROOT"). - Group("Consul") - }) - bdr.AddFlg(func(b cli.FlagBuilder) { - b.Default(""). - Titles("cacert", ""). - Description("Consul Client CA cert)", ``). - PlaceHolder("FILE"). - Group("Consul") - }) - bdr.AddFlg(func(b cli.FlagBuilder) { - b.Default(""). - Titles("cert", ""). - Description("Consul Client cert", ``). - PlaceHolder("FILE"). - Group("Consul") - }) - bdr.AddFlg(func(b cli.FlagBuilder) { - b.Default("http"). - Titles("scheme", ""). - Description("Consul connection protocol", ``). - PlaceHolder("SCHEME"). - Group("Consul") - }) - bdr.AddFlg(func(b cli.FlagBuilder) { - b.Default(""). - Titles("username", "u", "user", "usr", "uid"). - Description("HTTP Basic auth user", ``). - PlaceHolder("USERNAME"). - Group("Consul") - }) - bdr.AddFlg(func(b cli.FlagBuilder) { - b.Default(""). - Titles("password", "pw", "passwd", "pass", "pwd"). - Description("HTTP Basic auth password", ``). - PlaceHolder("PASSWORD"). - Group("Consul"). - ExternalEditor(cli.ExternalToolPasswordInput) - }) - bdr.AddFlg(func(b cli.FlagBuilder) { - b.Default(""). - Titles("message", "m", "msg", "mesg"). - Description("The commit message", ``). - PlaceHolder("MSG"). - Group("Git"). - ExternalEditor(cli.ExternalToolEditor) - }) + bdr.Flg("addr", "a"). + Default("localhost"). + Description("Consul ip/host and port: HOST[:PORT] (No leading 'http(s)://')", ``). + PlaceHolder("HOST[:PORT]"). + Group("Consul"). + Build() + bdr.Flg("port", "p"). + Default(8500). + Description("Consul port", ``). + PlaceHolder("PORT"). + Group("Consul"). + Build() + bdr.Flg("insecure", "K"). + Default(false). + Description("Skip TLS host verification", ``). + PlaceHolder(""). + Group("Consul"). + Build() + bdr.Flg("prefix", "px"). + Default("/"). + Description("Root key prefix", ``). + PlaceHolder("ROOT"). + Group("Consul"). + Build() + bdr.Flg("cacert", ""). + Default(""). + Description("Consul Client CA cert)", ``). + PlaceHolder("FILE"). + Group("Consul"). + Build() + bdr.Flg("cert", ""). + Default(""). + Description("Consul Client cert", ``). + PlaceHolder("FILE"). + Group("Consul"). + Build() + bdr.Flg("scheme", ""). + Default("http"). + Description("Consul connection protocol", ``). + PlaceHolder("SCHEME"). + Group("Consul"). + Build() + bdr.Flg("username", "u", "user", "usr", "uid"). + Default(""). + Description("HTTP Basic auth user", ``). + PlaceHolder("USERNAME"). + Group("Consul"). + Build() + bdr.Flg("password", "pw", "passwd", "pass", "pwd"). + Default(""). + Description("HTTP Basic auth password", ``). + PlaceHolder("PASSWORD"). + Group("Consul"). + ExternalEditor(cli.ExternalToolPasswordInput). + Build() + bdr.Flg("message", "m", "msg", "mesg"). + Default(""). + Description("The commit message", ``). + PlaceHolder("MSG"). + Group("Git"). + ExternalEditor(cli.ExternalToolEditor). + Build() } func serverStartup(cmd *cli.Command, args []string) (err error) { diff --git a/cli/examples/more.go b/cli/examples/more.go index 18912b9..47458d7 100644 --- a/cli/examples/more.go +++ b/cli/examples/more.go @@ -52,56 +52,44 @@ func AttachServerCommand(parent cli.CommandBuilder) { //nolint:revive // ':postscript file:_files -g \*.\(ps\|eps\)' Build() - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("start", "s", "st", "run", "startup"). - Description("startup this system service/daemon", ``). - OnAction(serverStartup) - b.Flg("foreground", "f", "fg", "fore"). - Default(false). - Description("run foreground", ``). - Build() - }) - - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("run1", "nf", "startup1"). - Description("startup this system service/daemon", ``). - OnAction(serverStartup) - b.AddCmd(func(b cli.CommandBuilder) { - b.Titles("run1", "nf", "startup1"). - Description("startup this system service/daemon", ``). - OnAction(serverStartup) - }) - }) - - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("stop", "t", "pause", "resume", "stp", "hlt", "halt"). - Description("stop this system service/daemon", ``). - OnAction(serverStop) - }) - - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("restart", "r", "reload", "live-reload"). - Description("restart/reload/live-reload this system service/daemon", ``). - OnAction(serverRestart) - }) - - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("status", "st"). - Description("display its running status as a system service/daemon", ``). - OnAction(serverStatus) - }) - - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("install", "i", "inst", "setup"). - Description("install as a system service/daemon", ``). - OnAction(serverInstall) - }) - - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("uninstall", "u", "remove", "rm", "delete"). - Description("uninstall a system service/daemon", ``). - OnAction(serverUninstall) - }) + cb := parent.Cmd("start", "s", "st", "run", "startup"). + Description("startup this system service/daemon", ``). + OnAction(serverStartup) + cb.Flg("foreground", "f", "fg", "fore"). + Default(false). + Description("run foreground", ``). + Build() + cb.Build() + + cb = parent.Cmd("run1", "nf", "startup1"). + Description("startup this system service/daemon", ``). + OnAction(serverStartup) + cb.Cmd("run1", "nf", "startup1"). + Description("startup this system service/daemon", ``). + OnAction(serverStartup). + Build() + cb.Build() + + parent.Cmd("stop", "t", "pause", "resume", "stp", "hlt", "halt"). + Description("stop this system service/daemon", ``). + OnAction(serverStop). + Build() + parent.Cmd("restart", "r", "reload", "live-reload"). + Description("restart/reload/live-reload this system service/daemon", ``). + OnAction(serverRestart). + Build() + parent.Cmd("status", "st"). + Description("display its running status as a system service/daemon", ``). + OnAction(serverStatus). + Build() + parent.Cmd("install", "i", "inst", "setup"). + Description("install as a system service/daemon", ``). + OnAction(serverInstall). + Build() + parent.Cmd("uninstall", "u", "remove", "rm", "delete"). + Description("uninstall a system service/daemon", ``). + OnAction(serverUninstall). + Build() } // AttachKvCommand adds 'kv' command to a builder (eg: app.App) @@ -122,33 +110,32 @@ func AttachKvCommand(parent cli.CommandBuilder) { // parent.AddCmd(func(b cli.CommandBuilder) { parent.Titles("kv-store", "kv", "kvstore"). Description("consul kv store operations...", ``) + AttachConsulConnectFlags(parent) - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("backup", "b", "bf", "bkp"). - Description("Dump Consul's KV database to a JSON/YAML file", ``). - OnAction(kvBackup) - b.Flg("output", "o", "out"). - Default("consul-backup.json"). - Description("Write output to a file (*.json / *.yml)", ``). - PlaceHolder("FILE"). - CompActionStr(`*.(json|yml|yaml)`). // \*.\(ps\|eps\) - // ':postscript file:_files -g \*.\(ps\|eps\)' - Build() - }) - - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("restore", "r"). - Description("restore to Consul's KV store, from a a JSON/YAML backup file", ``). - OnAction(kvRestore) - b.Flg("input", "i", "in"). - Default("consul-backup.json"). - Description("Read the input file (*.json / *.yml)", ``). - PlaceHolder("FILE"). - CompActionStr(`*.(json|yml|yaml)`). // \*.\(ps\|eps\) - // ':postscript file:_files -g \*.\(ps\|eps\)' - Build() - }) + cb := parent.Cmd("backup", "b", "bf", "bkp"). + Description("Dump Consul's KV database to a JSON/YAML file", ``). + OnAction(kvBackup) + cb.Flg("output", "o", "out"). + Default("consul-backup.json"). + Description("Write output to a file (*.json / *.yml)", ``). + PlaceHolder("FILE"). + CompActionStr(`*.(json|yml|yaml)`). // \*.\(ps\|eps\) + // ':postscript file:_files -g \*.\(ps\|eps\)' + Build() + cb.Build() + + cb = parent.Cmd("restore", "r"). + Description("restore to Consul's KV store, from a a JSON/YAML backup file", ``). + OnAction(kvRestore) + cb.Flg("input", "i", "in"). + Default("consul-backup.json"). + Description("Read the input file (*.json / *.yml)", ``). + PlaceHolder("FILE"). + CompActionStr(`*.(json|yml|yaml)`). // \*.\(ps\|eps\) + // ':postscript file:_files -g \*.\(ps\|eps\)' + Build() + cb.Build() // }) } @@ -200,13 +187,12 @@ func AttachMsCommand(parent cli.CommandBuilder) { //nolint:funlen //a test }). Build() - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("tags", "t"). - Description("tags operations of a micro-service", ""). - Group("") - AttachConsulConnectFlags(b) - tagsCommands(b) - }) + cb := parent.Cmd("tags", "t"). + Description("tags operations of a micro-service", ""). + Group("") + AttachConsulConnectFlags(cb) + tagsCommands(cb) + cb.Build() // tags := parent.Cmd("tags", "t"). // Description("tags operations of a micro-service", ""). @@ -218,166 +204,163 @@ func AttachMsCommand(parent cli.CommandBuilder) { //nolint:funlen //a test func tagsCommands(parent cli.CommandBuilder) { //nolint:revive // ms tags ls - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("list", "ls", "l", "lst", "dir"). - Description("list tags for ms tags cmd"). - Group("2333.List"). - OnAction(func(cmd *cli.Command, args []string) (err error) { - _, _ = cmd, args - return - }) - }) + cb := parent.Cmd("list", "ls", "l", "lst", "dir"). + Description("list tags for ms tags cmd"). + Group("2333.List"). + OnAction(func(cmd *cli.Command, args []string) (err error) { + _, _ = cmd, args + return + }) + cb.Build() // ms tags add - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("add", "a", "new", "create"). - Description("add tags"). - Deprecated("0.2.1"). - Group("") - - b.Flg("list", "ls", "l", "lst", "dir"). - Default([]string{}). - Description("tags add: a comma list to be added"). - Group(""). - PlaceHolder("LIST"). - Build() - - b.AddCmd(func(b1 cli.CommandBuilder) { - b1.Titles("check", "c", "chk"). - Description("[sub] check"). - Group("") - }) + cb = parent.Cmd("add", "a", "new", "create"). + Description("add tags"). + Deprecated("0.2.1"). + Group("") - b.AddCmd(func(b1 cli.CommandBuilder) { - b1.Titles("check-point", "pt", "chk-pt"). - Description("[sub][sub] checkpoint"). - Group("") - - b1.Flg("add", "a", "add-list"). - Default([]string{}). - Description("checkpoint: a comma list to be added."). - PlaceHolder("LIST"). - Group("List"). - Build() - - b1.Flg("remove", "r", "rm-list", "rm", "del", "delete"). - Default([]string{}). - Description("checkpoint: a comma list to be removed.", ``). - PlaceHolder("LIST"). - Group("List"). - Build() - }) + cb.Flg("list", "ls", "l", "lst", "dir"). + Default([]string{}). + Description("tags add: a comma list to be added"). + Group(""). + PlaceHolder("LIST"). + Build() - b.AddCmd(func(b1 cli.CommandBuilder) { - b1.Titles("check-in", "in", "chk-in"). - Description("[sub][sub] check-in"). - Group("") - - b1.AddFlg(func(b2 cli.FlagBuilder) { - b2.Titles("n", "name"). - Default(""). - Description("check-in name: a string to be added."). - Group("") - }) - - b1.AddCmd(func(b2 cli.CommandBuilder) { - b2.Titles("demo-1", "d1"). - Description("[sub][sub] check-in sub, d1"). - Group("") - }) - - b1.AddCmd(func(b2 cli.CommandBuilder) { - b2.Titles("demo-2", "d2"). - Description("[sub][sub] check-in sub, d2"). - Group("") - }) - - b1.AddCmd(func(b2 cli.CommandBuilder) { - b2.Titles("demo-3", "d3"). - Description("[sub][sub] check-in sub, d3"). - Group("") - }) - - b1.AddCmd(func(b2 cli.CommandBuilder) { - b2.Titles("check-out", "out", "chk-out"). - Description("[sub][sub] check-out"). - Group("") - }) - }) - }) + cb.Cmd("check", "c", "chk"). + Description("[sub] check"). + Group(""). + Build() + + cbc := cb.Cmd("check-point", "pt", "chk-pt"). + Description("[sub][sub] checkpoint"). + Group("") + + cbc.Flg("add", "a", "add-list"). + Default([]string{}). + Description("checkpoint: a comma list to be added."). + PlaceHolder("LIST"). + Group("List"). + Build() + + cbc.Flg("remove", "r", "rm-list", "rm", "del", "delete"). + Default([]string{}). + Description("checkpoint: a comma list to be removed.", ``). + PlaceHolder("LIST"). + Group("List"). + Build() + cbc.Build() + + cbc = cb.Cmd("check-in", "in", "chk-in"). + Description("[sub][sub] check-in"). + Group("") + + cbc.Flg("n", "name"). + Default(""). + Description("check-in name: a string to be added."). + Group(""). + Build() + + cbc.Cmd("demo-1", "d1"). + Description("[sub][sub] check-in sub, d1"). + Group(""). + Build() + + cbc.Cmd("demo-2", "d2"). + Description("[sub][sub] check-in sub, d2"). + Group(""). + Build() + + cbc.Cmd("demo-3", "d3"). + Description("[sub][sub] check-in sub, d3"). + Group(""). + Build() + + cbc.Cmd("check-out", "out", "chk-out"). + Description("[sub][sub] check-out"). + Group(""). + Build() + cbc.Build() + + cb.Build() // ms tags rm - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("rm", "r", "remove", "delete", "del", "erase"). - Description("remove tags"). - Group("") - b.Flg("list", "ls", "l", "lst", "dir"). - Default([]string{}). - Description("tags rm: a comma list to be added"). - Group(""). - PlaceHolder("LIST"). - Build() - }) + cb = parent.Cmd("rm", "r", "remove", "delete", "del", "erase"). + Description("remove tags"). + Group("") + cb.Flg("list", "ls", "l", "lst", "dir"). + Default([]string{}). + Description("tags rm: a comma list to be added"). + Group(""). + PlaceHolder("LIST"). + Build() + cb.Build() // ms tags modify - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("modify", "m", "mod", "modi", "update", "change"). - Description("modify tags of a service."). - Group(""). - OnAction(msTagsModify) - - AttachModifyFlags(b) - - b.Flg("add", "a", "add-list"). - Default([]string{}). - Description("tags modify: a comma list to be added."). - PlaceHolder("LIST"). - Group("List"). - Build() - b.Flg("remove", "r", "rm-list", "rm", "del", "delete"). - Default([]string{}). - Description("tags modify: a comma list to be removed."). - PlaceHolder("LIST"). - Group("List"). - Build() - }) + cb = parent.Cmd("modify", "m", "mod", "modi", "update", "change"). + Description("modify tags of a service."). + Group(""). + OnAction(msTagsModify) + + cb.Flg("delim", "d", "delimiter"). + Default("="). + Description("delimiter char in `non-plain` mode."). + PlaceHolder(""). + CompJustOnce(true). + Build() + + AttachModifyFlags(cb) + + cb.Flg("add", "a", "add-list"). + Default([]string{}). + Description("tags modify: a comma list to be added."). + PlaceHolder("LIST"). + Group("List"). + Build() + cb.Flg("remove", "r", "rm-list", "rm", "del", "delete"). + Default([]string{}). + Description("tags modify: a comma list to be removed."). + PlaceHolder("LIST"). + Group("List"). + Build() + + cb.Build() // ms tags toggle - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("toggle", "t", "tog", "switch"). - Description("toggle tags"). - Group(""). - OnAction(func(cmd *cli.Command, args []string) (err error) { - _, _ = cmd, args - return - }) - - AttachModifyFlags(b) - - b.Flg("set", "s"). - Default([]string{}). - Description("tags toggle: a comma list to be set"). - Group(""). - PlaceHolder("LIST"). - Build() - - b.Flg("unset", "un"). - Default([]string{}). - Description("tags toggle: a comma list to be unset"). - Group(""). - PlaceHolder("LIST"). - Build() - - b.Flg("address", "a", "addr"). - Default(""). - Description("tags toggle: the address of the service (by id or name)"). - PlaceHolder("HOST:PORT"). - Build() - }) + cb = parent.Cmd("toggle", "t", "tog", "switch"). + Description("toggle tags"). + Group(""). + OnAction(func(cmd *cli.Command, args []string) (err error) { + _, _ = cmd, args + return + }) + + AttachModifyFlags(cb) + + cb.Flg("set", "s"). + Default([]string{}). + Description("tags toggle: a comma list to be set"). + Group(""). + PlaceHolder("LIST"). + Build() + + cb.Flg("unset", "un"). + Default([]string{}). + Description("tags toggle: a comma list to be unset"). + Group(""). + PlaceHolder("LIST"). + Build() + + cb.Flg("address", "a", "addr"). + Default(""). + Description("tags toggle: the address of the service (by id or name)"). + PlaceHolder("HOST:PORT"). + Build() + + cb.Build() } func AttachMoreCommandsForTest(parent cli.CommandBuilder, moreAndMore bool) { //nolint:revive @@ -397,11 +380,10 @@ func AttachMoreCommandsForTest(parent cli.CommandBuilder, moreAndMore bool) { // tgCommand(more) mxCommand(more) - parent.AddFlg(func(b cli.FlagBuilder) { - b.Default(false). - Titles("enable-ueh", "ueh"). - Description("Enables the unhandled exception handler?") - }) + parent.Flg("enable-ueh", "ueh"). + Default(false). + Description("Enables the unhandled exception handler?"). + Build() cmdrPanic(more) @@ -416,239 +398,213 @@ func AttachMoreCommandsForTest(parent cli.CommandBuilder, moreAndMore bool) { // func tgCommand(parent cli.CommandBuilder) { //nolint:revive // toggle-group-test - without a default choice - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("tg-test", "tg", "toggle-group-test"). - Description("tg test new features", "tg test new features,\nverbose long descriptions here."). - Group("Test"). - OnAction(func(cmd *cli.Command, args []string) (err error) { - fmt.Printf("*** Got fruit (toggle group): %v\n", cmd.Set().MustString("app.tg-test.fruit")) + cb := parent.Cmd("tg-test", "tg", "toggle-group-test"). + Description("tg test new features", "tg test new features,\nverbose long descriptions here."). + Group("Test"). + OnAction(func(cmd *cli.Command, args []string) (err error) { + fmt.Printf("*** Got fruit (toggle group): %v\n", cmd.Set().MustString("app.tg-test.fruit")) - fmt.Printf("> STDIN MODE: %v \n", cmd.Set().MustBool("mx-test.stdin")) - fmt.Println() + fmt.Printf("> STDIN MODE: %v \n", cmd.Set().MustBool("mx-test.stdin")) + fmt.Println() - // logrus.Debug("debug") - // logrus.Info("debug") - // logrus.Warning("debug") - // logrus.WithField(logex.SKIP, 1).Warningf("dsdsdsds") - _, _ = cmd, args - - return - }). - Build() - b.AddFlg(func(b cli.FlagBuilder) { - b.Default(false). - Titles("apple", ""). - Description("the test text.", ""). - ToggleGroup("fruit"). - Build() - }) - b.AddFlg(func(b cli.FlagBuilder) { - b.Default(false).Titles("banana", ""). - Description("the test text.", ""). - ToggleGroup("fruit"). - Build() - }) - b.AddFlg(func(b cli.FlagBuilder) { - b.Default(true).Titles("orange", ""). - Description("the test text.", ""). - ToggleGroup("fruit"). - Build() + // logrus.Debug("debug") + // logrus.Info("debug") + // logrus.Warning("debug") + // logrus.WithField(logex.SKIP, 1).Warningf("dsdsdsds") + _, _ = cmd, args + + return }) - b.Build() - }) + + cb.Flg("apple", ""). + Default(false). + Description("the test text.", ""). + ToggleGroup("fruit"). + Build() + cb.Flg("banana", ""). + Default(false). + Description("the test text.", ""). + ToggleGroup("fruit"). + Build() + cb.Flg("orange", ""). + Default(true). + Description("the test text.", ""). + ToggleGroup("fruit"). + Build() + cb.Build() // tg2 - with a default choice - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("tg-test2", "tg2", "toggle-group-test2"). - Description("tg2 test new features", "tg2 test new features,\nverbose long descriptions here."). - Group("Test"). - OnAction(func(cmd *cli.Command, args []string) (err error) { - fmt.Printf("*** Got fruit (toggle group): %v\n", cmd.Set().MustString("app.tg-test2.fruit")) - _, _ = cmd, args + cb = parent.Cmd("tg-test2", "tg2", "toggle-group-test2"). + Description("tg2 test new features", "tg2 test new features,\nverbose long descriptions here."). + Group("Test"). + OnAction(func(cmd *cli.Command, args []string) (err error) { + fmt.Printf("*** Got fruit (toggle group): %v\n", cmd.Set().MustString("app.tg-test2.fruit")) + _, _ = cmd, args - fmt.Printf("> STDIN MODE: %v \n", cmd.Set().MustBool("mx-test.stdin")) - fmt.Println() - return - }). - Build() - - b.AddFlg(func(b cli.FlagBuilder) { - b.Default(false).Titles("apple", ""). - Description("the test text.", ""). - ToggleGroup("fruit"). - Build() - }) - b.AddFlg(func(b cli.FlagBuilder) { - b.Default(false).Titles("banana", ""). - Description("the test text.", ""). - ToggleGroup("fruit"). - Build() - }) - b.AddFlg(func(b cli.FlagBuilder) { - b.Default(false).Titles("orange", ""). - Description("the test text.", ""). - ToggleGroup("fruit"). - Build() + fmt.Printf("> STDIN MODE: %v \n", cmd.Set().MustBool("mx-test.stdin")) + fmt.Println() + return }) - }) + + cb.Flg("apple", ""). + Default(false). + Description("the test text.", ""). + ToggleGroup("fruit"). + Build() + cb.Flg("banana", ""). + Default(false). + Description("the test text.", ""). + ToggleGroup("fruit"). + Build() + cb.Flg("orange", ""). + Default(false). + Description("the test text.", ""). + ToggleGroup("fruit"). + Build() + + cb.Build() } func mxCommand(parent cli.CommandBuilder) { //nolint:revive // mx-test - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("mx-test", "mx"). - Description("mx test new features", "mx test new features,\nverbose long descriptions here."). - Group("Test"). - OnAction(func(cmd *cli.Command, args []string) (err error) { - _, _ = cmd, args - // cmdr.Set("test.1", 8) - cmd.Set().Set("test.deep.branch.1", "test") - z := cmd.Set().MustString("app.test.deep.branch.1") - fmt.Printf("*** Got app.test.deep.branch.1: %s\n", z) - if z != "test" { - logz.Fatal("err, expect 'test', but got z", "z", z) - } - - cmd.Set().Remove("app.test.deep.branch.1") - if cmd.Set().Has("app.test.deep.branch.1") { - logz.Fatal("FAILED, expect key not found, but found a value associated with: ", "value", cmd.Set().MustR("app.test.deep.branch.1")) + cb := parent.Cmd("mx-test", "mx"). + Description("mx test new features", "mx test new features,\nverbose long descriptions here."). + Group("Test"). + OnAction(func(cmd *cli.Command, args []string) (err error) { + _, _ = cmd, args + // cmdr.Set("test.1", 8) + cmd.Set().Set("test.deep.branch.1", "test") + z := cmd.Set().MustString("app.test.deep.branch.1") + fmt.Printf("*** Got app.test.deep.branch.1: %s\n", z) + if z != "test" { + logz.Fatal("err, expect 'test', but got z", "z", z) + } + + cmd.Set().Remove("app.test.deep.branch.1") + if cmd.Set().Has("app.test.deep.branch.1") { + logz.Fatal("FAILED, expect key not found, but found a value associated with: ", "value", cmd.Set().MustR("app.test.deep.branch.1")) + } + fmt.Printf("*** Got app.test.deep.branch.1 (after deleted): %s\n", cmd.Set().MustString("app.test.deep.branch.1")) + + fmt.Printf("*** Got pp: %s\n", cmd.Set().MustString("app.mx-test.password")) + fmt.Printf("*** Got msg: %s\n", cmd.Set().MustString("app.mx-test.message")) + fmt.Printf("*** Got fruit (valid args): %v\n", cmd.Set().MustString("app.mx-test.fruit")) + fmt.Printf("*** Got head (head-like): %v\n", cmd.Set().MustInt("app.mx-test.head")) + fmt.Println() + fmt.Printf("*** test text: %s\n", cmd.Set().MustString("mx-test.test")) + fmt.Println() + // fmt.Printf("> InTesting: args[0]=%v \n", tool.SavedOsArgs[0]) + // fmt.Println() + // fmt.Printf("> Used config file: %v\n", cmd.Set().GetUsedConfigFile()) + // fmt.Printf("> Used config files: %v\n", cmd.Set().GetUsingConfigFiles()) + // fmt.Printf("> Used config sub-dir: %v\n", cmd.Set().GetUsedConfigSubDir()) + + fmt.Printf("> STDIN MODE: %v \n", cmd.Set().MustBool("mx-test.stdin")) + fmt.Println() + + // logrus.Debug("debug") + // logrus.Info("debug") + // logrus.Warning("debug") + // logrus.WithField(logex.SKIP, 1).Warningf("dsdsdsds") + + if cmd.Set().MustBool("mx-test.stdin") { + fmt.Println("> Type your contents here, press Ctrl-D to end it:") + var data []byte + data, err = dir.ReadAll(os.Stdin) + if err != nil { + logz.Error("error:", "err", err) + return } - fmt.Printf("*** Got app.test.deep.branch.1 (after deleted): %s\n", cmd.Set().MustString("app.test.deep.branch.1")) - - fmt.Printf("*** Got pp: %s\n", cmd.Set().MustString("app.mx-test.password")) - fmt.Printf("*** Got msg: %s\n", cmd.Set().MustString("app.mx-test.message")) - fmt.Printf("*** Got fruit (valid args): %v\n", cmd.Set().MustString("app.mx-test.fruit")) - fmt.Printf("*** Got head (head-like): %v\n", cmd.Set().MustInt("app.mx-test.head")) + fmt.Println("> The input contents are:") + fmt.Print(string(data)) fmt.Println() - fmt.Printf("*** test text: %s\n", cmd.Set().MustString("mx-test.test")) - fmt.Println() - // fmt.Printf("> InTesting: args[0]=%v \n", tool.SavedOsArgs[0]) - // fmt.Println() - // fmt.Printf("> Used config file: %v\n", cmd.Set().GetUsedConfigFile()) - // fmt.Printf("> Used config files: %v\n", cmd.Set().GetUsingConfigFiles()) - // fmt.Printf("> Used config sub-dir: %v\n", cmd.Set().GetUsedConfigSubDir()) + } + return + }) - fmt.Printf("> STDIN MODE: %v \n", cmd.Set().MustBool("mx-test.stdin")) - fmt.Println() + cb.Flg("test", "t"). + Default(""). + Description("the test text.", ""). + EnvVars("COOLT", "TEST"). + Group(""). + Build() - // logrus.Debug("debug") - // logrus.Info("debug") - // logrus.Warning("debug") - // logrus.WithField(logex.SKIP, 1).Warningf("dsdsdsds") - - if cmd.Set().MustBool("mx-test.stdin") { - fmt.Println("> Type your contents here, press Ctrl-D to end it:") - var data []byte - data, err = dir.ReadAll(os.Stdin) - if err != nil { - logz.Error("error:", "err", err) - return - } - fmt.Println("> The input contents are:") - fmt.Print(string(data)) - fmt.Println() - } - return - }). - Build() - - b.AddFlg(func(b cli.FlagBuilder) { - b.Default(""). - Titles("test", "t"). - Description("the test text.", ""). - EnvVars("COOLT", "TEST"). - Group(""). - Build() - }) + cb.Flg("password", "pp"). + Default(""). + Description("the password requesting.", ""). + Group(""). + PlaceHolder("PASSWORD"). + ExternalEditor(cli.ExternalToolPasswordInput). + Build() - b.AddFlg(func(b cli.FlagBuilder) { - b.Default(""). - Titles("password", "pp"). - Description("the password requesting.", ""). - Group(""). - PlaceHolder("PASSWORD"). - ExternalEditor(cli.ExternalToolPasswordInput). - Build() - }) + cb.Flg("message", "m", "msg"). + Default(""). + Description("the message requesting.", ""). + Group(""). + PlaceHolder("MESG"). + ExternalEditor(cli.ExternalToolEditor). + Build() - b.AddFlg(func(b cli.FlagBuilder) { - b.Default(""). - Titles("message", "m", "msg"). - Description("the message requesting.", ""). - Group(""). - PlaceHolder("MESG"). - ExternalEditor(cli.ExternalToolEditor). - Build() - }) + cb.Flg("fruit", "fr"). + Default(""). + Description("the message.", ""). + Group(""). + PlaceHolder("FRUIT"). + ValidArgs("apple", "banana", "orange"). + Build() - b.AddFlg(func(b cli.FlagBuilder) { - b.Default(""). - Titles("fruit", "fr"). - Description("the message.", ""). - Group(""). - PlaceHolder("FRUIT"). - ValidArgs("apple", "banana", "orange"). - Build() - }) + cb.Flg("head", "hd"). + Default(1). + Description("the head lines.", ""). + Group(""). + PlaceHolder("LINES"). + HeadLike(true, 1, 3000). + Build() - b.AddFlg(func(b cli.FlagBuilder) { - b.Default(1). - Titles("head", "hd"). - Description("the head lines.", ""). - Group(""). - PlaceHolder("LINES"). - HeadLike(true, 1, 3000). - Build() - }) + cb.Flg("stdin", "c"). + Default(false). + Description("read file content from stdin.", ""). + Group(""). + Build() - b.AddFlg(func(b cli.FlagBuilder) { - b.Default(false). - Titles("stdin", "c"). - Description("read file content from stdin.", ""). - Group(""). - Build() - }) - }) + cb.Build() } func cmdrXyPrint(parent cli.CommandBuilder) { // xy-print - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("xy-print", "xy"). - Description("test terminal control sequences", "xy-print test terminal control sequences,\nverbose long descriptions here."). - Group("Test"). - OnAction(func(cmd *cli.Command, args []string) (err error) { - // - // https://en.wikipedia.org/wiki/ANSI_escape_code - // https://zh.wikipedia.org/wiki/ANSI%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97 - // https://en.wikipedia.org/wiki/POSIX_terminal_interface - // + parent.Cmd("xy-print", "xy"). + Description("test terminal control sequences", "xy-print test terminal control sequences,\nverbose long descriptions here."). + Group("Test"). + OnAction(func(cmd *cli.Command, args []string) (err error) { + // + // https://en.wikipedia.org/wiki/ANSI_escape_code + // https://zh.wikipedia.org/wiki/ANSI%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97 + // https://en.wikipedia.org/wiki/POSIX_terminal_interface + // - _, _ = cmd, args + _, _ = cmd, args - fmt.Println("\x1b[2J") // clear screen + fmt.Println("\x1b[2J") // clear screen - for i, s := range args { - fmt.Printf("\x1b[s\x1b[%d;%dH%s\x1b[u", 15+i, 30, s) - } + for i, s := range args { + fmt.Printf("\x1b[s\x1b[%d;%dH%s\x1b[u", 15+i, 30, s) + } - return - }). - Build() - }) + return + }). + Build() } func cmdrKbPrint(parent cli.CommandBuilder) { // kb-print - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("kb-print", "kb"). - Description("kilobytes test", "test kibibytes' input,\nverbose long descriptions here."). - Group("Test"). - Examples(` + cb := parent.Cmd("kb-print", "kb"). + Description("kilobytes test", "test kibibytes' input,\nverbose long descriptions here."). + Group("Test"). + Examples(` $ {{.AppName}} kb --size 5kb 5kb = 5,120 bytes $ {{.AppName}} kb --size 8T @@ -656,104 +612,96 @@ $ {{.AppName}} kb --size 8T $ {{.AppName}} kb --size 1g 1GB = 1,073,741,824 bytes `). - OnAction(func(cmd *cli.Command, args []string) (err error) { - // fmt.Printf("Got size: %v (literal: %v)\n\n", cmdr.GetKibibytesR("kb-print.size"), cmdr.GetStringR("kb-print.size")) - _, _ = cmd, args - return - }). - Build() - b.AddFlg(func(b cli.FlagBuilder) { - b.Default("1k").Titles("size", "s"). - Description("max message size. Valid formats: 2k, 2kb, 2kB, 2KB. Suffixes: k, m, g, t, p, e.", ""). - Group(""). - Build() + OnAction(func(cmd *cli.Command, args []string) (err error) { + // fmt.Printf("Got size: %v (literal: %v)\n\n", cmdr.GetKibibytesR("kb-print.size"), cmdr.GetStringR("kb-print.size")) + _, _ = cmd, args + return }) - }) + + cb.Flg("size", "s"). + Default("1k"). + Description("max message size. Valid formats: 2k, 2kb, 2kB, 2KB. Suffixes: k, m, g, t, p, e.", ""). + Group(""). + Build() + + cb.Build() } func cmdrPanic(parent cli.CommandBuilder) { // panic test - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("panic-test", "pa"). - Description("test panic inside cmdr actions", ""). - Group("Test"). - Build() - - val := 9 - zeroVal := zero - - b.AddCmd(func(b cli.CommandBuilder) { - b.Titles("division-by-zero", "dz"). - Description(""). - Group("Test"). - OnAction(func(cmd *cli.Command, args []string) (err error) { - _, _ = cmd, args - fmt.Println(val / zeroVal) - return - }). - Build() - }) - b.AddCmd(func(b cli.CommandBuilder) { - b.Titles("panic", "pa"). - Description(""). - Group("Test"). - OnAction(func(cmd *cli.Command, args []string) (err error) { - _, _ = cmd, args - panic(9) - }). - Build() - }) - }) + + cb := parent.Cmd("panic-test", "pa"). + Description("test panic inside cmdr actions", ""). + Group("Test") + + val := 9 + zeroVal := zero + + cb.Cmd("division-by-zero", "dz"). + Description(""). + Group("Test"). + OnAction(func(cmd *cli.Command, args []string) (err error) { + _, _ = cmd, args + fmt.Println(val / zeroVal) + return + }). + Build() + cb.Cmd("panic", "pa"). + Description(""). + Group("Test"). + OnAction(func(cmd *cli.Command, args []string) (err error) { + _, _ = cmd, args + panic(9) + }). + Build() + + cb.Build() } func cmdrSoundex(parent cli.CommandBuilder) { - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("soundex", "snd", "sndx", "sound"). - Description("soundex test"). - Group("Test"). - TailPlaceHolders("[text1, text2, ...]"). - OnAction(func(cmd *cli.Command, args []string) (err error) { - _, _ = cmd, args - for ix, s := range args { - fmt.Printf("%5d. %s => %s\n", ix, s, text.Soundex(s)) - } - return - }). - Build() - }) + parent.Cmd("soundex", "snd", "sndx", "sound"). + Description("soundex test"). + Group("Test"). + TailPlaceHolders("[text1, text2, ...]"). + OnAction(func(cmd *cli.Command, args []string) (err error) { + _, _ = cmd, args + for ix, s := range args { + fmt.Printf("%5d. %s => %s\n", ix, s, text.Soundex(s)) + } + return + }). + Build() } func cmdrTtySize(parent cli.CommandBuilder) { - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("cols", "rows", "tty-size"). - Description("detected tty size"). - Group("Test"). - OnAction(func(cmd *cli.Command, args []string) (err error) { - _, _ = cmd, args - - cols, rows := term.GetTtySize() - fmt.Printf(" 1. cols = %v, rows = %v\n\n", cols, rows) - - cols, rows, err = term.GetSize(int(os.Stdout.Fd())) - fmt.Printf(" 2. cols = %v, rows = %v | in-docker: %v\n\n", cols, rows, is.InDocker()) - if err != nil { - log.Printf(" err: %v", err) - } - - var out []byte - cc := exec.Command("stty", "size") - cc.Stdin = os.Stdin - out, err = cc.Output() - fmt.Printf(" 3. out: %v", string(out)) - fmt.Printf(" err: %v\n", err) + parent.Cmd("cols", "rows", "tty-size"). + Description("detected tty size"). + Group("Test"). + OnAction(func(cmd *cli.Command, args []string) (err error) { + _, _ = cmd, args - if is.InDocker() { - log.Printf(" 4 run-in-docker: %v", true) - } - return - }). - Build() - }) + cols, rows := term.GetTtySize() + fmt.Printf(" 1. cols = %v, rows = %v\n\n", cols, rows) + + cols, rows, err = term.GetSize(int(os.Stdout.Fd())) + fmt.Printf(" 2. cols = %v, rows = %v | in-docker: %v\n\n", cols, rows, is.InDocker()) + if err != nil { + log.Printf(" err: %v", err) + } + + var out []byte + cc := exec.Command("stty", "size") + cc.Stdin = os.Stdin + out, err = cc.Output() + fmt.Printf(" 3. out: %v", string(out)) + fmt.Printf(" err: %v\n", err) + + if is.InDocker() { + log.Printf(" 4 run-in-docker: %v", true) + } + return + }). + Build() } func cmdrManyCommandsTest(parent cli.CommandBuilder) { @@ -767,32 +715,30 @@ func cmdrManyCommandsTest(parent cli.CommandBuilder) { // ttl := strings2.Join(strings.ReverseStringSlice(ttls), ".") ttl := "" - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles(t, fmt.Sprintf("sc%v", i)). - Description(fmt.Sprintf("subcommands %v.sc%v test", ttl, i)). - Group("Test"). - Build() - cmdrAddFlags(b) - }) + cb := parent.Cmd(t, fmt.Sprintf("sc%v", i)). + Description(fmt.Sprintf("subcommands %v.sc%v test", ttl, i)). + Group("Test") + cmdrAddFlags(cb) + cb.Build() } } func cmdrMultiLevelTest(parent cli.CommandBuilder) { - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles("mls", "mls"). - Description("multi-level subcommands test"). - Group("Test"). - Build() - // Sets(func(cmd obj.CommandBuilder) { - // cmdrAddFlags(cmd) - // }) - - // cmd := root.NewSubCommand("mls", "mls"). - // Description("multi-level subcommands test"). - // Group("Test") - cmdrAddFlags(b) - cmdrMultiLevel(b, 1) - }) + cb := parent.Cmd("mls", "mls"). + Description("multi-level subcommands test"). + Group("Test") + + // Sets(func(cmd obj.CommandBuilder) { + // cmdrAddFlags(cmd) + // }) + + // cmd := root.NewSubCommand("mls", "mls"). + // Description("multi-level subcommands test"). + // Group("Test") + cmdrAddFlags(cb) + cmdrMultiLevel(cb, 1) + + cb.Build() } func cmdrMultiLevel(parent cli.CommandBuilder, depth int) { @@ -810,150 +756,132 @@ func cmdrMultiLevel(parent cli.CommandBuilder, depth int) { // ttl := strings.Join(tool.ReverseStringSlice(ttls), ".") ttl := "" - parent.AddCmd(func(b cli.CommandBuilder) { - b.Titles(t, fmt.Sprintf("sc%v", i)). - // cc := parent.NewSubCommand(t, fmt.Sprintf("sc%v", i)). - Description(fmt.Sprintf("subcommands %v.sc%v test", ttl, i)). - Group("Test"). - Build() - cmdrAddFlags(b) - cmdrMultiLevel(b, depth+1) - }) + cb := parent.Cmd(t, fmt.Sprintf("sc%v", i)). + // cc := parent.NewSubCommand(t, fmt.Sprintf("sc%v", i)). + Description(fmt.Sprintf("subcommands %v.sc%v test", ttl, i)). + Group("Test") + cmdrAddFlags(cb) + cmdrMultiLevel(cb, depth+1) + cb.Build() } } func cmdrAddFlags(c cli.CommandBuilder) { //nolint:revive - c.AddFlg(func(b cli.FlagBuilder) { - b.Default(false).Titles("apple", ""). - Description("the test text.", ""). - ToggleGroup("fruit"). - Build() - }) - c.AddFlg(func(b cli.FlagBuilder) { - b.Default(false).Titles("banana", ""). - Description("the test text.", ""). - ToggleGroup("fruit"). - Build() - }) - c.AddFlg(func(b cli.FlagBuilder) { - b.Default(false).Titles("orange", ""). - Description("the test text.", ""). - ToggleGroup("fruit"). - Build() - }) - - c.AddFlg(func(b cli.FlagBuilder) { - b.Default("").Titles("message", "m", "msg"). - Description("the message requesting.", ""). - Group(""). - PlaceHolder("MESG"). - ExternalEditor(cli.ExternalToolEditor). - Build() - }) - c.AddFlg(func(b cli.FlagBuilder) { - b.Default("").Titles("fruit", "fr"). - Description("the message.", ""). - Group(""). - PlaceHolder("FRUIT"). - ValidArgs("apple", "banana", "orange"). - Build() - }) - c.AddFlg(func(b cli.FlagBuilder) { - b.Default(false). - Titles("bool", "b"). - Description("A bool flag", ""). - Group(""). - Build() - }) - c.AddFlg(func(b cli.FlagBuilder) { - b.Default(1). - Titles("int", "i"). - Description("A int flag", ""). - Group("1000.Integer"). - Build() - }) - c.AddFlg(func(b cli.FlagBuilder) { - b.Default(int64(2)). - Titles("int64", "i64"). - Description("A int64 flag", ""). - Group("1000.Integer"). - Build() - }) - c.AddFlg(func(b cli.FlagBuilder) { - b.Default(uint(3)). - Titles("uint", "u"). - Description("A uint flag", ""). - Group("1000.Integer"). - Build() - }) - c.AddFlg(func(b cli.FlagBuilder) { - b.Default(uint64(4)). - Titles("uint64", "u64"). - Description("A uint64 flag", ""). - Group("1000.Integer"). - Build() - }) - c.AddFlg(func(b cli.FlagBuilder) { - b.Default(float32(2.71828)). - Titles("float32", "f", "float"). - Description("A float32 flag with 'e' value", ""). - Group("2000.Float"). - Build() - }) - c.AddFlg(func(b cli.FlagBuilder) { - b.Default(3.14159265358979323846264338327950288419716939937510582097494459230781640628620899). - Titles("float64", "f64"). - Description("A float64 flag with a `PI` value", ""). - Group("2000.Float"). - Build() - }) - c.AddFlg(func(b cli.FlagBuilder) { - b.Default(complex64(3.14+9i)). - Titles("complex64", "c64"). - Description("A complex64 flag", ""). - Group("2010.Complex"). - Build() - }) - c.AddFlg(func(b cli.FlagBuilder) { - b.Default(complex128(3.14+9i)). - Titles("complex128", "c128"). - Description("A complex128 flag", ""). - Group("2010.Complex"). - Build() - }) + c.Flg("apple", ""). + Default(false). + Description("the test text.", ""). + ToggleGroup("fruit"). + Build() + + c.Flg("banana", ""). + Default(false). + Description("the test text.", ""). + ToggleGroup("fruit"). + Build() + + c.Flg("orange", ""). + Default(false). + Description("the test text.", ""). + ToggleGroup("fruit"). + Build() + + c.Flg("message", "m", "msg"). + Default(""). + Description("the message requesting.", ""). + Group(""). + PlaceHolder("MESG"). + ExternalEditor(cli.ExternalToolEditor). + Build() + + c.Flg("fruit", "fr"). + Default(""). + Description("the message.", ""). + Group(""). + PlaceHolder("FRUIT"). + ValidArgs("apple", "banana", "orange"). + Build() + + c.Flg("bool", "b"). + Default(false). + Description("A bool flag", ""). + Group(""). + Build() + + c.Flg("int", "i"). + Default(1). + Description("A int flag", ""). + Group("1000.Integer"). + Build() + + c.Flg("int64", "i64"). + Default(int64(2)). + Description("A int64 flag", ""). + Group("1000.Integer"). + Build() + + c.Flg("uint", "u"). + Default(uint(3)). + Description("A uint flag", ""). + Group("1000.Integer"). + Build() + + c.Flg("uint64", "u64"). + Default(uint64(4)). + Description("A uint64 flag", ""). + Group("1000.Integer"). + Build() + + c.Flg("float32", "f", "float"). + Default(float32(2.71828)). + Description("A float32 flag with 'e' value", ""). + Group("2000.Float"). + Build() + + c.Flg("float64", "f64"). + Default(3.14159265358979323846264338327950288419716939937510582097494459230781640628620899). + Description("A float64 flag with a `PI` value", ""). + Group("2000.Float"). + Build() + + c.Flg("complex64", "c64"). + Default(complex64(3.14+9i)). + Description("A complex64 flag", ""). + Group("2010.Complex"). + Build() + + c.Flg("complex128", "c128"). + Default(complex128(3.14+9i)). + Description("A complex128 flag", ""). + Group("2010.Complex"). + Build() // a set of booleans - c.AddFlg(func(b cli.FlagBuilder) { - b.Default(false). - Titles("single", "s"). - Description("A bool flag: single", ""). - Group("Boolean"). - EnvVars(""). - Build() - }) - c.AddFlg(func(b cli.FlagBuilder) { - b.Default(false). - Titles("double", "d"). - Description("A bool flag: double", ""). - Group("Boolean"). - EnvVars(""). - Build() - }) - c.AddFlg(func(b cli.FlagBuilder) { - b.Default(false). - Titles("norway", "n", "nw"). - Description("A bool flag: norway", ""). - Group("Boolean"). - Build() - }) - c.AddFlg(func(b cli.FlagBuilder) { - b.Default(false). - Titles("mongo", "mongo"). - Description("A bool flag: mongo", ""). - Group("Boolean"). - Build() - }) + c.Flg("single", "s"). + Default(false). + Description("A bool flag: single", ""). + Group("Boolean"). + EnvVars(""). + Build() + + c.Flg("double", "d"). + Default(false). + Description("A bool flag: double", ""). + Group("Boolean"). + EnvVars(""). + Build() + + c.Flg("norway", "n", "nw"). + Default(false). + Description("A bool flag: norway", ""). + Group("Boolean"). + Build() + + c.Flg("mongo", "mongo"). + Default(false). + Description("A bool flag: mongo", ""). + Group("Boolean"). + Build() } const zero = 0 diff --git a/cli/worker/builtins.go b/cli/worker/builtins.go index 704595c..d20f914 100644 --- a/cli/worker/builtins.go +++ b/cli/worker/builtins.go @@ -370,134 +370,126 @@ $ {{.AppName}} gen man }). OnAction((&genS{}).onAction) - bb.AddCmd(func(b1 cli.CommandBuilder) { - b1.Titles("manual", "m", "man"). - Description("Generate Linux Manual Documentations"). - Group(cli.SysMgmtGroup). - Hidden(true, true). - OnMatched(func(c *cli.Command, position int, hitState *cli.MatchState) (err error) { //nolint:revive - return - }). - OnAction((&genManS{}).onAction) - - b1.AddFlg(func(b cli.FlagBuilder) { - b.Titles("dir", "d"). - Default(""). - Description("The output directory"). - Group("Output"). - Hidden(true, true). - PlaceHolder("DIR") - }) + b1 := bb.Cmd("manual", "m", "man"). + Description("Generate Linux Manual Documentations"). + Group(cli.SysMgmtGroup). + Hidden(true, true). + OnMatched(func(c *cli.Command, position int, hitState *cli.MatchState) (err error) { //nolint:revive + return + }). + OnAction((&genManS{}).onAction) - b1.AddFlg(func(b cli.FlagBuilder) { - b.Titles("type", "t"). - Default(1). - Description("Linux man type"). - Hidden(true, true). - HeadLike(true, 1, 9) - }) - }) + b1.Flg("dir", "d"). + Default(""). + Description("The output directory"). + Group("Output"). + Hidden(true, true). + PlaceHolder("DIR"). + Build() - bb.AddCmd(func(b1 cli.CommandBuilder) { - b1.Titles("doc", "d", "docx", "tex", "pdf", "markdown"). - Description("Generate documentations"). - Group(cli.SysMgmtGroup). - Hidden(true, true). - OnMatched(func(c *cli.Command, position int, hitState *cli.MatchState) (err error) { //nolint:revive - return - }). - OnAction((&genDocS{}).onAction) - - b1.AddFlg(func(b cli.FlagBuilder) { - b.Titles("dir", "d"). - Default(""). - Description("The output directory"). - Group("Output"). - Hidden(true, true). - PlaceHolder("DIR") - }) - }) + b1.Flg("type", "t"). + Default(1). + Description("Linux man type"). + Hidden(true, true). + HeadLike(true, 1, 9). + Build() - bb.AddCmd(func(b1 cli.CommandBuilder) { - b1.Titles("shell", "s", "sh", "bash", "zsh", "fish", "elvish", "fig", "powershell", "ps"). - Description("Generate the shell completion script or install it"). - Group(cli.SysMgmtGroup). - Hidden(true, true). - OnMatched(func(c *cli.Command, position int, hitState *cli.MatchState) (err error) { //nolint:revive - return - }). - OnAction((&genShS{}).onAction) - - b1.AddFlg(func(b cli.FlagBuilder) { - b.Titles("dir", "d"). - Default(""). - Description("The output directory"). - Group("Output"). - Hidden(true, true). - PlaceHolder("DIR") - }) + b1.Build() - b1.AddFlg(func(b cli.FlagBuilder) { - b.Titles("output", "o"). - Default(""). - Description("The output filename"). - Group("Output"). - Hidden(true, true). - PlaceHolder("FILE") - }) + b1 = bb.Cmd("doc", "d", "docx", "tex", "pdf", "markdown"). + Description("Generate documentations"). + Group(cli.SysMgmtGroup). + Hidden(true, true). + OnMatched(func(c *cli.Command, position int, hitState *cli.MatchState) (err error) { //nolint:revive + return + }). + OnAction((&genDocS{}).onAction) - b1.AddFlg(func(b cli.FlagBuilder) { - b.Titles("auto", "a"). - Default(true). - Description("Generate auto completion script to fit for your current env"). - ToggleGroup("Shell"). - Hidden(true, true) - }) + b1.Flg("dir", "d"). + Default(""). + Description("The output directory"). + Group("Output"). + Hidden(true, true). + PlaceHolder("DIR"). + Build() - b1.AddFlg(func(b cli.FlagBuilder) { - b.Titles("zsh", "z"). - Default(false). - Description("Generate auto completion script for Zsh"). - ToggleGroup("Shell"). - Hidden(true, true) - }) + b1.Build() - b1.AddFlg(func(b cli.FlagBuilder) { - b.Titles("bash", "b"). - Default(false). - Description("Generate auto completion script for Bash"). - ToggleGroup("Shell"). - Hidden(true, true) - }) - b1.AddFlg(func(b cli.FlagBuilder) { - b.Titles("fish", "f"). - Default(false). - Description("Generate auto completion script for Fish"). - ToggleGroup("Shell"). - Hidden(true, true) - }) - b1.AddFlg(func(b cli.FlagBuilder) { - b.Titles("powershell", "p"). - Default(false). - Description("Generate auto completion script for PowerShell"). - ToggleGroup("Shell"). - Hidden(true, true) - }) - b1.AddFlg(func(b cli.FlagBuilder) { - b.Titles("elvish", "e"). - Default(false). - Description("Generate auto completion script for Elvish [TODO]"). - ToggleGroup("Shell"). - Hidden(true, true) - }) - b1.AddFlg(func(b cli.FlagBuilder) { - b.Titles("fig", "f"). - Default(false). - Description("Generate auto completion script for fig-shell [TODO]"). - ToggleGroup("Shell"). - Hidden(true, true) - }) - }) + b1 = bb.Cmd("shell", "s", "sh", "bash", "zsh", "fish", "elvish", "fig", "powershell", "ps"). + Description("Generate the shell completion script or install it"). + Group(cli.SysMgmtGroup). + Hidden(true, true). + OnMatched(func(c *cli.Command, position int, hitState *cli.MatchState) (err error) { //nolint:revive + return + }). + OnAction((&genShS{}).onAction) + + b1.Flg("dir", "d"). + Default(""). + Description("The output directory"). + Group("Output"). + Hidden(true, true). + PlaceHolder("DIR"). + Build() + + b1.Flg("output", "o"). + Default(""). + Description("The output filename"). + Group("Output"). + Hidden(true, true). + PlaceHolder("FILE"). + Build() + + b1.Flg("auto", "a"). + Default(true). + Description("Generate auto completion script to fit for your current env"). + ToggleGroup("Shell"). + Hidden(true, true). + Build() + + b1.Flg("zsh", "z"). + Default(false). + Description("Generate auto completion script for Zsh"). + ToggleGroup("Shell"). + Hidden(true, true). + Build() + + b1.Flg("bash", "b"). + Default(false). + Description("Generate auto completion script for Bash"). + ToggleGroup("Shell"). + Hidden(true, true). + Build() + + b1.Flg("fish", "f"). + Default(false). + Description("Generate auto completion script for Fish"). + ToggleGroup("Shell"). + Hidden(true, true). + Build() + + b1.Flg("powershell", "p"). + Default(false). + Description("Generate auto completion script for PowerShell"). + ToggleGroup("Shell"). + Hidden(true, true). + Build() + + b1.Flg("elvish", "e"). + Default(false). + Description("Generate auto completion script for Elvish [TODO]"). + ToggleGroup("Shell"). + Hidden(true, true). + Build() + + b1.Flg("fig", "f"). + Default(false). + Description("Generate auto completion script for fig-shell [TODO]"). + ToggleGroup("Shell"). + Hidden(true, true). + Build() + + b1.Build() }) } diff --git a/cli/worker/i_test.go b/cli/worker/i_test.go index 170aa58..f88b150 100644 --- a/cli/worker/i_test.go +++ b/cli/worker/i_test.go @@ -48,97 +48,83 @@ func buildDemoApp() (app cli.App) { //nolint:revive Info("demo-app", "0.3.1"). Author("hedzr") - app.AddCmd(func(b cli.CommandBuilder) { - b.Titles("jump"). - Description("jump is a demo command"). - Examples(`jump example`). - Deprecated(`since: v0.9.1`). - Hidden(false). - AddCmd(func(b cli.CommandBuilder) { - b.Titles("to"). - Description("to command"). - Examples(``). - Deprecated(``). - Hidden(false). - OnAction(func(cmd *cli.Command, args []string) (err error) { //nolint:revive - return // handling command action here - }) - - b.AddFlg(func(b cli.FlagBuilder) { - b.Default(false). - Titles("full", "f"). - Description("full command") - }) - }) - b.AddFlg(func(b cli.FlagBuilder) { - b.Default(false). - Titles("empty", "e"). - Description("empty command") - }) - }).AddFlg(func(b cli.FlagBuilder) { - b.Titles("dry-run", "n"). - Default(false). - Description("run all but without committing") - }) + b := app.Cmd("jump"). + Description("jump is a demo command"). + Examples(`jump example`). + Deprecated(`since: v0.9.1`). + Hidden(false) + b.Cmd("to"). + Description("to command"). + Examples(``). + Deprecated(``). + Hidden(false). + OnAction(func(cmd *cli.Command, args []string) (err error) { //nolint:revive + return // handling command action here + }). + Build() + + b.Flg("full", "f"). + Default(false). + Description("full command"). + Build() + + b.Flg("empty", "e"). + Default(false). + Description("empty command"). + Build() + b.Build() + + app.Flg("dry-run", "n"). + Default(false). + Description("run all but without committing"). + Build() app.Flg("wet-run", "w"). Default(false). Description("run all but with committing"). Build() // no matter even if you're adding the duplicated one. - app.AddCmd(func(b cli.CommandBuilder) { - b.Titles("consul", "c"). - Description("command set for consul operations") - - b.Flg("data-center", "dc", "datacenter"). - // Description("set data-center"). - Default("dc-1"). - Build() - }) - - app.AddCmd(func(b cli.CommandBuilder) { - examples.AttachServerCommand(b) - }) - - app.AddCmd(func(b cli.CommandBuilder) { - examples.AttachKvCommand(b) - }) - - app.AddCmd(func(b cli.CommandBuilder) { - examples.AttachMsCommand(b) - }) - - app.AddCmd(func(b cli.CommandBuilder) { - examples.AttachMoreCommandsForTest(b, true) - }) - - app.AddCmd(func(b cli.CommandBuilder) { - b.Titles("display", "da"). - Description("command set for display adapter operations") - - b1 := b.Cmd("voodoo", "vd"). - Description("command set for voodoo operations") - b1.Flg("data-center", "dc", "datacenter"). - Default("dc-1"). - Build() - b1.Build() - - b2 := b.Cmd("nvidia", "nv"). - Description("command set for nvidia operations") - b2.Flg("data-center", "dc", "datacenter"). - Default("dc-1"). - Build() - b2.Build() - - b.AddCmd(func(b cli.CommandBuilder) { - b.Titles("amd", "amd"). - Description("command set for AMD operations") - b.Flg("data-center", "dc", "datacenter"). - Default("dc-1"). - Build() - }) - }) + b = app.Cmd("consul", "c"). + Description("command set for consul operations") + b.Flg("data-center", "dc", "datacenter"). + // Description("set data-center"). + Default("dc-1"). + Build() + b.Build() + + examples.AttachServerCommand(app.NewCommandBuilder("server")) + + examples.AttachKvCommand(app.NewCommandBuilder("kv")) + + examples.AttachMsCommand(app.NewCommandBuilder("ms")) + + examples.AttachMoreCommandsForTest(app.NewCommandBuilder("more"), true) + + b = app.Cmd("display", "da"). + Description("command set for display adapter operations") + + b1 := b.Cmd("voodoo", "vd"). + Description("command set for voodoo operations") + b1.Flg("data-center", "dc", "datacenter"). + Default("dc-1"). + Build() + b1.Build() + + b2 := b.Cmd("nvidia", "nv"). + Description("command set for nvidia operations") + b2.Flg("data-center", "dc", "datacenter"). + Default("dc-1"). + Build() + b2.Build() + + b3 := b.Cmd("amd", "amd"). + Description("command set for AMD operations") + b3.Flg("data-center", "dc", "datacenter"). + Default("dc-1"). + Build() + b3.Build() + b.Build() return } diff --git a/cli/worker/worker_test.go b/cli/worker/worker_test.go new file mode 100644 index 0000000..1c9b008 --- /dev/null +++ b/cli/worker/worker_test.go @@ -0,0 +1,57 @@ +package worker + +import ( + "regexp" + "strings" + "testing" + + "github.com/hedzr/cmdr/v2/cli" + "github.com/hedzr/store" +) + +func TestWorkerS_Run2(t *testing.T) { //nolint:revive + aTaskBeforeRun := func(root *cli.RootCommand, runner cli.Runner, extras ...any) (err error) { return } //nolint:revive + + for i, c := range []struct { + args string + verifier taskAfterParse + opts []cli.Opt + }{ + {args: "m unk snd cool", verifier: func(w *workerS, ctx *parseCtx, errParsed error) (err error) { //nolint:revive + if !regexp.MustCompile(`UNKNOWN (Command|Flag) FOUND:?`).MatchString(errParsed.Error()) { + t.Log("expect 'UNKNOWN Command FOUND' error, but not matched.") // "unk" + } + return /* errParsed */ + }, opts: []cli.Opt{cli.WithUnmatchedAsError(true)}}, + + {}, + {}, + {}, + {}, + {}, + {}, + } { + if c.args == "" && c.verifier == nil { + continue + } + + t.Log() + t.Log() + t.Log() + t.Logf("--------------- test #%d: Parsing %q\n", i, c.args) + + app, ww := cleanApp(t, false) + ww.Config.Store = store.New() + // ww.Config.Loaders = []cli.Loader{loaders.NewConfigFileLoader(), loaders.NewEnvVarLoader()} + + ww.setArgs(append([]string{app.Name()}, strings.Split(c.args, " ")...)) + ww.tasksAfterParse = []taskAfterParse{c.verifier} + ww.Config.TasksBeforeRun = []cli.Task{aTaskBeforeRun} + err := ww.Run(c.opts...) // withTasksBeforeRun(taskBeforeRun),withTasksAfterParse(c.verifier)) + // err := app.Run() + if err != nil { + _ = app + t.Fatal(err) + } + } +}