asdf/internal/help/help.go
DeedleFake 5d5d04fbb7 feat(golang-rewrite): rename module and move main pacakge to cmd/asdf
* Replace direct `fmt.Println()` usage in a test with `t.Log()`
* Rename `cmd` to `cli`
* Move asdf command from module root
* Fix some linter warnings, thus enabling some tests that were being skipped
* Fix `Makefile`
* Rename module to `github.com/asdf-vm/asdf`
* Fix `TestGetAllToolsAndVersionsInContent/returns_empty_list_with_found_true_and_no_error_when_empty_content`
* Rewrite `Unique()` to be a bit more straightforwards
* Get workflow checks passing again

toolversions.Unique is ever so slightly faster, technically.

```
goos: linux
goarch: amd64
pkg: github.com/asdf-vm/asdf/internal/toolversions
cpu: AMD Ryzen 9 3900X 12-Core Processor
          │ /tmp/old.txt │            /tmp/new.txt            │
          │    sec/op    │   sec/op     vs base               │
Unique-24    346.5n ± 1%   342.4n ± 1%  -1.17% (p=0.027 n=10)

          │ /tmp/old.txt │          /tmp/new.txt          │
          │     B/op     │    B/op     vs base            │
Unique-24     160.0 ± 0%   160.0 ± 0%  ~ (p=1.000 n=10) ¹
¹ all samples are equal

          │ /tmp/old.txt │          /tmp/new.txt          │
          │  allocs/op   │ allocs/op   vs base            │
Unique-24     3.000 ± 0%   3.000 ± 0%  ~ (p=1.000 n=10) ¹
¹ all samples are equal
```
2024-12-18 11:32:04 -05:00

161 lines
4.0 KiB
Go

// Package help contains functions responsible for generating help output for
// asdf and asdf plugins.
package help
import (
_ "embed"
"fmt"
"io"
"os"
"strings"
"github.com/asdf-vm/asdf/internal/config"
"github.com/asdf-vm/asdf/internal/plugins"
"github.com/asdf-vm/asdf/internal/toolversions"
)
//go:embed help.txt
var helpText string
const quote = "\"Late but latest\"\n-- Rajinikanth"
// Print help output to STDOUT
func Print(asdfVersion string, plugins []plugins.Plugin) error {
return Write(asdfVersion, plugins, os.Stdout)
}
// PrintTool write tool help output to STDOUT
func PrintTool(conf config.Config, toolName string) error {
return WriteToolHelp(conf, toolName, os.Stdout, os.Stderr)
}
// PrintToolVersion write help for specific tool version to STDOUT
func PrintToolVersion(conf config.Config, toolName, toolVersion string) error {
return WriteToolVersionHelp(conf, toolName, toolVersion, os.Stdout, os.Stderr)
}
// Write help output to an io.Writer
func Write(asdfVersion string, allPlugins []plugins.Plugin, writer io.Writer) error {
_, err := writer.Write([]byte(fmt.Sprintf("version: %s\n\n", asdfVersion)))
if err != nil {
return err
}
_, err = writer.Write([]byte(helpText))
if err != nil {
return err
}
_, err = writer.Write([]byte("\n"))
if err != nil {
return err
}
extensionCommandHelp, err := pluginExtensionCommands(allPlugins)
if err != nil {
fmt.Printf("err %#+v\n", err)
return err
}
_, err = writer.Write([]byte(extensionCommandHelp))
if err != nil {
return err
}
_, err = writer.Write([]byte("\n"))
if err != nil {
return err
}
_, err = writer.Write([]byte(quote))
if err != nil {
return err
}
_, err = writer.Write([]byte("\n"))
if err != nil {
return err
}
return nil
}
// WriteToolHelp output to an io.Writer
func WriteToolHelp(conf config.Config, toolName string, writer io.Writer, errWriter io.Writer) error {
return writePluginHelp(conf, toolName, "", writer, errWriter)
}
// WriteToolVersionHelp output to an io.Writer
func WriteToolVersionHelp(conf config.Config, toolName, toolVersion string, writer io.Writer, errWriter io.Writer) error {
return writePluginHelp(conf, toolName, toolVersion, writer, errWriter)
}
func writePluginHelp(conf config.Config, toolName, toolVersion string, writer io.Writer, errWriter io.Writer) error {
plugin := plugins.New(conf, toolName)
env := map[string]string{
"ASDF_INSTALL_PATH": plugin.Dir,
}
if toolVersion != "" {
version := toolversions.Parse(toolVersion)
env["ASDF_INSTALL_VERSION"] = version.Value
env["ASDF_INSTALL_TYPE"] = version.Type
}
if err := plugin.Exists(); err != nil {
errWriter.Write([]byte(fmt.Sprintf("No plugin named %s\n", plugin.Name)))
return err
}
err := plugin.RunCallback("help.overview", []string{}, env, writer, errWriter)
if _, ok := err.(plugins.NoCallbackError); ok {
// No such callback, print err msg
errWriter.Write([]byte(fmt.Sprintf("No documentation for plugin %s\n", plugin.Name)))
return err
}
if err != nil {
return err
}
err = plugin.RunCallback("help.deps", []string{}, env, writer, errWriter)
if _, ok := err.(plugins.NoCallbackError); !ok {
return err
}
err = plugin.RunCallback("help.config", []string{}, env, writer, errWriter)
if _, ok := err.(plugins.NoCallbackError); !ok {
return err
}
err = plugin.RunCallback("help.links", []string{}, env, writer, errWriter)
if _, ok := err.(plugins.NoCallbackError); !ok {
return err
}
return nil
}
func pluginExtensionCommands(plugins []plugins.Plugin) (string, error) {
var output strings.Builder
for _, plugin := range plugins {
commands, err := plugin.GetExtensionCommands()
if err != nil {
return output.String(), err
}
if len(commands) > 0 {
output.WriteString(fmt.Sprintf("PLUGIN %s\n", plugin.Name))
for _, command := range commands {
if command == "" {
// must be default command
output.WriteString(fmt.Sprintf(" asdf %s\n", plugin.Name))
} else {
output.WriteString(fmt.Sprintf(" asdf %s %s\n", plugin.Name, command))
}
}
}
}
return output.String(), nil
}