Blueprint
good practise for an app written with cmdr
Blueprint
blueprint app 展示了我们推荐的一种项目组织方法。源代码可以在 hedzr/cmdr-tests 的 这里 找到。
“重复的代码”?
除了在 hedzr/cmdr-tests 中有一个 blueprint 示例程序之外,在 hedzr/cmdr 的 examples 中同样有一个 blueprint 示例程序,该示例缺乏 hedzr/cmdr-loaders repo 所提供的外部文件、源的加载能力。
在 hedzr/cmdr-go-starter 中的代码模版同样是 blueprint,这里更为正式,更适合工程实作,因为它为项目代码提供了周边相关的文件,具有完整的代码规范。
在未来,blueprint 将会被放入 hedzr/cmdr-templates repo 中,作为一个默认模版向你提供。
真实世界
cmdr-cli (暂未释出) 工具是完全标准化的独立 app,其中也包含大量到 cmdr 库的代码,这里也是一个参考。
样本代码
hedzr/cmdr-tests 中,以及 hedzr/cmdr 的 examples/ 中都包含各种示例代码供你参考。
package main
import (
"context"
"os"
loaders "github.com/hedzr/cmdr-loaders"
"github.com/hedzr/cmdr-tests/examples/blueprint/cmd"
"github.com/hedzr/cmdr/v2"
"github.com/hedzr/cmdr/v2/cli"
"github.com/hedzr/cmdr/v2/examples/devmode"
"github.com/hedzr/cmdr/v2/pkg/logz"
)
const (
appName = "blueprint"
desc = `a good blueprint for you.`
version = cmdr.Version
author = `The Examples Authors`
)
func main() {
ctx := context.Background() app := prepareApp(cmd.Commands...) // define your own commands implementations with cmd/*.go
if err := app.Run(ctx); err != nil {
logz.ErrorContext(ctx, "Application Error:", "err", err) // stacktrace if in debug mode/build
os.Exit(app.SuggestRetCode())
} else if rc := app.SuggestRetCode(); rc != 0 {
os.Exit(rc)
}
}
func prepareApp(commands ...cli.CmdAdder) cli.App {
return loaders.Create(
appName, version, author, desc,
cmdr.WithAutoEnvBindings(true), // default it's false
cmdr.WithSortInHelpScreen(true), // default it's false
// cmdr.WithDontGroupInHelpScreen(false), // default it's false
// cmdr.WithForceDefaultAction(false),
).
// importing devmode package and run its init():
With(func(app cli.App) { logz.Debug("in dev mode?", "mode", devmode.InDevelopmentMode()) }).
WithBuilders(
// common.AddHeadLikeFlagWithoutCmd, // add a `--line` option, feel free to remove it.
// common.AddToggleGroupFlags, //
// common.AddTypedFlags, //
// common.AddKilobytesFlag, //
// common.AddValidArgsFlag, //
).
WithAdders(commands...).
Build()
}package cmd
import (
"github.com/hedzr/cmdr/v2/cli"
)
var Commands = append(
[]cli.CmdAdder{
sndx{},
},
// cmd.Commands...,
)package cmd
import (
"context"
"fmt"
"github.com/hedzr/cmdr/v2/cli"
"github.com/hedzr/cmdr/v2/pkg/text"
)
type sndx struct{}
func (sndx) Add(app cli.App) {
app.Cmd("soundex", "snd", "sndx", "sound").
Description("soundex test").
Group("Test").
TailPlaceHolders("[text1, text2, ...]").
OnAction(soundex).
Build()
}
func soundex(ctx context.Context, cmd cli.Cmd, args []string) (err error) {
_, _ = cmd, args
for ix, s := range args {
fmt.Printf("%5d. %s => %s\n", ix, s, text.Soundex(s))
}
return
}cmdr-tests 中的 blueprint 具有完整的应用程序基础能力。
除了集成了 Store 提供的完整的配置数据管理功能之外,也包含了自动装载配置源的功能。
此外,blueprint 在所有的方面都具备基本的支持。
所以从这里开始,你可以立即投入功能性开发。
如何开始
在有了 blueprint 的基础架构之后,你可以添加子命令。
例如我们想要增加一个 hello 子命令,那么首先可以在 cmd/ 文件夹中增加一个 hello.go 源文件,内容如下:
package cmd
import (
"context"
"fmt"
"github.com/hedzr/cmdr/v2/cli"
"github.com/hedzr/cmdr/v2/pkg/text"
)
type helloCmd struct{}
func (helloCmd) Add(app cli.App) {
app.Cmd("hello", "hi").
Description("hello test").
Group("Test").
OnAction(helloCmdRun).
Build()
}
func helloCmdRun(ctx context.Context, cmd cli.Cmd, args []string) (err error) {
_, _ = cmd, args
for ix, s := range args {
fmt.Printf("%5d. %s => %s\n", ix, s, text.Soundex(s))
}
return
}然后将 helloCmd{} 实例加入 cmd/all.go 的 Commands 中:
package cmd
import (
"github.com/hedzr/cmdr/v2/cli"
)
var Commands = append(
[]cli.CmdAdder{
sndx{},
helloCmd{},
},
// cmd.Commands...,
)现在 hello 子命令就添加就绪了,运行显示帮助屏将会得到下面的结果:
$ go run ./examples/blueprint/ -h
blueprint v2.1.1 ~ Copyright © 2025 by The Examples Authors ~ All Rights Reserved.
Usage:
$ blueprint [Options...][files...]
Description:
a good blueprint for you.
Commands:
[Test]
snd, soundex, sndx, sound soundex test
hello hello test
Global Flags:
[Misc]
-h, --help,--info,--usage Show this help screen (-?) [Env: HELP] (Default: true)
Type '-h'/'-?' or '--help' to get command help screen.
More: '-D'/'--debug', '-V'/'--version', '-#'/'--build-info', '--no-color'...
$和 devmode 一起工作
blueprint 集成了 devmode.go 来打包初始化用于开发模式的一系列状态环境:
- debugMode, traceMode and levels of them
- 状态同步的 logging 设置:是否允许
logz.Debug()输出(以及logz.Trace()) - 自动检测
.devmode文件是否存在并切入DevMode
这是通过
With(func(app cli.App) {
logz.Debug("in dev mode?", "mode", devmode.InDevelopmentMode())
}).来达成的。
该调用在初始化时刻引用 devmode 包中的 init func 来完成环境检测和状态初始化。
配置文件
cmdr-loader 已经装配好了所有有关的基本工作,所以这样开始:
- 在工作目录下新建
blueprint.toml填写如下内容[zoo.camel] grouped = false - 运行
./bin/blueprint ~~debug查看和找到app.zoo.camel.grouped表项以证实配置文件正确装载。 - 证实
./ci/etc/blueprint/的配置项已经被加载。
最后,在部署 app 时,将 ./ci/etc/blueprint/ 部署到 /etc/blueprint/,而将 ./blueprint.toml 和 bin/blueprint 可执行文件放在一起。
Tip
windows
将 ./ci/etc/blueprint/ 部署到 /etc/blueprint/ ?
macOS
将 ./ci/etc/blueprint/ 部署到 /usr/local/etc/blueprint/ 或者 /opt/homebrew/etc/blueprint 或者 $HOME/.config/blueprint 都是可以的。
:end:
What is Next?
How is this guide?
最后更新于