hzDocs
hzDocs
文章 / 文档hedzr.com首页

cmdr series

介绍 cmdr

Guide

你的首个 CLI app更适合工程实践的版本
循序渐进
基本概念
命令命令:执行外部程序命令:预设参数命令:重定向命令:动态命令清单命令:在配置文件中定义别名清单命令:事件响应函数标志标志:必须项标志:可翻转组标志:枚举值标志:`Head -1` 风格标志:调用外部工具获得输入标志:自动否定标志:加号 `+` 前缀标志:事件响应函数解析结果内建命令和标志帮助子系统可共享共存的 app 实例辨析顶级函数WithOptsBackstage
如何……
Auto-close the ClosersRead config into structUsing is DetectorsUsing Store

References

What's New
Packages

Others

Examples
Blueprint
产品发布
产品发布之前
介绍 cmdr-cxx

Guide

cmdr supports

Intro

Guide

More features

References

Others

evendeep(-go)

Guide

Usagesdeepcopydeepdiffdeepequal
logg/slog(-go)

Guide

Guide

others

Components
trie-cxx

Guide

Guide

links

On Github

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/ 中都包含各种示例代码供你参考。

all.go
soundex.go
main.go
main.go
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()
}
cmd/all.go
package cmd

import (
	"github.com/hedzr/cmdr/v2/cli"
)

var Commands = append(
	[]cli.CmdAdder{
		sndx{},
	},
	// cmd.Commands...,
)
cmd/soundex.go
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 源文件,内容如下:

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 中:

cmd/all.go
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 已经装配好了所有有关的基本工作,所以这样开始:

  1. 在工作目录下新建 blueprint.toml 填写如下内容
    [zoo.camel]
    grouped = false
  2. 运行 ./bin/blueprint ~~debug 查看和找到 app.zoo.camel.grouped 表项以证实配置文件正确装载。
  3. 证实 ./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?

Components

Components

On Github

How is this guide?

最后更新于

目录

Blueprint
如何开始
和 devmode 一起工作
配置文件