wand/tools/lib.go

105 lines
4.1 KiB
Go

// Package tools provides tools to work with the wand library. The functions in this package serve primarily as
// the implementation of the wand executable command.
package tools
import (
"code.squareroundforest.org/arpio/docreflect/generate"
"fmt"
"io"
"os"
)
// DocreflectOption defines options for the docreflect function.
type DocreflectOptions struct {
// Main indicates that the docs for the symbols will be lookded up as part of the main package of an
// executable.
Main bool
}
// ManOptions represents input options for generating man pages for a command created with wand.
type ManOptions struct {
// DateString provides the value for the release date field in a man page.
DateString string
// Version provides the value for the release version field in a man page.
Version string
}
// MarkdownOptions represents input options for generating markdown documents for a command created with wand.
type MarkdownOptions struct {
// Level provides a default title level offset for the titles in a markdown document.
Level int
}
// ExecOptions represents input options for executing a function from the command line using the wand mechanism.
type ExecOptions struct {
// NoCache causes the execution to avoid relying on the cached artifacts resulting from a previous
// execution.
NoCache bool
// ClearCache clears the cached artifacts resulting from a previous execution before the current execution.
ClearCache bool
// CacheDir specifies a custom cache dir for wand. Default: ~/.wand.
CacheDir string
// Import lists the packages required for the expression to be executed. It accepts versioned package
// specifications, or it uses the latest version. When a package spec is prefixed with alias= or .=, it will
// import the package for the expression with the specified alias or inline.
Import []string
// ReplaceModule replaces imported Go modules with local or other versions of the given modules. The format
// of the items is: <module-path>=<replacement-module-path>, like for the go mod edit -replace command.
ReplaceModule []string
}
// Docreflect generates documentation from the go docs of a package to be included in the compiled binary and
// to be accessed by the automatic help and documentation generator.
//
// The packageName parameter specifies the package name for the generated Go code.
//
// The gopath arguments accept any number of package, package level symbol, or struct field paths. It is
// recommended to use package paths unless there are special circumstances.
func Docreflect(o DocreflectOptions, out io.Writer, packageName string, gopaths ...string) error {
genOpt := generate.Options{Main: o.Main}
return generate.GenerateRegistry(genOpt, out, packageName, gopaths...)
}
// Man generates a man page in roff format for a command defined with wand. It relies on the go doc entries
// extracted by Docreflect.
func Man(out io.Writer, o ManOptions, commandDir string) error {
return execCommandDir(
out,
commandDir,
"_wandgenerate=man",
fmt.Sprintf("_wandgeneratedate=%s", o.DateString),
fmt.Sprintf("_wandgenerateversion=%s", o.Version),
)
}
// Markdown generates a markdown page for a command defined with wand. It relies on the go doc entries extracted by
// Docreflect.
func Markdown(out io.Writer, o MarkdownOptions, commandDir string) error {
return execCommandDir(
out,
commandDir,
"_wandgenerate=markdown",
fmt.Sprintf("_wandmarkdownlevel=%d", o.Level),
)
}
// Exec executes a Go function expression parameterized by the subsequent command line arguments.
//
// It has two modes. When called with arguments, the first argument must be the function expression, and the
// rest of the arguments are the command line flags and positional arguments. When no arguments are provided, it
// starts reading from the input, and considers every line as the expected function expression followed by the
// options and positional arguments. In the latter case, the escaping is mostly identical to that of bash input.
// It keeps executing the input expressions until the input is closed (Ctrl+D).
func Exec(o ExecOptions, stdin io.Reader, stdout io.Writer, args ...string) error {
return execInput(o, stdin, stdout, os.Stderr, args...)
}