144 lines
3.2 KiB
Markdown
144 lines
3.2 KiB
Markdown
# Wand
|
|
|
|
Wand is a library to wrap Go functions as executable binaries. It supports:
|
|
|
|
- hierarch of subcommands
|
|
- binding of command line options
|
|
- binding of environment variables
|
|
- binding of configuration entries
|
|
- positional arguments
|
|
- automatically generated help and documentation from go doc
|
|
|
|
## Example:
|
|
|
|
```
|
|
package main
|
|
|
|
import (
|
|
"strings"
|
|
"code.squareroundforest.org/arpio/wand"
|
|
)
|
|
|
|
func main() {
|
|
wand.Exec(strings.Split)
|
|
}
|
|
```
|
|
|
|
## Lib docs:
|
|
|
|
- [./lib.go](./lib.go)
|
|
- [go docs html](https://godocs.io/code.squareroundforest.org/arpio/wand)
|
|
|
|
## wand tool
|
|
|
|
The wand tool helps with following tasks:
|
|
|
|
- generating code from the go doc of the library that is converted by the wand library into an executable binary
|
|
- generating man(roff) or markdown documentation
|
|
- executing arbitrary Go functions in the command line addressed by their go path
|
|
|
|
Generating code with the docs of the wrapped library is particularly useful, because this way the automatically
|
|
generated help can be based on the go docs. This is an important part of the attempt to achieve that ideal
|
|
situation, where a solution to a problem is presented both as a library and a command line tool, and there is
|
|
only a single place ("source of truth") of documentation.
|
|
|
|
Executing arbitrary Go functions in the command line is only a lucky side effect of the way wand was built.
|
|
While it's not the primary function of the tool, it can be useful when just quickly trying out some Go functions
|
|
or expressions, without having to create a throwaway main.go file.
|
|
|
|
### wand tool installation
|
|
|
|
```
|
|
sudo make install
|
|
```
|
|
|
|
or in the current user's home:
|
|
|
|
```
|
|
prefix=~/.local make install
|
|
```
|
|
|
|
(See the recommended way below on how to use the locked version in the build tooling of a project.)
|
|
|
|
tool usage: docreflect for lib and man for cmd
|
|
|
|
### wand tool usage
|
|
|
|
Let's consider a project hierarchy such as in the root we have a library (mylib), and in the ./cmd directory we
|
|
have a main package, wrapping one or more functions of that library with wand as an executable binary:
|
|
|
|
```
|
|
./cmd/main.go
|
|
./lib.go
|
|
```
|
|
|
|
Generating the compiled docs from go doc of a library:
|
|
|
|
```
|
|
wand docreflect mylib .
|
|
```
|
|
|
|
Generating a man page for the command:
|
|
|
|
```
|
|
wand manpages --date-string $(2026-01-07) --version v1.0.0 ./cmd
|
|
```
|
|
|
|
### wand tool bonus usage
|
|
|
|
```
|
|
wand --import strings strings.Split 1:2:3 :
|
|
```
|
|
|
|
### wand tool docs
|
|
|
|
- [./cmd/readme.md](./cmd/readme.md)
|
|
|
|
When installed:
|
|
|
|
```
|
|
man wand
|
|
```
|
|
|
|
When not installed with man pages:
|
|
|
|
```
|
|
wand help
|
|
```
|
|
|
|
### wand tool usage with go.mod version
|
|
|
|
When generating the docs for a shared project, we may want to ensure that always the same version of wand is
|
|
used for both docreflect and manpages. Best is to use the version that is defined in go.mod. This can be
|
|
achieved using trivial scripts, the example below showing docreflect:
|
|
|
|
```
|
|
package main
|
|
|
|
import (
|
|
"code.squareroundforest.org/arpio/wand/tools"
|
|
"log"
|
|
"os"
|
|
)
|
|
|
|
func main() {
|
|
if len(os.Args) < 2 {
|
|
log.Fatalln("expected package name")
|
|
}
|
|
|
|
if err := tools.Docreflect(os.Stdout, os.Args[1], os.Args[2:]...); err != nil {
|
|
log.Fatalln(err)
|
|
}
|
|
}
|
|
```
|
|
|
|
and calling it, e.g. from a Makefile, with go run like:
|
|
|
|
```
|
|
go run script/gendocs.go mylib . gopath.to/me/mylib > docs.gen.go
|
|
```
|
|
|
|
---
|
|
|
|
*Made in Berlin, DE*
|