cmdr
is a POSIX-compliant, command-line UI (CLI) library in Golang.
It is a getopt-like parser of command-line options,
be compatible with the getopt_long
command line UI, which is an extension of the syntax recommended by POSIX.
We made many enhancements beyond the standard library flag
.
There is a fully-functional Options Store
(configurations) for your
hierarchical configuration dataset too.
The .netCore version Cmdr.Core is available now. And, a cxx
version cmdr-cxx
was pre-released just now (Happy Spring Festival 2021).
See the image frames at #1.
See our extras:
- cmdr-docs: documentations (Working)
- cmdr-addons: a new daemon plugin
dex
for linux/macOS/windows. - cmdr-examples: collects the samples for cmdr
- cmdr-go-starter: public template repo to new your cli app
and Bonus of #cmdr Series:
-
docs (WIP):
- english documentation NOT completed yet
- documentation at: https://hedzr.github.io/cmdr-docs/
-
v1.10.36 (WIP)
- _
-
v1.10.35
- fix nil exception while print error sometimes
-
v1.10.33
- routine maintenance release
-
v1.10.32
- fix: processing terminated too fast if global pre-actions return nil
-
v1.10.31
- routine maintenance release
-
v1.10.30
- routine maintenance release
- add: examples/example-app
- imp: use relative path in log output
- reenable error template
-
v1.10.29
- routine maintenance release
-
v1.10.27
- upgrade to errors.v3
-
v1.10.24
- fix: version command, help screen not work
-
v1.10.23
- fix: unknown switch char not an error now
- imp: refined gen zsh code, and gen shell codes
- fea: support fish-shell completion generating now
- fea: added root.
RunAsSubCommand
, treat 'app' as a synonym of 'app subcmd1 subcmd2' - imp/fix/fea: clarify the slice append or replace mode - SetNx &
SetNxOverwrite
for Option Store - fea: added
VendorHidden
field for when you wanna a never shown flag or command - fea: conf package - add
Serial
,SerialString
for CI tool - imp: erase man1 folder after
--man
- fix/imp: prints description with color escaped, when multiline
- fix: restore Match() but with new name MatchAndTest()
- fix: high-order fn hold the older copy, so pass it by holding a pointer to original variable
- imp: review most of the tests
- NOTE: cleanup the deprecated codes [
cmd.NewFlagV
,cmd.NewFlag
,cmd.NewSubCommand
, ...] - fea: more completion supports
-
v1.10.19
- temporary build for earlier testing
- confirmed: backward compatible with go1.12
-
v1.10.13
- fix/imp: adapt windir to *nix name to fit for generic config file loading
- fea/imp: improved Aliases algor, support more tmpl var substitute
- fix: fallback the unknown type as string type
- fea: add flag to control whether write the changes back to alternative config file or
not,
WithAlterConfigAutoWriteBack
- imp: name/desc fields of builtin commands and flags
- CHANGE: use bgo build-tool now, Makefile thrown
-
More details at CHANGELOG
Old README.md: README.old.md
See example-app
Expand to source codes
package main
import (
"fmt"
"github.com/hedzr/cmdr"
"github.com/hedzr/cmdr/examples/internal"
"github.com/hedzr/cmdr/plugin/pprof"
"github.com/hedzr/cmdr/tool"
"github.com/hedzr/log"
"github.com/hedzr/log/isdelve"
"github.com/hedzr/logex/build"
"gopkg.in/hedzr/errors.v3"
)
func main() {
Entry()
}
func Entry() {
root := buildRootCmd()
if err := cmdr.Exec(root, options...); err != nil {
log.Fatalf("error occurs in app running: %+v\n", err)
}
}
func buildRootCmd() (rootCmd *cmdr.RootCommand) {
root := cmdr.Root(appName, version).
//AddGlobalPreAction(func(cmd *cmdr.Command, args []string) (err error) {
// // cmdr.Set("enable-ueh", true)
// return
//}).
//AddGlobalPreAction(func(cmd *cmdr.Command, args []string) (err error) {
// //fmt.Printf("# global pre-action 2, exe-path: %v\n", cmdr.GetExecutablePath())
// return
//}).
//AddGlobalPostAction(func(cmd *cmdr.Command, args []string) {
// //fmt.Println("# global post-action 1")
//}).
//AddGlobalPostAction(func(cmd *cmdr.Command, args []string) {
// //fmt.Println("# global post-action 2")
//}).
Copyright(copyright, "hedzr").
Description(desc, longDesc).
Examples(examples)
rootCmd = root.RootCommand()
// for your biz-logic, constructing an AttachToCmdr(root *cmdr.RootCmdOpt) is recommended.
// see our full sample and template repo: https://github.com/hedzr/cmdr-go-starter
//core.AttachToCmdr(root.RootCmdOpt())
// These lines are removable
cmdr.NewBool(false).
Titles("enable-ueh", "ueh").
Description("Enables the unhandled exception handler?").
AttachTo(root)
//cmdrPanic(root)
cmdrSoundex(root)
//pprof.AttachToCmdr(root.RootCmdOpt())
return
}
func cmdrSoundex(root cmdr.OptCmd) {
cmdr.NewSubCmd().Titles("soundex", "snd", "sndx", "sound").
Description("soundex test").
Group("Test").
TailPlaceholder("[text1, text2, ...]").
Action(func(cmd *cmdr.Command, args []string) (err error) {
for ix, s := range args {
fmt.Printf("%5d. %s => %s\n", ix, s, tool.Soundex(s))
}
return
}).
AttachTo(root)
}
func onUnhandledErrorHandler(err interface{}) {
if cmdr.GetBoolR("enable-ueh") {
dumpStacks()
}
panic(err) // re-throw it
}
func dumpStacks() {
fmt.Printf("\n\n=== BEGIN goroutine stack dump ===\n%s\n=== END goroutine stack dump ===\n\n", errors.DumpStacksAsString(true))
}
func init() {
options = append(options, cmdr.WithUnhandledErrorHandler(onUnhandledErrorHandler))
options = append(options,
cmdr.WithLogx(build.New(build.NewLoggerConfigWith(
defaultDebugEnabled, defaultLoggerBackend, defaultLoggerLevel,
log.WithTimestamp(true, "")))))
options = append(options, cmdr.WithHelpTailLine(`
# Type '-h'/'-?' or '--help' to get command help screen.
# Star me if it's helpful: https://github.com/hedzr/cmdr/examples/example-app
`))
if isDebugBuild() {
options = append(options, pprof.GetCmdrProfilingOptions())
}
// enable '--trace' command line option to toggle a internal trace mode (can be retrieved by cmdr.GetTraceMode())
// import "github.com/hedzr/cmdr-addons/pkg/plugins/trace"
// trace.WithTraceEnable(defaultTraceEnabled)
// Or:
optAddTraceOption := cmdr.WithXrefBuildingHooks(func(root *cmdr.RootCommand, args []string) {
cmdr.NewBool(false).
Titles("trace", "tr").
Description("enable trace mode for tcp/mqtt send/recv data dump", "").
//Action(func(cmd *cmdr.Command, args []string) (err error) { println("trace mode on"); cmdr.SetTraceMode(true); return; }).
Group(cmdr.SysMgmtGroup).
AttachToRoot(root)
}, nil)
options = append(options, optAddTraceOption)
//options = append(options, optAddServerExtOpt«ion)
// allow and search '.<appname>.yml' at first
locations := []string{".$APPNAME.yml"}
locations = append(locations, cmdr.GetPredefinedLocations()...)
options = append(options, cmdr.WithPredefinedLocations(locations...))
options = append(options, internal.NewAppOption())
}
func isDebugBuild() bool { return isdelve.Enabled }
var options []cmdr.ExecOption
//goland:noinspection GoNameStartsWithPackageName
const (
appName = "example-app"
version = "0.2.5"
copyright = "example-app - A devops tool - cmdr series"
desc = "example-app is an effective devops tool. It make an demo application for 'cmdr'"
longDesc = `example-app is an effective devops tool. It make an demo application for 'cmdr'.
`
examples = `
$ {{.AppName}} gen shell [--bash|--zsh|--fish|--auto]
generate bash/shell completion scripts
$ {{.AppName}} gen man
generate linux man page 1
$ {{.AppName}} --help
show help screen.
$ {{.AppName}} --help --man
show help screen in manpage viewer (for linux/darwin).
`
overview = ``
zero = 0
defaultTraceEnabled = true
defaultDebugEnabled = false
defaultLoggerLevel = "debug"
defaultLoggerBackend = "logrus"
)
Here is a docker build for cmdr/examples/fluent so that you can run it without go building or downloading the release files:
# from Docker Hub:
$ docker run -it --rm hedzr/cmdr-fluent
$ docker run -it --rm hedzr/cmdr-fluent --help
# from Github Packages (please following the guide of GitHub Packages Site):
$ docker run -it --rm docker.pkg.github.com/hedzr/cmdr/cmdr-fluent
$ docker run -it --rm docker.pkg.github.com/hedzr/cmdr/cmdr-fluent --help
-
short
simple codes with structured data style. -
demo
normal demo with external config files. -
wget-demo
partial-covered for GNUwget
. -
fluent
demostrates how to define your command-ui with the fluent api style. -
a demo to show you how to migrate from go
flag
smoothly. -
cmdr-http2
http2 server with daemon supports, graceful shutdown -
awesome-tool
awesome-tool
is a cli app that fetch the repo stars and generate a markdown summary, accordingly with most of awesome-xxx list in github (such as awesome-go).
See Also the examples index: Examples.md (zh-cn TODO: Examples.zh-cn.md)
- https://github.com/hedzr/consul-tags
- https://github.com/hedzr/ini-op
- https://github.com/hedzr/awesome-tool
- austr
- Issue me to adding yours
Feel free to issue me bug reports and fixes. Many thanks to all contributors.
Thanks to JetBrains for donating product licenses to help develop **
cmdr**
MIT