hzDocs
hzDocs
Articles / Postshedzr.comIntroduction

Guide

Your First CLI AppConcise Version
Step by step
Concepts
CommandCommand: Invoke programCommand: Presetting ArgsCommand: RedirectToCommand: DynCommandCommand: Aliases from ConfigCommand: Event HandlersFlagFlag: RequiredFlag: Toggle GroupFlag: Valid ArgsFlag: `Head -1` styleFlag: External EditorFlag: NegatableFlag: Leading Plus Sign `+`Flag: Event Handlers解析结果Builtin Commands & Flags帮助子系统Shared App辨析Package level functionsWithOptsBackstage
Howto ...
Auto-close the ClosersRead config into structUsing is DetectorsUsing Store

References

What's New
Packages

Others

Examples
Blueprint
产品发布
产品发布之前
Howto ...

Read config into struct

Working with Store and struct

介绍

Manual of `hedzr/store`

Chapter: Using Store

`hedzr/store` on Github

cmdr.Set() 返回的 Store 对象包含了 app 的配置数据。层次化的配置数据可以通过 dottedPath 来访问。

// get `app.logging.file` as a string
println(cmdr.Set().MustString("logging.file"))

但有时候,将一颗子树抽出并映射到 struct 中可能是有用的。

cmdr.v2 通过 Store 对象的方法 To() / GetSectionFrom() 来实现这样的映射。其原型为:

To(path string, holder any, opts ...MOpt[T]) (err error)

同时,cmdr.To(path, holder, opts...) 是更便捷的调用。使用方法如下:

func TestTo(t *testing.T) {
	ctx := context.Background()
	app := cmdr.Create("app", "v1", `author`, `desc`,
		cli.WithArgs("test-app", "--debug"),
	).OnAction(func(ctx context.Context, cmd cli.Cmd, args []string) (err error) {
		b := cmdr.Store().MustBool("debug")
		println("debug flag: ", b)
		if !b {
			t.Fail()
		}
		println(cmdr.Set().Dump())
		type manS struct {
			Dir  string
			Type int
		}
		type genS struct {
			Manual manS
		}
		var v genS
		err = cmdr.To("cmd.generate", &v)
		if err != nil {
			t.Fail()
		}
		if v.Manual.Type != 1 {
			t.Fail()
		}
		return
	}).
		Build()
	err := app.Run(ctx)
	if err != nil {
		t.Errorf("Error: %v", err)
	}
}
func TestStore_GetSectionFrom(t *testing.T) {
	conf := newBasicStore()
	conf.Set("app.logging.words", []any{"a", 1, false})
	conf.Set("app.server.sites", -1)
	t.Logf("\nPath\n%v\n", conf.Dump())

    type loggingS struct {
    	File   uint
    	Rotate uint64
    	Words  []any
    }

    type serverS struct {
    	Start int
    	Sites int
    }

    type appS struct {
    	Debug   bool
    	Dump    int
    	Verbose bool
    	Logging loggingS
    	Server  serverS
    }

    type cfgS struct {
    	App appS
    }

    var ss cfgS
    err := conf.GetSectionFrom("", &ss)
    t.Logf("cfgS: %v | err: %v", ss, err)

    assertEqual(t, []any{"a", 1, false}, ss.App.Logging.Words)
    assertEqual(t, -1, ss.App.Server.Sites)

    if !reflect.DeepEqual(ss.App.Logging.Words, []any{"a", 1, false}) {
    	t.Fail()
    }

    err = conf.GetSectionFrom("nonexist", nil)
    t.Log("nothing happened")

    err = conf.GetSectionFrom("nonexist", &ss)
    t.Logf("cfgS: %v | err: %v", ss, err)
    if err != nil {
    	t.Fail()
    }
    assertTrue(t, ss.App.Server.Sites == -1)

}

func newBasicStore(opts ...Opt) \*storeS {
conf := New(opts...)
conf.Set("app.debug", false)
// t.Logf("\nPath\n%v\n", conf.dump())
conf.Set("app.verbose", true)
// t.Logf("\nPath\n%v\n", conf.dump())
conf.Set("app.dump", 3)
conf.Set("app.logging.file", "/tmp/1.log")
conf.Set("app.server.start", 5)

    // conf.Set("app.logging.rotate", 6)
    // conf.Set("app.logging.words", []string{"a", "1", "false"})

    ss := conf.WithPrefix("app.logging")
    ss.Set("rotate", 6)
    ss.Set("words", []string{"a", "1", "false"})
    return conf.(*storeS)

}

以 Test 1 为例,一个标准的 cmdr app 带有内建的 generate 子命令,相应的配置项节选如下:

  app.cmd.                      <B>
    generate.                   <B>
      manual.                   <B>
        dir                     <L> app.cmd.generate.manual.dir =>
        type                    <L> app.cmd.generate.manual.type => 1
      doc.dir                   <L> app.cmd.generate.doc.dir =>
      shell.                    <B>
        Shell                   <L> app.cmd.generate.shell.Shell => auto
        dir                     <L> app.cmd.generate.shell.dir =>
        output                  <L> app.cmd.generate.shell.output =>
        auto                    <L> app.cmd.generate.shell.auto => true
        zsh                     <L> app.cmd.generate.shell.zsh => false
        bash                    <L> app.cmd.generate.shell.bash => false
        fi                      <B>
          sh                    <L> app.cmd.generate.shell.fish => false
          g                     <L> app.cmd.generate.shell.fig => false
        powershell              <L> app.cmd.generate.shell.powershell => false
        elvish                  <L> app.cmd.generate.shell.elvish => false

从 app.cmd.generate 抽出子树映射到 genS 结构当中将会提取 app.cmd.generate.manual.dir 和 app.cmd.generate.manual.type 配置项。

这也意味着 v.(genS).Manual.Type 必然获得值 1。

了解更多

Manual of `hedzr/store`

Chapter: Using Store

`hedzr/store` on Github

What is Next?

How is this guide?

Last updated on

Auto-close the Closers

Managing the resource lifecycle (Peripherals)

Using is Detectors

is.inDeveloping()?

On this page

介绍
了解更多