https://github.com/xmidt-org/clifx
Provides simple dependency injection for parsed command lines
https://github.com/xmidt-org/clifx
Last synced: 2 months ago
JSON representation
Provides simple dependency injection for parsed command lines
- Host: GitHub
- URL: https://github.com/xmidt-org/clifx
- Owner: xmidt-org
- License: apache-2.0
- Created: 2024-12-11T02:27:37.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2025-03-11T09:36:39.000Z (2 months ago)
- Last Synced: 2025-03-11T10:38:57.183Z (2 months ago)
- Language: Go
- Size: 58.6 KB
- Stars: 0
- Watchers: 9
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README
# clifx
[](https://github.com/xmidt-org/clifx/actions/workflows/ci.yml)
[](http://codecov.io/github/xmidt-org/clifx?branch=main)
[](https://goreportcard.com/report/github.com/xmidt-org/clifx)
[](https://github.com/xmidt-org/clifx/blob/main/LICENSE)
[](CHANGELOG.md)
[](https://pkg.go.dev/github.com/xmidt-org/clifx)## Summary
Provides basic bootstrapping for a parsed command line into an [fx.App](https://pkg.go.dev/go.uber.org/fx#App). [Kong](https://pkg.go.dev/github.com/alecthomas/kong) is used to parse a command line into an arbitrary `golang` **struct**.
## Table of Contents
- [Code of Conduct](#code-of-conduct)
- [Installation](#installation)
- [Usage](#usage)
- [Basic](#basic)
- [Lifecycle](#lifecycle)
- [Custom Options](#custom-options)
- [Suppressing os.Exit](#suppressing-osexit)
- [Custom Arguments](#custom-arguments)
- [Contributing](#contributing)## Code of Conduct
This project and everyone participating in it are governed by the [XMiDT Code Of Conduct](https://xmidt.io/code_of_conduct/).
By participating, you agree to this Code.## Installation
```shell
go get github.com/xmidt-org/clifx@latest
```## Usage
### Basic
```go
import github.com/xmidt-org/clifxtype MyCLI struct {
Debug bool
Files []string
}func main() {
app := fx.New(
clifx.Provide[MyCLI](
clifx.StandardArguments(),
),
// a component of type MyCLI will now
// be available for dependency injection.
// For example:
fx.Invoke(
func(cli MyCLI) error {
// do things
return nil
},
),// you can bind dependencies to the kong.Context. if desired,
// you must do this before calling kong.Context.Run:
fx.Supply("dependency"),
fx.Invoke(
func(kctx *kong.Context, dependency string) {
kctx.Bind(dependency) // this is now available in CLI methods
}
),// the kong.Context can be used to run the CLI.
// This will cause fx.New to run the command:
fx.Invoke(
func(kctx *kong.Context, sh fx.Shutdowner) error {
defer sh.Shutdown() // optional: this ensures the app exits from app.New
return kctx.Run() // you could pass dependencies to Run
},
)
)
}
```### Lifecycle
You can bind a CLI to the `fx.Lifecycle` in the same way as any other component. For example,
it's common to want to run the CLI when `fx.App.Run` is called, then shutdown the app when finished:```go
import github.com/xmidt-org/clifxtype MyCLI struct {
Debug bool
Files []string
}func main() {
app := fx.New(
clifx.Provide[MyCLI](
clifx.StandardArguments(),
),fx.Invoke(
func(kctx *kong.Context, l fx.Lifecycle, sh fx.Shutdowner /* any other dependencies from the enclosing app */) {
l.Append(fx.Hook{
OnStart: func(_ context.Context) error {
// optional: this just exits from app.Run when the CLI is done.
// without this, app.Run will not return until explicitly stopped, such as
// by hitting ctrl+C at a console.
defer sh.Shutdown()// don't forget: you can pass dependencies from the enclosing app here
return kctx.Run()
},
})
},
),
)// this now causes the CLI to be executed. Any error that is returned will be
// from the CLI tool.
app.Run()
}
```### Custom options
You can supply custom any number of `kong` options to `Provide`.
```go
clifx.Provide[MyCLI](
clifx.StandardArguments(),
kong.UsageOnError(),
kong.Description("here is a custom tool"),
)
```### Suppressing os.Exit
By default, `kong` will invoke `os.Exit(1)` anytime a parse fails. You can suppress this easily by providing a noop **Exit** function. `clifx` provides a `kong` option for this purpose:
```go
import github.com/xmidt-org/clifxtype MyCLI struct {
Debug bool
Files []string
}func main() {
app := fx.New(
clifx.Provide[MyCLI](
clifx.StandardArguments(),
clifx.SuppressExit(),
),
fx.Invoke(
func(cli MyCLI) error {
return nil
},
),
)// since we didn't exit the process, we can test app.Err()
var pe *kong.ParseError
if errors.As(app.Err(), &pe) {
// custom behavior in reaction to a bad command-line
}
}
```### Custom arguments
`clifx.StandardArguments` returns the command-line passed to the process. You can supply an arguments you like, which is useful for testing or interactive use:
```go
clifx.Provide[MyCLI](
clifx.AsArguments("--bind", ":8080", "-v"),
)
```## Contributing
Refer to [CONTRIBUTING.md](CONTRIBUTING.md).