From 6e3e3dd5aa5b560e9bede484640e8af5f4163d36 Mon Sep 17 00:00:00 2001 From: Arpad Ryszka Date: Tue, 30 Dec 2025 16:52:10 +0100 Subject: [PATCH] docs, config and tools testing --- config.go | 9 +- config_test.go | 93 +++++- docreflect.gen.go | 15 +- docreflect_test.go | 1 + exec.go | 8 +- go.mod | 2 +- go.sum | 2 + help.go | 91 ++--- help_test.go | 13 +- iniparser.gen.go | 2 +- internal/tests/testconfig.ini | 1 + internal/tests/testlib/cmd/main.go | 17 + internal/tests/testlib/lib.go | 3 + .../7uxW5Ik-qaesYEi3BWbg9Q.go | 5 + .../tmpdir/7uxW5Ik-qaesYEi3BWbg9Q/go.mod | 18 + .../tmpdir/7uxW5Ik-qaesYEi3BWbg9Q/go.sum | 20 ++ .../Du66PUa6l2PUdTO2P6Mz8w.go | 6 + .../tmpdir/Du66PUa6l2PUdTO2P6Mz8w/go.mod | 18 + .../tmpdir/Du66PUa6l2PUdTO2P6Mz8w/go.sum | 20 ++ .../GBAVk0TbT71P1fBFC4wZxQ.go | 22 ++ .../tmpdir/GBAVk0TbT71P1fBFC4wZxQ/go.mod | 18 + .../tmpdir/GBAVk0TbT71P1fBFC4wZxQ/go.sum | 20 ++ .../Vw9o9PuLOlqrxfbxo88FwA.go | 5 + .../tmpdir/Vw9o9PuLOlqrxfbxo88FwA/go.mod | 18 + .../tmpdir/Vw9o9PuLOlqrxfbxo88FwA/go.sum | 20 ++ .../W0w-rWwNmthjuerTOFnMIQ.go | 6 + .../tmpdir/W0w-rWwNmthjuerTOFnMIQ/go.mod | 18 + .../tmpdir/W0w-rWwNmthjuerTOFnMIQ/go.sum | 20 ++ .../c128RsAggPny5Yt3rXQnjA.go | 6 + .../tmpdir/c128RsAggPny5Yt3rXQnjA/go.mod | 18 + .../tmpdir/c128RsAggPny5Yt3rXQnjA/go.sum | 20 ++ .../djTBWFYLXSZapqVl11Wnpg.go | 6 + .../tmpdir/djTBWFYLXSZapqVl11Wnpg/go.mod | 18 + .../tmpdir/djTBWFYLXSZapqVl11Wnpg/go.sum | 20 ++ .../fbneVWE281vn9cQJ87O0vA.go | 6 + .../tmpdir/fbneVWE281vn9cQJ87O0vA/go.mod | 18 + .../tmpdir/fbneVWE281vn9cQJ87O0vA/go.sum | 20 ++ .../tmpdir/k_vqGB1P94wR5O4M7XiD4A/go.mod | 18 + .../tmpdir/k_vqGB1P94wR5O4M7XiD4A/go.sum | 20 ++ .../k_vqGB1P94wR5O4M7XiD4A.go | 5 + .../tmpdir/pPXRXBwDsfnuJDBB1hbG7w/go.mod | 18 + .../tmpdir/pPXRXBwDsfnuJDBB1hbG7w/go.sum | 20 ++ .../pPXRXBwDsfnuJDBB1hbG7w.go | 6 + .../tmpdir/qo6bOwdhYFcgh80Jx-WTyg/go.mod | 18 + .../tmpdir/qo6bOwdhYFcgh80Jx-WTyg/go.sum | 20 ++ .../qo6bOwdhYFcgh80Jx-WTyg.go | 23 ++ .../tmpdir/wtqcAdcxZGXt7vrbvOkxAw/go.mod | 18 + .../tmpdir/wtqcAdcxZGXt7vrbvOkxAw/go.sum | 20 ++ .../wtqcAdcxZGXt7vrbvOkxAw.go | 19 ++ lib.go | 2 +- lib_test.go | 15 + reflect.go | 9 - tools/exec.go | 4 - tools/execwand.go | 104 +++--- tools/execwand_test.go | 202 +++++++++++ tools/lib_test.go | 314 ++++++++++++++++++ 56 files changed, 1357 insertions(+), 121 deletions(-) create mode 100644 internal/tests/testconfig.ini create mode 100644 internal/tests/testlib/cmd/main.go create mode 100644 internal/tests/tmpdir/7uxW5Ik-qaesYEi3BWbg9Q/7uxW5Ik-qaesYEi3BWbg9Q.go create mode 100644 internal/tests/tmpdir/7uxW5Ik-qaesYEi3BWbg9Q/go.mod create mode 100644 internal/tests/tmpdir/7uxW5Ik-qaesYEi3BWbg9Q/go.sum create mode 100644 internal/tests/tmpdir/Du66PUa6l2PUdTO2P6Mz8w/Du66PUa6l2PUdTO2P6Mz8w.go create mode 100644 internal/tests/tmpdir/Du66PUa6l2PUdTO2P6Mz8w/go.mod create mode 100644 internal/tests/tmpdir/Du66PUa6l2PUdTO2P6Mz8w/go.sum create mode 100644 internal/tests/tmpdir/GBAVk0TbT71P1fBFC4wZxQ/GBAVk0TbT71P1fBFC4wZxQ.go create mode 100644 internal/tests/tmpdir/GBAVk0TbT71P1fBFC4wZxQ/go.mod create mode 100644 internal/tests/tmpdir/GBAVk0TbT71P1fBFC4wZxQ/go.sum create mode 100644 internal/tests/tmpdir/Vw9o9PuLOlqrxfbxo88FwA/Vw9o9PuLOlqrxfbxo88FwA.go create mode 100644 internal/tests/tmpdir/Vw9o9PuLOlqrxfbxo88FwA/go.mod create mode 100644 internal/tests/tmpdir/Vw9o9PuLOlqrxfbxo88FwA/go.sum create mode 100644 internal/tests/tmpdir/W0w-rWwNmthjuerTOFnMIQ/W0w-rWwNmthjuerTOFnMIQ.go create mode 100644 internal/tests/tmpdir/W0w-rWwNmthjuerTOFnMIQ/go.mod create mode 100644 internal/tests/tmpdir/W0w-rWwNmthjuerTOFnMIQ/go.sum create mode 100644 internal/tests/tmpdir/c128RsAggPny5Yt3rXQnjA/c128RsAggPny5Yt3rXQnjA.go create mode 100644 internal/tests/tmpdir/c128RsAggPny5Yt3rXQnjA/go.mod create mode 100644 internal/tests/tmpdir/c128RsAggPny5Yt3rXQnjA/go.sum create mode 100644 internal/tests/tmpdir/djTBWFYLXSZapqVl11Wnpg/djTBWFYLXSZapqVl11Wnpg.go create mode 100644 internal/tests/tmpdir/djTBWFYLXSZapqVl11Wnpg/go.mod create mode 100644 internal/tests/tmpdir/djTBWFYLXSZapqVl11Wnpg/go.sum create mode 100644 internal/tests/tmpdir/fbneVWE281vn9cQJ87O0vA/fbneVWE281vn9cQJ87O0vA.go create mode 100644 internal/tests/tmpdir/fbneVWE281vn9cQJ87O0vA/go.mod create mode 100644 internal/tests/tmpdir/fbneVWE281vn9cQJ87O0vA/go.sum create mode 100644 internal/tests/tmpdir/k_vqGB1P94wR5O4M7XiD4A/go.mod create mode 100644 internal/tests/tmpdir/k_vqGB1P94wR5O4M7XiD4A/go.sum create mode 100644 internal/tests/tmpdir/k_vqGB1P94wR5O4M7XiD4A/k_vqGB1P94wR5O4M7XiD4A.go create mode 100644 internal/tests/tmpdir/pPXRXBwDsfnuJDBB1hbG7w/go.mod create mode 100644 internal/tests/tmpdir/pPXRXBwDsfnuJDBB1hbG7w/go.sum create mode 100644 internal/tests/tmpdir/pPXRXBwDsfnuJDBB1hbG7w/pPXRXBwDsfnuJDBB1hbG7w.go create mode 100644 internal/tests/tmpdir/qo6bOwdhYFcgh80Jx-WTyg/go.mod create mode 100644 internal/tests/tmpdir/qo6bOwdhYFcgh80Jx-WTyg/go.sum create mode 100644 internal/tests/tmpdir/qo6bOwdhYFcgh80Jx-WTyg/qo6bOwdhYFcgh80Jx-WTyg.go create mode 100644 internal/tests/tmpdir/wtqcAdcxZGXt7vrbvOkxAw/go.mod create mode 100644 internal/tests/tmpdir/wtqcAdcxZGXt7vrbvOkxAw/go.sum create mode 100644 internal/tests/tmpdir/wtqcAdcxZGXt7vrbvOkxAw/wtqcAdcxZGXt7vrbvOkxAw.go create mode 100644 tools/execwand_test.go create mode 100644 tools/lib_test.go diff --git a/config.go b/config.go index dde607f..a16a7bd 100644 --- a/config.go +++ b/config.go @@ -78,17 +78,12 @@ func unescapeConfig(s string) string { return []rune{r}, false }, - func(escaped bool) []rune { - if escaped { - return []rune{'\\'} - } - - return nil - }, + nil, ), ) w.Write([]byte(s)) + w.Flush() return b.String() } diff --git a/config_test.go b/config_test.go index 971d75a..4380ff3 100644 --- a/config_test.go +++ b/config_test.go @@ -114,7 +114,7 @@ func TestConfig(t *testing.T) { ) t.Run( - "discard in previous same doc", + "discard in previous and same doc", testExec( testCase{ impl: fm, @@ -126,12 +126,18 @@ func TestConfig(t *testing.T) { ), ) - // check the syntax for tests - // - white space ignored - // - comment line - // - comment at the end of an entry - // - invalid key - // check the code for tests + t.Run( + "discard multiple values", + testExec( + testCase{ + impl: fm, + mergeConf: []string{"one=bar\none=baz\nsecond-var=baz", "one\nsecond-var=qux\nsecond-var"}, + command: "foo", + }, + "", + ";", + ), + ) t.Run("white space ignored", testExec(testCase{impl: fm, conf: "one = bar ", command: "foo"}, "", "bar;")) t.Run( @@ -148,4 +154,77 @@ func TestConfig(t *testing.T) { ) t.Run("invald key", testExec(testCase{impl: fm, conf: "one two = bar", command: "foo"}, "parse failed", "")) + t.Run( + "config file", + testExec( + testCase{ + impl: fm, + mergeConfTyped: []Config{ConfigFile("./internal/tests/testconfig.ini")}, + command: "foo", + }, + "", + "42;", + ), + ) + + t.Run( + "config file error", + testExec( + testCase{ + impl: fm, + mergeConfTyped: []Config{ConfigFile("./internal/tests/testconfig-noexist.ini")}, + command: "foo", + }, + "file", + ), + ) + + t.Run( + "config file error optional", + testExec( + testCase{ + impl: fm, + mergeConfTyped: []Config{OptionalConfig(ConfigFile("./internal/tests/testconfig-noexist.ini"))}, + command: "foo", + }, + "", + ";", + ), + ) + + t.Run( + "config from option", + testExec( + testCase{ + impl: fm, + mergeConfTyped: []Config{ConfigFromOption()}, + command: "foo --second-var bar --config ./internal/tests/testconfig.ini", + }, + "", + "42;bar", + ), + ) + + t.Run( + "config from option shadowed", + testExec( + testCase{ + impl: func(struct{ Config int }) {}, + mergeConfTyped: []Config{ConfigFromOption()}, + command: "foo --config ./internal/tests/testconfig.ini", + }, + "option reserved", + ), + ) + + t.Run( + "dangling backslash", + testExec( + testCase{ + impl: fm, + conf: "one = foo\\", + }, + "parse failed", + ), + ) } diff --git a/docreflect.gen.go b/docreflect.gen.go index 43dc6eb..6469672 100644 --- a/docreflect.gen.go +++ b/docreflect.gen.go @@ -9,13 +9,13 @@ import "code.squareroundforest.org/arpio/docreflect" func init() { docreflect.Register("code.squareroundforest.org/arpio/wand/tools", "") docreflect.Register("code.squareroundforest.org/arpio/wand/tools.Docreflect", "\nfunc(out, packageName, gopaths)") - docreflect.Register("code.squareroundforest.org/arpio/wand/tools.Exec", "\nfunc(o, stdin, args)") + docreflect.Register("code.squareroundforest.org/arpio/wand/tools.Exec", "\nfunc(o, stdin, stdout, args)") docreflect.Register("code.squareroundforest.org/arpio/wand/tools.ExecOptions", "") docreflect.Register("code.squareroundforest.org/arpio/wand/tools.ExecOptions.CacheDir", "") docreflect.Register("code.squareroundforest.org/arpio/wand/tools.ExecOptions.ClearCache", "") docreflect.Register("code.squareroundforest.org/arpio/wand/tools.ExecOptions.Import", "") - docreflect.Register("code.squareroundforest.org/arpio/wand/tools.ExecOptions.InlineImport", "") docreflect.Register("code.squareroundforest.org/arpio/wand/tools.ExecOptions.NoCache", "") + docreflect.Register("code.squareroundforest.org/arpio/wand/tools.ExecOptions.ReplaceModule", "") docreflect.Register("code.squareroundforest.org/arpio/wand/tools.Man", "\nfunc(out, o, commandDir)") docreflect.Register("code.squareroundforest.org/arpio/wand/tools.ManOptions", "") docreflect.Register("code.squareroundforest.org/arpio/wand/tools.ManOptions.DateString", "") @@ -25,11 +25,12 @@ func init() { docreflect.Register("code.squareroundforest.org/arpio/wand/tools.MarkdownOptions.Level", "") docreflect.Register("code.squareroundforest.org/arpio/wand/tools.commandReader", "\nfunc(in)") docreflect.Register("code.squareroundforest.org/arpio/wand/tools.execCommandDir", "\nfunc(out, commandDir, env)") + docreflect.Register("code.squareroundforest.org/arpio/wand/tools.execInput", "\nfunc(o, stdin, stdout, stderr, args)") docreflect.Register("code.squareroundforest.org/arpio/wand/tools.execInternal", "\nfunc(command, args)") - docreflect.Register("code.squareroundforest.org/arpio/wand/tools.execTransparent", "\nfunc(command, args)") - docreflect.Register("code.squareroundforest.org/arpio/wand/tools.execWand", "\nfunc(o, args)") + docreflect.Register("code.squareroundforest.org/arpio/wand/tools.execWand", "\nfunc(o, stdin, stdout, stderr, args)") docreflect.Register("code.squareroundforest.org/arpio/wand/tools.execc", "\nfunc(stdin, stdout, stderr, command, args, env)") - docreflect.Register("code.squareroundforest.org/arpio/wand/tools.hash", "\nfunc(expression, imports, inlineImports)") - docreflect.Register("code.squareroundforest.org/arpio/wand/tools.printGoFile", "\nfunc(fn, expression, imports, inlineImports)") - docreflect.Register("code.squareroundforest.org/arpio/wand/tools.readExec", "\nfunc(o, stdin)") + docreflect.Register("code.squareroundforest.org/arpio/wand/tools.hash", "\nfunc(expression, imports)") + docreflect.Register("code.squareroundforest.org/arpio/wand/tools.printGoFile", "\nfunc(fn, expression, imports)") + docreflect.Register("code.squareroundforest.org/arpio/wand/tools.readExec", "\nfunc(o, stdin, stdout, stderr)") + docreflect.Register("code.squareroundforest.org/arpio/wand/tools.selfPkg", "") } diff --git a/docreflect_test.go b/docreflect_test.go index 70f9d69..10e7c94 100644 --- a/docreflect_test.go +++ b/docreflect_test.go @@ -18,5 +18,6 @@ func init() { docreflect.Register("code.squareroundforest.org/arpio/wand/internal/tests/testlib.Options.Bar", "Bars, any number.\n") docreflect.Register("code.squareroundforest.org/arpio/wand/internal/tests/testlib.Options.Duration", "Duration is another option.\n") docreflect.Register("code.squareroundforest.org/arpio/wand/internal/tests/testlib.Options.Foo", "Foo is an option.\n") + docreflect.Register("code.squareroundforest.org/arpio/wand/internal/tests/testlib.Options.Some", "Some is an option of any type.\n") docreflect.Register("code.squareroundforest.org/arpio/wand/internal/tests/testlib.Options.Time", "Time is the third option here.\n") } diff --git a/exec.go b/exec.go index d111406..6b2a980 100644 --- a/exec.go +++ b/exec.go @@ -4,13 +4,17 @@ import ( "errors" "fmt" "io" - "path/filepath" + "path" "strconv" "time" ) func exec(stdin io.Reader, stdout, stderr io.Writer, exit func(int), cmd Cmd, conf Config, env, args []string) { - _, cmd.name = filepath.Split(args[0]) + generate := getenv(env, "_wandgenerate") + if cmd.name == "" || generate == "" { + _, cmd.name = path.Split(args[0]) + } + if err := validateCommand(cmd, conf); err != nil { fmt.Fprintf(stderr, "program error: %v\n", err) exit(1) diff --git a/go.mod b/go.mod index 3dbd4c5..44da9df 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 - code.squareroundforest.org/arpio/treerack v0.0.0-20251031193114-4f1c219052ae + code.squareroundforest.org/arpio/treerack v0.0.0-20251210201822-5e069c4ca4e7 github.com/iancoleman/strcase v0.3.0 golang.org/x/term v0.37.0 ) diff --git a/go.sum b/go.sum index 9e06bb2..120946a 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,8 @@ code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 h1:2 code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18/go.mod h1:+0G3gufMAP8SCEIrDT1D/DaVOSfjS8EwPTBs5vfxqQg= code.squareroundforest.org/arpio/treerack v0.0.0-20251031193114-4f1c219052ae h1:D28IunhepRhRSp3U2z84e3WtxbYMRzi/FwEEZg54ULM= code.squareroundforest.org/arpio/treerack v0.0.0-20251031193114-4f1c219052ae/go.mod h1:9XhPcVt1Y1M609z02lHvEcp00dwPD9NUCoVxS2TpcH8= +code.squareroundforest.org/arpio/treerack v0.0.0-20251210201822-5e069c4ca4e7 h1:5dXQ/w5nvo6k46BUvUNvpA9nnCvIOxPgVBJurIHnIYA= +code.squareroundforest.org/arpio/treerack v0.0.0-20251210201822-5e069c4ca4e7/go.mod h1:9XhPcVt1Y1M609z02lHvEcp00dwPD9NUCoVxS2TpcH8= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= diff --git a/help.go b/help.go index 93e42b0..5f92fc1 100644 --- a/help.go +++ b/help.go @@ -546,8 +546,8 @@ func docOptions(cmd Cmd, conf Config, titleLevel, wrapWidth, hintStyle int) []En } } -func docListSubcommands(cmd Cmd, fullCommand []string, wrapWidth int) []Entry { - subcommandsTitle := Title(1, "Subcommands:") +func docListSubcommands(cmd Cmd, fullCommand []string, level, wrapWidth int) []Entry { + subcommandsTitle := Title(level+1, "Subcommands:") var ( items []DefinitionItem @@ -600,11 +600,11 @@ func docListSubcommands(cmd Cmd, fullCommand []string, wrapWidth int) []Entry { } } -func docFullSubcommands(cmd Cmd, conf Config) []Entry { +func docFullSubcommands(cmd Cmd, conf Config, level int) []Entry { var e []Entry e = append( e, - Title(1, "Subcommands:"), + Title(level+1, "Subcommands:"), Paragraph(Text(docSubcommandHint)), ) @@ -643,7 +643,7 @@ func docFullSubcommands(cmd Cmd, conf Config) []Entry { command = fmt.Sprintf("%s (default)", command) } - e = append(e, Indent(Title(2, command), 2, 0)) + e = append(e, Indent(Title(level+2, command), 2, 0)) if sc.command.version != "" { e = append(e, Indent(Paragraph(Text("Show version.")), 4, 0)) continue @@ -656,7 +656,7 @@ func docFullSubcommands(cmd Cmd, conf Config) []Entry { e = append(e, synopsis...) if docs := docs(sc.command); len(docs) > 0 { - e = append(e, Indent(Title(3, "Description:"), 4, 0)) + e = append(e, Indent(Title(level+3, "Description:"), 4, 0)) for i := range docs { docs[i] = Indent(docs[i], 4, 0) } @@ -675,7 +675,7 @@ func docFullSubcommands(cmd Cmd, conf Config) []Entry { return e } -func docEnv(cmd Cmd) []Entry { +func docEnv(cmd Cmd, level int) []Entry { // env will not work if the app has a non-standard name: if !commandNameExpression.MatchString(cmd.name) { return nil @@ -686,13 +686,13 @@ func docEnv(cmd Cmd) []Entry { return nil } - e := []Entry{Title(1, "Environment variables:")} + e := []Entry{Title(level+1, "Environment variables:")} p := paragraphs(envDocs) for _, pi := range p { e = append(e, Indent(Paragraph(Text(pi)), 4, 0)) } - e = append(e, Indent(Title(2, "Example environment variable:"), 4, 0)) + e = append(e, Indent(Title(level+2, "Example environment variable:"), 4, 0)) option := options[0] name := strcase.ToScreamingSnake(fmt.Sprintf("%s-%s", cmd.name, option.Name())) value := "42" @@ -704,7 +704,7 @@ func docEnv(cmd Cmd) []Entry { return e } -func docConfig(cmd Cmd, conf Config) []Entry { +func docConfig(cmd Cmd, conf Config, level int) []Entry { options := allNonHelpOptions(cmd) if len(options) == 0 { return nil @@ -715,7 +715,7 @@ func docConfig(cmd Cmd, conf Config) []Entry { return nil } - e := []Entry{Title(1, "Configuration:")} + e := []Entry{Title(level+1, "Configuration:")} p := paragraphs(configDocs) for _, pi := range p { e = append(e, Indent(Paragraph(Text(pi)), 4, 0)) @@ -742,7 +742,7 @@ func docConfig(cmd Cmd, conf Config) []Entry { e = append( e, - Indent(Title(2, "Configuration files:"), 4, 0), + Indent(Title(level+2, "Configuration files:"), 4, 0), Indent(List(items...), 8, 0), ) @@ -762,7 +762,7 @@ func docConfig(cmd Cmd, conf Config) []Entry { e = append( e, - Indent(Title(2, "Example configuration entry:"), 4, 0), + Indent(Title(level+2, "Example configuration entry:"), 4, 0), Indent(CodeBlock(exampleCode), 4, 0), ) @@ -773,7 +773,7 @@ func docConfig(cmd Cmd, conf Config) []Entry { e = append( e, - Indent(Title(2, "Example for discarding an inherited entry:"), 4, 0), + Indent(Title(level+2, "Example for discarding an inherited entry:"), 4, 0), Indent(CodeBlock(discardExample), 4, 0), ) @@ -802,10 +802,19 @@ func helpOptions(cmd Cmd, conf Config, width int) []Entry { } func helpSubcommands(cmd Cmd, fullCommand []string, width int) []Entry { - return docListSubcommands(cmd, fullCommand, width) + return docListSubcommands(cmd, fullCommand, 0, width) } func manTitle(cmd Cmd, date time.Time, version string) []Entry { + if version == "" { + for _, sc := range cmd.subcommands { + if sc.version != "" { + version = sc.version + break + } + } + } + return []Entry{ Title( 0, @@ -863,30 +872,30 @@ func manSubcommands(cmd Cmd, conf Config) []Entry { } if hasSubcommands { - return docFullSubcommands(cmd, conf) + return docFullSubcommands(cmd, conf, 0) } - return docListSubcommands(cmd, []string{cmd.name}, 0) + return docListSubcommands(cmd, []string{cmd.name}, 0, 0) } func manEnv(cmd Cmd) []Entry { - return docEnv(cmd) + return docEnv(cmd, 0) } func manConfig(cmd Cmd, conf Config) []Entry { - return docConfig(cmd, conf) + return docConfig(cmd, conf, 0) } -func markdownTitle(cmd Cmd) []Entry { +func markdownTitle(cmd Cmd, level int) []Entry { txt := docCommandNameText(cmd, []string{cmd.name}) - return []Entry{Title(0, strings.Join(txt, " "))} + return []Entry{Title(level, strings.Join(txt, " "))} } -func markdownSynopsis(cmd Cmd) []Entry { - return docSynopsis(cmd, []string{cmd.name}, 1, markdownWrapWidth) +func markdownSynopsis(cmd Cmd, level int) []Entry { + return docSynopsis(cmd, []string{cmd.name}, level+1, markdownWrapWidth) } -func markdownDocs(cmd Cmd) []Entry { +func markdownDocs(cmd Cmd, level int) []Entry { paragraphs := docs(cmd) if len(paragraphs) == 0 { return nil @@ -896,11 +905,11 @@ func markdownDocs(cmd Cmd) []Entry { paragraphs[i] = Wrap(paragraphs[i], markdownWrapWidth) } - return append([]Entry{Title(1, "Description:")}, paragraphs...) + return append([]Entry{Title(level+1, "Description:")}, paragraphs...) } -func markdownOptions(cmd Cmd, conf Config) []Entry { - e := docOptions(cmd, conf, 1, 0, allRelevantHints) +func markdownOptions(cmd Cmd, conf Config, level int) []Entry { + e := docOptions(cmd, conf, level+1, 0, allRelevantHints) for i := 1; i < len(e); i++ { e[i] = Wrap(e[i], markdownWrapWidth) } @@ -908,7 +917,7 @@ func markdownOptions(cmd Cmd, conf Config) []Entry { return e } -func markdownSubcommands(cmd Cmd, conf Config) []Entry { +func markdownSubcommands(cmd Cmd, conf Config, level int) []Entry { var hasSubcommands bool for _, sc := range cmd.subcommands { if sc.helpFor != nil || sc.version != "" { @@ -921,9 +930,9 @@ func markdownSubcommands(cmd Cmd, conf Config) []Entry { var e []Entry if hasSubcommands { - e = docFullSubcommands(cmd, conf) + e = docFullSubcommands(cmd, conf, level) } else { - e = docListSubcommands(cmd, []string{cmd.name}, 0) + e = docListSubcommands(cmd, []string{cmd.name}, level, 0) } for i := range e { @@ -933,8 +942,8 @@ func markdownSubcommands(cmd Cmd, conf Config) []Entry { return e } -func markdownEnv(cmd Cmd) []Entry { - e := docEnv(cmd) +func markdownEnv(cmd Cmd, level int) []Entry { + e := docEnv(cmd, level) for i := range e { e[i] = Wrap(e[i], markdownWrapWidth) } @@ -942,8 +951,8 @@ func markdownEnv(cmd Cmd) []Entry { return e } -func markdownConfig(cmd Cmd, conf Config) []Entry { - e := docConfig(cmd, conf) +func markdownConfig(cmd Cmd, conf Config, level int) []Entry { + e := docConfig(cmd, conf, level) for i := range e { e[i] = Wrap(e[i], markdownWrapWidth) } @@ -977,13 +986,13 @@ func generateMan(out io.Writer, cmd Cmd, conf Config, date time.Time, version st func generateMarkdown(out io.Writer, cmd Cmd, conf Config, level int) error { var e []Entry - e = append(e, markdownTitle(cmd)...) - e = append(e, markdownSynopsis(cmd)...) - e = append(e, markdownDocs(cmd)...) - e = append(e, markdownOptions(cmd, conf)...) - e = append(e, markdownSubcommands(cmd, conf)...) - e = append(e, markdownEnv(cmd)...) - e = append(e, markdownConfig(cmd, conf)...) + e = append(e, markdownTitle(cmd, level)...) + e = append(e, markdownSynopsis(cmd, level)...) + e = append(e, markdownDocs(cmd, level)...) + e = append(e, markdownOptions(cmd, conf, level)...) + e = append(e, markdownSubcommands(cmd, conf, level)...) + e = append(e, markdownEnv(cmd, level)...) + e = append(e, markdownConfig(cmd, conf, level)...) return Markdown(out, Doc(e...)) } diff --git a/help_test.go b/help_test.go index e6a9235..dab06e1 100644 --- a/help_test.go +++ b/help_test.go @@ -257,6 +257,7 @@ Options: --bar string [*]: Bars, any number. --duration duration: Duration is another option. --foo int: Foo is an option. + --some any: Some is an option of any type. --time time: Time is the third option here. --help: Show help. @@ -285,6 +286,7 @@ Options: --bar string [*]: Bars, any number. --duration duration: Duration is another option. --foo int: Foo is an option. + --some any: Some is an option of any type. --time time: Time is the third option here. --help: Show help. @@ -381,7 +383,8 @@ Subcommands: Command("foo", func(struct { Foo bool Bar string - }) {}), + }) { + }), "f", "foo", "b", "bar", ), command: "foo help", @@ -970,6 +973,10 @@ foo .br .in 25 .ti 4 +--some any:\~\~\~\~\~\~\~\~\~\~Some is an option of any type. +.br +.in 25 +.ti 4 --time time:\~\~\~\~\~\~\~\~\~Time is the third option here. .br .in 25 @@ -1234,7 +1241,8 @@ When both the environment variable and the command line option is defined, the c impl: ShortForm(Command("foo", func(struct { Foo bool Bar int - }) {}), "f", "foo", "b", "bar"), + }) { + }), "f", "foo", "b", "bar"), command: "foo", env: "_wandgenerate=man;_wandgeneratedate=2025-12-03;_wandgenerateversion=2025-12-03-abcd123", }, @@ -1732,6 +1740,7 @@ foo - --bar string \[\*\]: Bars, any number. - --duration duration: Duration is another option. - --foo int: Foo is an option. +- --some any: Some is an option of any type. - --time time: Time is the third option here. - --config: Configuration file. - --help: Show help. diff --git a/iniparser.gen.go b/iniparser.gen.go index 27815f2..29df60f 100644 --- a/iniparser.gen.go +++ b/iniparser.gen.go @@ -619,7 +619,7 @@ func (c *context) read() bool { } token, n, err := c.reader.ReadRune() if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { if n == 0 { c.eof = true return false diff --git a/internal/tests/testconfig.ini b/internal/tests/testconfig.ini new file mode 100644 index 0000000..015a4a9 --- /dev/null +++ b/internal/tests/testconfig.ini @@ -0,0 +1 @@ +one = 42 diff --git a/internal/tests/testlib/cmd/main.go b/internal/tests/testlib/cmd/main.go new file mode 100644 index 0000000..4a2c55c --- /dev/null +++ b/internal/tests/testlib/cmd/main.go @@ -0,0 +1,17 @@ +package main + +import ( + . "code.squareroundforest.org/arpio/wand" + "code.squareroundforest.org/arpio/wand/internal/tests/testlib" +) + +func main() { + Exec( + Group( + "test", + Default(Command("foo", testlib.Foo)), + Command("bar", testlib.Bar), + Command("baz", testlib.Baz), + ), + ) +} diff --git a/internal/tests/testlib/lib.go b/internal/tests/testlib/lib.go index 565bd6d..a93d144 100644 --- a/internal/tests/testlib/lib.go +++ b/internal/tests/testlib/lib.go @@ -18,6 +18,9 @@ type Options struct { // Time is the third option here. Time time.Time + + // Some is an option of any type. + Some any } type OptionWithHelp struct { diff --git a/internal/tests/tmpdir/7uxW5Ik-qaesYEi3BWbg9Q/7uxW5Ik-qaesYEi3BWbg9Q.go b/internal/tests/tmpdir/7uxW5Ik-qaesYEi3BWbg9Q/7uxW5Ik-qaesYEi3BWbg9Q.go new file mode 100644 index 0000000..4c155ed --- /dev/null +++ b/internal/tests/tmpdir/7uxW5Ik-qaesYEi3BWbg9Q/7uxW5Ik-qaesYEi3BWbg9Q.go @@ -0,0 +1,5 @@ +package main +import "code.squareroundforest.org/arpio/wand" +func main() { +wand.Exec(func(a string) { println(a) }) +} \ No newline at end of file diff --git a/internal/tests/tmpdir/7uxW5Ik-qaesYEi3BWbg9Q/go.mod b/internal/tests/tmpdir/7uxW5Ik-qaesYEi3BWbg9Q/go.mod new file mode 100644 index 0000000..a2f9d8f --- /dev/null +++ b/internal/tests/tmpdir/7uxW5Ik-qaesYEi3BWbg9Q/go.mod @@ -0,0 +1,18 @@ +module 7uxW5Ik-qaesYEi3BWbg9Q + +go 1.25.4 + +require ( + code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 // indirect + code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 // indirect + code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 // indirect + code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 // indirect + code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f // indirect + code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 // indirect + code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect +) + +replace code.squareroundforest.org/arpio/wand => /Users/arpio/work/code/wand diff --git a/internal/tests/tmpdir/7uxW5Ik-qaesYEi3BWbg9Q/go.sum b/internal/tests/tmpdir/7uxW5Ik-qaesYEi3BWbg9Q/go.sum new file mode 100644 index 0000000..0928802 --- /dev/null +++ b/internal/tests/tmpdir/7uxW5Ik-qaesYEi3BWbg9Q/go.sum @@ -0,0 +1,20 @@ +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 h1:SIgLIawD6Vv7rAvUobpVshLshdwFEJ0NOUrWpheS088= +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5/go.mod h1:tTCmCwFABKNm3PO0Dclsp4zWhNQFTfg9+uSrgoarZFI= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 h1:bJi41U5yGQykg6jVlD2AdWiznvx3Jg7ZpzEU85syOXw= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1/go.mod h1:/3xQI36oJG8qLBxT2fSS61P5/+i1T64fTX9GHRh8XhA= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 h1:b7voJlwe0jKH568X+O7b/JTAUrHLTSKNSSL+hhV2Q/Q= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9/go.mod h1:hq+2CENEd4bVSZnOdq38FUFOJJnF3OTQRv78qMGkNlE= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 h1:JvLVMuvF2laxXkIZbHC1/0xtKyKndAwIHbIIWkHqTzc= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239/go.mod h1:ait4Fvg9o0+bq5hlxi9dAcPL5a+/sr33qsZPNpToMLY= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f h1:gomu8xTD953IkL3M528qVEuZ2z93C2I6Hr4vyIwE7kI= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f/go.mod h1:nXdFdxdI69JrkIT97f+AEE4OgplmxbgNFZC5j7gsdqs= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 h1:2aa62CYm9ld5SNoFxWzE2wUN0xjVWQ+xieoeFantdg4= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18/go.mod h1:+0G3gufMAP8SCEIrDT1D/DaVOSfjS8EwPTBs5vfxqQg= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 h1:9XKwyrmOi2upsYWyjMQOPhO6ebl7AEHSViBVu9U/2jc= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022/go.mod h1:dwEF9zEIbOxbLxytOKSuRQPKmvbhPjDCJcoXM3j8cOU= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= diff --git a/internal/tests/tmpdir/Du66PUa6l2PUdTO2P6Mz8w/Du66PUa6l2PUdTO2P6Mz8w.go b/internal/tests/tmpdir/Du66PUa6l2PUdTO2P6Mz8w/Du66PUa6l2PUdTO2P6Mz8w.go new file mode 100644 index 0000000..fcf0d59 --- /dev/null +++ b/internal/tests/tmpdir/Du66PUa6l2PUdTO2P6Mz8w/Du66PUa6l2PUdTO2P6Mz8w.go @@ -0,0 +1,6 @@ +package main +import "strings" +import "code.squareroundforest.org/arpio/wand" +func main() { +wand.Exec(strings.Split) +} \ No newline at end of file diff --git a/internal/tests/tmpdir/Du66PUa6l2PUdTO2P6Mz8w/go.mod b/internal/tests/tmpdir/Du66PUa6l2PUdTO2P6Mz8w/go.mod new file mode 100644 index 0000000..019748b --- /dev/null +++ b/internal/tests/tmpdir/Du66PUa6l2PUdTO2P6Mz8w/go.mod @@ -0,0 +1,18 @@ +module Du66PUa6l2PUdTO2P6Mz8w + +go 1.25.4 + +require ( + code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 // indirect + code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 // indirect + code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 // indirect + code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 // indirect + code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f // indirect + code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 // indirect + code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect +) + +replace code.squareroundforest.org/arpio/wand => /Users/arpio/work/code/wand diff --git a/internal/tests/tmpdir/Du66PUa6l2PUdTO2P6Mz8w/go.sum b/internal/tests/tmpdir/Du66PUa6l2PUdTO2P6Mz8w/go.sum new file mode 100644 index 0000000..0928802 --- /dev/null +++ b/internal/tests/tmpdir/Du66PUa6l2PUdTO2P6Mz8w/go.sum @@ -0,0 +1,20 @@ +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 h1:SIgLIawD6Vv7rAvUobpVshLshdwFEJ0NOUrWpheS088= +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5/go.mod h1:tTCmCwFABKNm3PO0Dclsp4zWhNQFTfg9+uSrgoarZFI= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 h1:bJi41U5yGQykg6jVlD2AdWiznvx3Jg7ZpzEU85syOXw= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1/go.mod h1:/3xQI36oJG8qLBxT2fSS61P5/+i1T64fTX9GHRh8XhA= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 h1:b7voJlwe0jKH568X+O7b/JTAUrHLTSKNSSL+hhV2Q/Q= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9/go.mod h1:hq+2CENEd4bVSZnOdq38FUFOJJnF3OTQRv78qMGkNlE= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 h1:JvLVMuvF2laxXkIZbHC1/0xtKyKndAwIHbIIWkHqTzc= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239/go.mod h1:ait4Fvg9o0+bq5hlxi9dAcPL5a+/sr33qsZPNpToMLY= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f h1:gomu8xTD953IkL3M528qVEuZ2z93C2I6Hr4vyIwE7kI= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f/go.mod h1:nXdFdxdI69JrkIT97f+AEE4OgplmxbgNFZC5j7gsdqs= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 h1:2aa62CYm9ld5SNoFxWzE2wUN0xjVWQ+xieoeFantdg4= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18/go.mod h1:+0G3gufMAP8SCEIrDT1D/DaVOSfjS8EwPTBs5vfxqQg= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 h1:9XKwyrmOi2upsYWyjMQOPhO6ebl7AEHSViBVu9U/2jc= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022/go.mod h1:dwEF9zEIbOxbLxytOKSuRQPKmvbhPjDCJcoXM3j8cOU= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= diff --git a/internal/tests/tmpdir/GBAVk0TbT71P1fBFC4wZxQ/GBAVk0TbT71P1fBFC4wZxQ.go b/internal/tests/tmpdir/GBAVk0TbT71P1fBFC4wZxQ/GBAVk0TbT71P1fBFC4wZxQ.go new file mode 100644 index 0000000..5d09b6e --- /dev/null +++ b/internal/tests/tmpdir/GBAVk0TbT71P1fBFC4wZxQ/GBAVk0TbT71P1fBFC4wZxQ.go @@ -0,0 +1,22 @@ +package main +import "io" +import "code.squareroundforest.org/arpio/wand" +func main() { +wand.Exec(func(in io.Reader) (out io.Reader) { + out := bytes.NewBuffer(nil) + buf := make([]byte, 1) + for { + n, err := in.Read(buf) + if n == 1 { + buf[0] = buf[0] * 2 + out.Write(buf) + } + + if err != nil { + return out + } + } + + return out + }) +} \ No newline at end of file diff --git a/internal/tests/tmpdir/GBAVk0TbT71P1fBFC4wZxQ/go.mod b/internal/tests/tmpdir/GBAVk0TbT71P1fBFC4wZxQ/go.mod new file mode 100644 index 0000000..5a060bb --- /dev/null +++ b/internal/tests/tmpdir/GBAVk0TbT71P1fBFC4wZxQ/go.mod @@ -0,0 +1,18 @@ +module GBAVk0TbT71P1fBFC4wZxQ + +go 1.25.4 + +require ( + code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 // indirect + code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 // indirect + code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 // indirect + code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 // indirect + code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f // indirect + code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 // indirect + code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect +) + +replace code.squareroundforest.org/arpio/wand => /Users/arpio/work/code/wand diff --git a/internal/tests/tmpdir/GBAVk0TbT71P1fBFC4wZxQ/go.sum b/internal/tests/tmpdir/GBAVk0TbT71P1fBFC4wZxQ/go.sum new file mode 100644 index 0000000..0928802 --- /dev/null +++ b/internal/tests/tmpdir/GBAVk0TbT71P1fBFC4wZxQ/go.sum @@ -0,0 +1,20 @@ +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 h1:SIgLIawD6Vv7rAvUobpVshLshdwFEJ0NOUrWpheS088= +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5/go.mod h1:tTCmCwFABKNm3PO0Dclsp4zWhNQFTfg9+uSrgoarZFI= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 h1:bJi41U5yGQykg6jVlD2AdWiznvx3Jg7ZpzEU85syOXw= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1/go.mod h1:/3xQI36oJG8qLBxT2fSS61P5/+i1T64fTX9GHRh8XhA= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 h1:b7voJlwe0jKH568X+O7b/JTAUrHLTSKNSSL+hhV2Q/Q= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9/go.mod h1:hq+2CENEd4bVSZnOdq38FUFOJJnF3OTQRv78qMGkNlE= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 h1:JvLVMuvF2laxXkIZbHC1/0xtKyKndAwIHbIIWkHqTzc= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239/go.mod h1:ait4Fvg9o0+bq5hlxi9dAcPL5a+/sr33qsZPNpToMLY= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f h1:gomu8xTD953IkL3M528qVEuZ2z93C2I6Hr4vyIwE7kI= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f/go.mod h1:nXdFdxdI69JrkIT97f+AEE4OgplmxbgNFZC5j7gsdqs= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 h1:2aa62CYm9ld5SNoFxWzE2wUN0xjVWQ+xieoeFantdg4= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18/go.mod h1:+0G3gufMAP8SCEIrDT1D/DaVOSfjS8EwPTBs5vfxqQg= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 h1:9XKwyrmOi2upsYWyjMQOPhO6ebl7AEHSViBVu9U/2jc= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022/go.mod h1:dwEF9zEIbOxbLxytOKSuRQPKmvbhPjDCJcoXM3j8cOU= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= diff --git a/internal/tests/tmpdir/Vw9o9PuLOlqrxfbxo88FwA/Vw9o9PuLOlqrxfbxo88FwA.go b/internal/tests/tmpdir/Vw9o9PuLOlqrxfbxo88FwA/Vw9o9PuLOlqrxfbxo88FwA.go new file mode 100644 index 0000000..a7b0a17 --- /dev/null +++ b/internal/tests/tmpdir/Vw9o9PuLOlqrxfbxo88FwA/Vw9o9PuLOlqrxfbxo88FwA.go @@ -0,0 +1,5 @@ +package main +import "code.squareroundforest.org/arpio/wand" +func main() { +wand.Exec(func(a any) { println(a) }) +} \ No newline at end of file diff --git a/internal/tests/tmpdir/Vw9o9PuLOlqrxfbxo88FwA/go.mod b/internal/tests/tmpdir/Vw9o9PuLOlqrxfbxo88FwA/go.mod new file mode 100644 index 0000000..69e562a --- /dev/null +++ b/internal/tests/tmpdir/Vw9o9PuLOlqrxfbxo88FwA/go.mod @@ -0,0 +1,18 @@ +module Vw9o9PuLOlqrxfbxo88FwA + +go 1.25.4 + +require ( + code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 // indirect + code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 // indirect + code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 // indirect + code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 // indirect + code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f // indirect + code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 // indirect + code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect +) + +replace code.squareroundforest.org/arpio/wand => /Users/arpio/work/code/wand diff --git a/internal/tests/tmpdir/Vw9o9PuLOlqrxfbxo88FwA/go.sum b/internal/tests/tmpdir/Vw9o9PuLOlqrxfbxo88FwA/go.sum new file mode 100644 index 0000000..0928802 --- /dev/null +++ b/internal/tests/tmpdir/Vw9o9PuLOlqrxfbxo88FwA/go.sum @@ -0,0 +1,20 @@ +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 h1:SIgLIawD6Vv7rAvUobpVshLshdwFEJ0NOUrWpheS088= +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5/go.mod h1:tTCmCwFABKNm3PO0Dclsp4zWhNQFTfg9+uSrgoarZFI= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 h1:bJi41U5yGQykg6jVlD2AdWiznvx3Jg7ZpzEU85syOXw= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1/go.mod h1:/3xQI36oJG8qLBxT2fSS61P5/+i1T64fTX9GHRh8XhA= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 h1:b7voJlwe0jKH568X+O7b/JTAUrHLTSKNSSL+hhV2Q/Q= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9/go.mod h1:hq+2CENEd4bVSZnOdq38FUFOJJnF3OTQRv78qMGkNlE= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 h1:JvLVMuvF2laxXkIZbHC1/0xtKyKndAwIHbIIWkHqTzc= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239/go.mod h1:ait4Fvg9o0+bq5hlxi9dAcPL5a+/sr33qsZPNpToMLY= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f h1:gomu8xTD953IkL3M528qVEuZ2z93C2I6Hr4vyIwE7kI= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f/go.mod h1:nXdFdxdI69JrkIT97f+AEE4OgplmxbgNFZC5j7gsdqs= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 h1:2aa62CYm9ld5SNoFxWzE2wUN0xjVWQ+xieoeFantdg4= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18/go.mod h1:+0G3gufMAP8SCEIrDT1D/DaVOSfjS8EwPTBs5vfxqQg= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 h1:9XKwyrmOi2upsYWyjMQOPhO6ebl7AEHSViBVu9U/2jc= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022/go.mod h1:dwEF9zEIbOxbLxytOKSuRQPKmvbhPjDCJcoXM3j8cOU= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= diff --git a/internal/tests/tmpdir/W0w-rWwNmthjuerTOFnMIQ/W0w-rWwNmthjuerTOFnMIQ.go b/internal/tests/tmpdir/W0w-rWwNmthjuerTOFnMIQ/W0w-rWwNmthjuerTOFnMIQ.go new file mode 100644 index 0000000..5781cc7 --- /dev/null +++ b/internal/tests/tmpdir/W0w-rWwNmthjuerTOFnMIQ/W0w-rWwNmthjuerTOFnMIQ.go @@ -0,0 +1,6 @@ +package main +import "fmt" +import "code.squareroundforest.org/arpio/wand" +func main() { +wand.Exec(func(a any) { println(a) }) +} \ No newline at end of file diff --git a/internal/tests/tmpdir/W0w-rWwNmthjuerTOFnMIQ/go.mod b/internal/tests/tmpdir/W0w-rWwNmthjuerTOFnMIQ/go.mod new file mode 100644 index 0000000..277296b --- /dev/null +++ b/internal/tests/tmpdir/W0w-rWwNmthjuerTOFnMIQ/go.mod @@ -0,0 +1,18 @@ +module W0w-rWwNmthjuerTOFnMIQ + +go 1.25.4 + +require ( + code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 // indirect + code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 // indirect + code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 // indirect + code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 // indirect + code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f // indirect + code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 // indirect + code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect +) + +replace code.squareroundforest.org/arpio/wand => /Users/arpio/work/code/wand diff --git a/internal/tests/tmpdir/W0w-rWwNmthjuerTOFnMIQ/go.sum b/internal/tests/tmpdir/W0w-rWwNmthjuerTOFnMIQ/go.sum new file mode 100644 index 0000000..0928802 --- /dev/null +++ b/internal/tests/tmpdir/W0w-rWwNmthjuerTOFnMIQ/go.sum @@ -0,0 +1,20 @@ +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 h1:SIgLIawD6Vv7rAvUobpVshLshdwFEJ0NOUrWpheS088= +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5/go.mod h1:tTCmCwFABKNm3PO0Dclsp4zWhNQFTfg9+uSrgoarZFI= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 h1:bJi41U5yGQykg6jVlD2AdWiznvx3Jg7ZpzEU85syOXw= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1/go.mod h1:/3xQI36oJG8qLBxT2fSS61P5/+i1T64fTX9GHRh8XhA= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 h1:b7voJlwe0jKH568X+O7b/JTAUrHLTSKNSSL+hhV2Q/Q= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9/go.mod h1:hq+2CENEd4bVSZnOdq38FUFOJJnF3OTQRv78qMGkNlE= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 h1:JvLVMuvF2laxXkIZbHC1/0xtKyKndAwIHbIIWkHqTzc= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239/go.mod h1:ait4Fvg9o0+bq5hlxi9dAcPL5a+/sr33qsZPNpToMLY= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f h1:gomu8xTD953IkL3M528qVEuZ2z93C2I6Hr4vyIwE7kI= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f/go.mod h1:nXdFdxdI69JrkIT97f+AEE4OgplmxbgNFZC5j7gsdqs= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 h1:2aa62CYm9ld5SNoFxWzE2wUN0xjVWQ+xieoeFantdg4= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18/go.mod h1:+0G3gufMAP8SCEIrDT1D/DaVOSfjS8EwPTBs5vfxqQg= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 h1:9XKwyrmOi2upsYWyjMQOPhO6ebl7AEHSViBVu9U/2jc= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022/go.mod h1:dwEF9zEIbOxbLxytOKSuRQPKmvbhPjDCJcoXM3j8cOU= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= diff --git a/internal/tests/tmpdir/c128RsAggPny5Yt3rXQnjA/c128RsAggPny5Yt3rXQnjA.go b/internal/tests/tmpdir/c128RsAggPny5Yt3rXQnjA/c128RsAggPny5Yt3rXQnjA.go new file mode 100644 index 0000000..48fef09 --- /dev/null +++ b/internal/tests/tmpdir/c128RsAggPny5Yt3rXQnjA/c128RsAggPny5Yt3rXQnjA.go @@ -0,0 +1,6 @@ +package main +import "fmt" +import "code.squareroundforest.org/arpio/wand" +func main() { +wand.Exec(fmt.Println) +} \ No newline at end of file diff --git a/internal/tests/tmpdir/c128RsAggPny5Yt3rXQnjA/go.mod b/internal/tests/tmpdir/c128RsAggPny5Yt3rXQnjA/go.mod new file mode 100644 index 0000000..f502585 --- /dev/null +++ b/internal/tests/tmpdir/c128RsAggPny5Yt3rXQnjA/go.mod @@ -0,0 +1,18 @@ +module c128RsAggPny5Yt3rXQnjA + +go 1.25.4 + +require ( + code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 // indirect + code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 // indirect + code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 // indirect + code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 // indirect + code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f // indirect + code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 // indirect + code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect +) + +replace code.squareroundforest.org/arpio/wand => /Users/arpio/work/code/wand diff --git a/internal/tests/tmpdir/c128RsAggPny5Yt3rXQnjA/go.sum b/internal/tests/tmpdir/c128RsAggPny5Yt3rXQnjA/go.sum new file mode 100644 index 0000000..0928802 --- /dev/null +++ b/internal/tests/tmpdir/c128RsAggPny5Yt3rXQnjA/go.sum @@ -0,0 +1,20 @@ +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 h1:SIgLIawD6Vv7rAvUobpVshLshdwFEJ0NOUrWpheS088= +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5/go.mod h1:tTCmCwFABKNm3PO0Dclsp4zWhNQFTfg9+uSrgoarZFI= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 h1:bJi41U5yGQykg6jVlD2AdWiznvx3Jg7ZpzEU85syOXw= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1/go.mod h1:/3xQI36oJG8qLBxT2fSS61P5/+i1T64fTX9GHRh8XhA= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 h1:b7voJlwe0jKH568X+O7b/JTAUrHLTSKNSSL+hhV2Q/Q= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9/go.mod h1:hq+2CENEd4bVSZnOdq38FUFOJJnF3OTQRv78qMGkNlE= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 h1:JvLVMuvF2laxXkIZbHC1/0xtKyKndAwIHbIIWkHqTzc= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239/go.mod h1:ait4Fvg9o0+bq5hlxi9dAcPL5a+/sr33qsZPNpToMLY= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f h1:gomu8xTD953IkL3M528qVEuZ2z93C2I6Hr4vyIwE7kI= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f/go.mod h1:nXdFdxdI69JrkIT97f+AEE4OgplmxbgNFZC5j7gsdqs= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 h1:2aa62CYm9ld5SNoFxWzE2wUN0xjVWQ+xieoeFantdg4= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18/go.mod h1:+0G3gufMAP8SCEIrDT1D/DaVOSfjS8EwPTBs5vfxqQg= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 h1:9XKwyrmOi2upsYWyjMQOPhO6ebl7AEHSViBVu9U/2jc= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022/go.mod h1:dwEF9zEIbOxbLxytOKSuRQPKmvbhPjDCJcoXM3j8cOU= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= diff --git a/internal/tests/tmpdir/djTBWFYLXSZapqVl11Wnpg/djTBWFYLXSZapqVl11Wnpg.go b/internal/tests/tmpdir/djTBWFYLXSZapqVl11Wnpg/djTBWFYLXSZapqVl11Wnpg.go new file mode 100644 index 0000000..dd2834f --- /dev/null +++ b/internal/tests/tmpdir/djTBWFYLXSZapqVl11Wnpg/djTBWFYLXSZapqVl11Wnpg.go @@ -0,0 +1,6 @@ +package main +import . "strings" +import "code.squareroundforest.org/arpio/wand" +func main() { +wand.Exec(Split) +} \ No newline at end of file diff --git a/internal/tests/tmpdir/djTBWFYLXSZapqVl11Wnpg/go.mod b/internal/tests/tmpdir/djTBWFYLXSZapqVl11Wnpg/go.mod new file mode 100644 index 0000000..b1281a6 --- /dev/null +++ b/internal/tests/tmpdir/djTBWFYLXSZapqVl11Wnpg/go.mod @@ -0,0 +1,18 @@ +module djTBWFYLXSZapqVl11Wnpg + +go 1.25.4 + +require ( + code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 // indirect + code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 // indirect + code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 // indirect + code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 // indirect + code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f // indirect + code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 // indirect + code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect +) + +replace code.squareroundforest.org/arpio/wand => /Users/arpio/work/code/wand diff --git a/internal/tests/tmpdir/djTBWFYLXSZapqVl11Wnpg/go.sum b/internal/tests/tmpdir/djTBWFYLXSZapqVl11Wnpg/go.sum new file mode 100644 index 0000000..0928802 --- /dev/null +++ b/internal/tests/tmpdir/djTBWFYLXSZapqVl11Wnpg/go.sum @@ -0,0 +1,20 @@ +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 h1:SIgLIawD6Vv7rAvUobpVshLshdwFEJ0NOUrWpheS088= +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5/go.mod h1:tTCmCwFABKNm3PO0Dclsp4zWhNQFTfg9+uSrgoarZFI= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 h1:bJi41U5yGQykg6jVlD2AdWiznvx3Jg7ZpzEU85syOXw= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1/go.mod h1:/3xQI36oJG8qLBxT2fSS61P5/+i1T64fTX9GHRh8XhA= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 h1:b7voJlwe0jKH568X+O7b/JTAUrHLTSKNSSL+hhV2Q/Q= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9/go.mod h1:hq+2CENEd4bVSZnOdq38FUFOJJnF3OTQRv78qMGkNlE= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 h1:JvLVMuvF2laxXkIZbHC1/0xtKyKndAwIHbIIWkHqTzc= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239/go.mod h1:ait4Fvg9o0+bq5hlxi9dAcPL5a+/sr33qsZPNpToMLY= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f h1:gomu8xTD953IkL3M528qVEuZ2z93C2I6Hr4vyIwE7kI= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f/go.mod h1:nXdFdxdI69JrkIT97f+AEE4OgplmxbgNFZC5j7gsdqs= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 h1:2aa62CYm9ld5SNoFxWzE2wUN0xjVWQ+xieoeFantdg4= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18/go.mod h1:+0G3gufMAP8SCEIrDT1D/DaVOSfjS8EwPTBs5vfxqQg= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 h1:9XKwyrmOi2upsYWyjMQOPhO6ebl7AEHSViBVu9U/2jc= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022/go.mod h1:dwEF9zEIbOxbLxytOKSuRQPKmvbhPjDCJcoXM3j8cOU= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= diff --git a/internal/tests/tmpdir/fbneVWE281vn9cQJ87O0vA/fbneVWE281vn9cQJ87O0vA.go b/internal/tests/tmpdir/fbneVWE281vn9cQJ87O0vA/fbneVWE281vn9cQJ87O0vA.go new file mode 100644 index 0000000..3b64eaa --- /dev/null +++ b/internal/tests/tmpdir/fbneVWE281vn9cQJ87O0vA/fbneVWE281vn9cQJ87O0vA.go @@ -0,0 +1,6 @@ +package main +import str "strings" +import "code.squareroundforest.org/arpio/wand" +func main() { +wand.Exec(str.Split) +} \ No newline at end of file diff --git a/internal/tests/tmpdir/fbneVWE281vn9cQJ87O0vA/go.mod b/internal/tests/tmpdir/fbneVWE281vn9cQJ87O0vA/go.mod new file mode 100644 index 0000000..113b559 --- /dev/null +++ b/internal/tests/tmpdir/fbneVWE281vn9cQJ87O0vA/go.mod @@ -0,0 +1,18 @@ +module fbneVWE281vn9cQJ87O0vA + +go 1.25.4 + +require ( + code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 // indirect + code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 // indirect + code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 // indirect + code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 // indirect + code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f // indirect + code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 // indirect + code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect +) + +replace code.squareroundforest.org/arpio/wand => /Users/arpio/work/code/wand diff --git a/internal/tests/tmpdir/fbneVWE281vn9cQJ87O0vA/go.sum b/internal/tests/tmpdir/fbneVWE281vn9cQJ87O0vA/go.sum new file mode 100644 index 0000000..0928802 --- /dev/null +++ b/internal/tests/tmpdir/fbneVWE281vn9cQJ87O0vA/go.sum @@ -0,0 +1,20 @@ +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 h1:SIgLIawD6Vv7rAvUobpVshLshdwFEJ0NOUrWpheS088= +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5/go.mod h1:tTCmCwFABKNm3PO0Dclsp4zWhNQFTfg9+uSrgoarZFI= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 h1:bJi41U5yGQykg6jVlD2AdWiznvx3Jg7ZpzEU85syOXw= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1/go.mod h1:/3xQI36oJG8qLBxT2fSS61P5/+i1T64fTX9GHRh8XhA= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 h1:b7voJlwe0jKH568X+O7b/JTAUrHLTSKNSSL+hhV2Q/Q= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9/go.mod h1:hq+2CENEd4bVSZnOdq38FUFOJJnF3OTQRv78qMGkNlE= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 h1:JvLVMuvF2laxXkIZbHC1/0xtKyKndAwIHbIIWkHqTzc= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239/go.mod h1:ait4Fvg9o0+bq5hlxi9dAcPL5a+/sr33qsZPNpToMLY= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f h1:gomu8xTD953IkL3M528qVEuZ2z93C2I6Hr4vyIwE7kI= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f/go.mod h1:nXdFdxdI69JrkIT97f+AEE4OgplmxbgNFZC5j7gsdqs= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 h1:2aa62CYm9ld5SNoFxWzE2wUN0xjVWQ+xieoeFantdg4= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18/go.mod h1:+0G3gufMAP8SCEIrDT1D/DaVOSfjS8EwPTBs5vfxqQg= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 h1:9XKwyrmOi2upsYWyjMQOPhO6ebl7AEHSViBVu9U/2jc= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022/go.mod h1:dwEF9zEIbOxbLxytOKSuRQPKmvbhPjDCJcoXM3j8cOU= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= diff --git a/internal/tests/tmpdir/k_vqGB1P94wR5O4M7XiD4A/go.mod b/internal/tests/tmpdir/k_vqGB1P94wR5O4M7XiD4A/go.mod new file mode 100644 index 0000000..92fedad --- /dev/null +++ b/internal/tests/tmpdir/k_vqGB1P94wR5O4M7XiD4A/go.mod @@ -0,0 +1,18 @@ +module k_vqGB1P94wR5O4M7XiD4A + +go 1.25.4 + +require ( + code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 // indirect + code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 // indirect + code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 // indirect + code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 // indirect + code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f // indirect + code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 // indirect + code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect +) + +replace code.squareroundforest.org/arpio/wand => /Users/arpio/work/code/wand diff --git a/internal/tests/tmpdir/k_vqGB1P94wR5O4M7XiD4A/go.sum b/internal/tests/tmpdir/k_vqGB1P94wR5O4M7XiD4A/go.sum new file mode 100644 index 0000000..0928802 --- /dev/null +++ b/internal/tests/tmpdir/k_vqGB1P94wR5O4M7XiD4A/go.sum @@ -0,0 +1,20 @@ +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 h1:SIgLIawD6Vv7rAvUobpVshLshdwFEJ0NOUrWpheS088= +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5/go.mod h1:tTCmCwFABKNm3PO0Dclsp4zWhNQFTfg9+uSrgoarZFI= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 h1:bJi41U5yGQykg6jVlD2AdWiznvx3Jg7ZpzEU85syOXw= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1/go.mod h1:/3xQI36oJG8qLBxT2fSS61P5/+i1T64fTX9GHRh8XhA= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 h1:b7voJlwe0jKH568X+O7b/JTAUrHLTSKNSSL+hhV2Q/Q= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9/go.mod h1:hq+2CENEd4bVSZnOdq38FUFOJJnF3OTQRv78qMGkNlE= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 h1:JvLVMuvF2laxXkIZbHC1/0xtKyKndAwIHbIIWkHqTzc= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239/go.mod h1:ait4Fvg9o0+bq5hlxi9dAcPL5a+/sr33qsZPNpToMLY= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f h1:gomu8xTD953IkL3M528qVEuZ2z93C2I6Hr4vyIwE7kI= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f/go.mod h1:nXdFdxdI69JrkIT97f+AEE4OgplmxbgNFZC5j7gsdqs= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 h1:2aa62CYm9ld5SNoFxWzE2wUN0xjVWQ+xieoeFantdg4= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18/go.mod h1:+0G3gufMAP8SCEIrDT1D/DaVOSfjS8EwPTBs5vfxqQg= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 h1:9XKwyrmOi2upsYWyjMQOPhO6ebl7AEHSViBVu9U/2jc= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022/go.mod h1:dwEF9zEIbOxbLxytOKSuRQPKmvbhPjDCJcoXM3j8cOU= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= diff --git a/internal/tests/tmpdir/k_vqGB1P94wR5O4M7XiD4A/k_vqGB1P94wR5O4M7XiD4A.go b/internal/tests/tmpdir/k_vqGB1P94wR5O4M7XiD4A/k_vqGB1P94wR5O4M7XiD4A.go new file mode 100644 index 0000000..1d78402 --- /dev/null +++ b/internal/tests/tmpdir/k_vqGB1P94wR5O4M7XiD4A/k_vqGB1P94wR5O4M7XiD4A.go @@ -0,0 +1,5 @@ +package main +import "code.squareroundforest.org/arpio/wand" +func main() { +wand.Exec(println) +} \ No newline at end of file diff --git a/internal/tests/tmpdir/pPXRXBwDsfnuJDBB1hbG7w/go.mod b/internal/tests/tmpdir/pPXRXBwDsfnuJDBB1hbG7w/go.mod new file mode 100644 index 0000000..0345b4d --- /dev/null +++ b/internal/tests/tmpdir/pPXRXBwDsfnuJDBB1hbG7w/go.mod @@ -0,0 +1,18 @@ +module pPXRXBwDsfnuJDBB1hbG7w + +go 1.25.4 + +require ( + code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 // indirect + code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 // indirect + code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 // indirect + code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 // indirect + code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f // indirect + code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 // indirect + code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect +) + +replace code.squareroundforest.org/arpio/wand => /Users/arpio/work/code/wand diff --git a/internal/tests/tmpdir/pPXRXBwDsfnuJDBB1hbG7w/go.sum b/internal/tests/tmpdir/pPXRXBwDsfnuJDBB1hbG7w/go.sum new file mode 100644 index 0000000..0928802 --- /dev/null +++ b/internal/tests/tmpdir/pPXRXBwDsfnuJDBB1hbG7w/go.sum @@ -0,0 +1,20 @@ +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 h1:SIgLIawD6Vv7rAvUobpVshLshdwFEJ0NOUrWpheS088= +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5/go.mod h1:tTCmCwFABKNm3PO0Dclsp4zWhNQFTfg9+uSrgoarZFI= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 h1:bJi41U5yGQykg6jVlD2AdWiznvx3Jg7ZpzEU85syOXw= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1/go.mod h1:/3xQI36oJG8qLBxT2fSS61P5/+i1T64fTX9GHRh8XhA= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 h1:b7voJlwe0jKH568X+O7b/JTAUrHLTSKNSSL+hhV2Q/Q= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9/go.mod h1:hq+2CENEd4bVSZnOdq38FUFOJJnF3OTQRv78qMGkNlE= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 h1:JvLVMuvF2laxXkIZbHC1/0xtKyKndAwIHbIIWkHqTzc= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239/go.mod h1:ait4Fvg9o0+bq5hlxi9dAcPL5a+/sr33qsZPNpToMLY= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f h1:gomu8xTD953IkL3M528qVEuZ2z93C2I6Hr4vyIwE7kI= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f/go.mod h1:nXdFdxdI69JrkIT97f+AEE4OgplmxbgNFZC5j7gsdqs= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 h1:2aa62CYm9ld5SNoFxWzE2wUN0xjVWQ+xieoeFantdg4= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18/go.mod h1:+0G3gufMAP8SCEIrDT1D/DaVOSfjS8EwPTBs5vfxqQg= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 h1:9XKwyrmOi2upsYWyjMQOPhO6ebl7AEHSViBVu9U/2jc= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022/go.mod h1:dwEF9zEIbOxbLxytOKSuRQPKmvbhPjDCJcoXM3j8cOU= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= diff --git a/internal/tests/tmpdir/pPXRXBwDsfnuJDBB1hbG7w/pPXRXBwDsfnuJDBB1hbG7w.go b/internal/tests/tmpdir/pPXRXBwDsfnuJDBB1hbG7w/pPXRXBwDsfnuJDBB1hbG7w.go new file mode 100644 index 0000000..baf1132 --- /dev/null +++ b/internal/tests/tmpdir/pPXRXBwDsfnuJDBB1hbG7w/pPXRXBwDsfnuJDBB1hbG7w.go @@ -0,0 +1,6 @@ +package main +import "fmt" +import "code.squareroundforest.org/arpio/wand" +func main() { +wand.Exec(func(a) +} \ No newline at end of file diff --git a/internal/tests/tmpdir/qo6bOwdhYFcgh80Jx-WTyg/go.mod b/internal/tests/tmpdir/qo6bOwdhYFcgh80Jx-WTyg/go.mod new file mode 100644 index 0000000..0e85ea1 --- /dev/null +++ b/internal/tests/tmpdir/qo6bOwdhYFcgh80Jx-WTyg/go.mod @@ -0,0 +1,18 @@ +module qo6bOwdhYFcgh80Jx-WTyg + +go 1.25.4 + +require ( + code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 // indirect + code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 // indirect + code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 // indirect + code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 // indirect + code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f // indirect + code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 // indirect + code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect +) + +replace code.squareroundforest.org/arpio/wand => /Users/arpio/work/code/wand diff --git a/internal/tests/tmpdir/qo6bOwdhYFcgh80Jx-WTyg/go.sum b/internal/tests/tmpdir/qo6bOwdhYFcgh80Jx-WTyg/go.sum new file mode 100644 index 0000000..0928802 --- /dev/null +++ b/internal/tests/tmpdir/qo6bOwdhYFcgh80Jx-WTyg/go.sum @@ -0,0 +1,20 @@ +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 h1:SIgLIawD6Vv7rAvUobpVshLshdwFEJ0NOUrWpheS088= +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5/go.mod h1:tTCmCwFABKNm3PO0Dclsp4zWhNQFTfg9+uSrgoarZFI= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 h1:bJi41U5yGQykg6jVlD2AdWiznvx3Jg7ZpzEU85syOXw= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1/go.mod h1:/3xQI36oJG8qLBxT2fSS61P5/+i1T64fTX9GHRh8XhA= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 h1:b7voJlwe0jKH568X+O7b/JTAUrHLTSKNSSL+hhV2Q/Q= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9/go.mod h1:hq+2CENEd4bVSZnOdq38FUFOJJnF3OTQRv78qMGkNlE= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 h1:JvLVMuvF2laxXkIZbHC1/0xtKyKndAwIHbIIWkHqTzc= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239/go.mod h1:ait4Fvg9o0+bq5hlxi9dAcPL5a+/sr33qsZPNpToMLY= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f h1:gomu8xTD953IkL3M528qVEuZ2z93C2I6Hr4vyIwE7kI= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f/go.mod h1:nXdFdxdI69JrkIT97f+AEE4OgplmxbgNFZC5j7gsdqs= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 h1:2aa62CYm9ld5SNoFxWzE2wUN0xjVWQ+xieoeFantdg4= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18/go.mod h1:+0G3gufMAP8SCEIrDT1D/DaVOSfjS8EwPTBs5vfxqQg= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 h1:9XKwyrmOi2upsYWyjMQOPhO6ebl7AEHSViBVu9U/2jc= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022/go.mod h1:dwEF9zEIbOxbLxytOKSuRQPKmvbhPjDCJcoXM3j8cOU= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= diff --git a/internal/tests/tmpdir/qo6bOwdhYFcgh80Jx-WTyg/qo6bOwdhYFcgh80Jx-WTyg.go b/internal/tests/tmpdir/qo6bOwdhYFcgh80Jx-WTyg/qo6bOwdhYFcgh80Jx-WTyg.go new file mode 100644 index 0000000..3f86cfa --- /dev/null +++ b/internal/tests/tmpdir/qo6bOwdhYFcgh80Jx-WTyg/qo6bOwdhYFcgh80Jx-WTyg.go @@ -0,0 +1,23 @@ +package main +import "bytes" +import "io" +import "code.squareroundforest.org/arpio/wand" +func main() { +wand.Exec(func(in io.Reader) (out io.Reader) { + out = bytes.NewBuffer(nil) + buf := make([]byte, 1) + for { + n, err := in.Read(buf) + if n == 1 { + buf[0] = buf[0] * 2 + out.(io.Writer).Write(buf) + } + + if err != nil { + return out + } + } + + return out + }) +} \ No newline at end of file diff --git a/internal/tests/tmpdir/wtqcAdcxZGXt7vrbvOkxAw/go.mod b/internal/tests/tmpdir/wtqcAdcxZGXt7vrbvOkxAw/go.mod new file mode 100644 index 0000000..76853ff --- /dev/null +++ b/internal/tests/tmpdir/wtqcAdcxZGXt7vrbvOkxAw/go.mod @@ -0,0 +1,18 @@ +module wtqcAdcxZGXt7vrbvOkxAw + +go 1.25.4 + +require ( + code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 // indirect + code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 // indirect + code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 // indirect + code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 // indirect + code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f // indirect + code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 // indirect + code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect +) + +replace code.squareroundforest.org/arpio/wand => /Users/arpio/work/code/wand diff --git a/internal/tests/tmpdir/wtqcAdcxZGXt7vrbvOkxAw/go.sum b/internal/tests/tmpdir/wtqcAdcxZGXt7vrbvOkxAw/go.sum new file mode 100644 index 0000000..0928802 --- /dev/null +++ b/internal/tests/tmpdir/wtqcAdcxZGXt7vrbvOkxAw/go.sum @@ -0,0 +1,20 @@ +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5 h1:SIgLIawD6Vv7rAvUobpVshLshdwFEJ0NOUrWpheS088= +code.squareroundforest.org/arpio/bind v0.0.0-20251105181644-3443251be2d5/go.mod h1:tTCmCwFABKNm3PO0Dclsp4zWhNQFTfg9+uSrgoarZFI= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1 h1:bJi41U5yGQykg6jVlD2AdWiznvx3Jg7ZpzEU85syOXw= +code.squareroundforest.org/arpio/docreflect v0.0.0-20251031192707-01c5ff18fab1/go.mod h1:/3xQI36oJG8qLBxT2fSS61P5/+i1T64fTX9GHRh8XhA= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9 h1:b7voJlwe0jKH568X+O7b/JTAUrHLTSKNSSL+hhV2Q/Q= +code.squareroundforest.org/arpio/html v0.0.0-20251103020946-e262eca50ac9/go.mod h1:hq+2CENEd4bVSZnOdq38FUFOJJnF3OTQRv78qMGkNlE= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239 h1:JvLVMuvF2laxXkIZbHC1/0xtKyKndAwIHbIIWkHqTzc= +code.squareroundforest.org/arpio/notation v0.0.0-20251101123932-5f5c05ee0239/go.mod h1:ait4Fvg9o0+bq5hlxi9dAcPL5a+/sr33qsZPNpToMLY= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f h1:gomu8xTD953IkL3M528qVEuZ2z93C2I6Hr4vyIwE7kI= +code.squareroundforest.org/arpio/textedit v0.0.0-20251207224821-c75c3965789f/go.mod h1:nXdFdxdI69JrkIT97f+AEE4OgplmxbgNFZC5j7gsdqs= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18 h1:2aa62CYm9ld5SNoFxWzE2wUN0xjVWQ+xieoeFantdg4= +code.squareroundforest.org/arpio/textfmt v0.0.0-20251207234108-fed32c8bbe18/go.mod h1:+0G3gufMAP8SCEIrDT1D/DaVOSfjS8EwPTBs5vfxqQg= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022 h1:9XKwyrmOi2upsYWyjMQOPhO6ebl7AEHSViBVu9U/2jc= +code.squareroundforest.org/arpio/wand v0.0.0-20251210193110-60acf6e82022/go.mod h1:dwEF9zEIbOxbLxytOKSuRQPKmvbhPjDCJcoXM3j8cOU= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= diff --git a/internal/tests/tmpdir/wtqcAdcxZGXt7vrbvOkxAw/wtqcAdcxZGXt7vrbvOkxAw.go b/internal/tests/tmpdir/wtqcAdcxZGXt7vrbvOkxAw/wtqcAdcxZGXt7vrbvOkxAw.go new file mode 100644 index 0000000..64ea302 --- /dev/null +++ b/internal/tests/tmpdir/wtqcAdcxZGXt7vrbvOkxAw/wtqcAdcxZGXt7vrbvOkxAw.go @@ -0,0 +1,19 @@ +package main +import "io" +import "code.squareroundforest.org/arpio/wand" +func main() { +wand.Exec(func(in io.Reader) (out io.Reader) { + buf := make([]byte, 1) + for { + n, err := in.Read(buf) + if n == 1 { + buf[0] = buf[0] * 2 + out.Write(buf) + } + + if err != nil { + return + } + } + }) +} \ No newline at end of file diff --git a/lib.go b/lib.go index 5ca6157..ffc00f9 100644 --- a/lib.go +++ b/lib.go @@ -53,7 +53,7 @@ func Args(cmd Cmd, min, max int) Cmd { func ShortForm(cmd Cmd, f ...string) Cmd { if len(f)%2 != 0 { - f = append(f, "") + f = f[:len(f)-1] } cmd.shortForms = append(cmd.shortForms, f...) diff --git a/lib_test.go b/lib_test.go index 4ef36cf..e69f088 100644 --- a/lib_test.go +++ b/lib_test.go @@ -1 +1,16 @@ package wand + +import "testing" + +func TestShortForm(t *testing.T) { + t.Run( + "undefined short form", + testExec( + testCase{ + impl: ShortForm(Command("foo", func(struct{ Foo int }) {}), "f", "foo", "b"), + command: "foo -b", + }, + "option not supported", + ), + ) +} diff --git a/reflect.go b/reflect.go index 98b093b..ee87b18 100644 --- a/reflect.go +++ b/reflect.go @@ -115,15 +115,6 @@ func isTime(t reflect.Type) bool { return t.ConvertibleTo(reflect.TypeFor[time.Time]()) } -func isDuration(t reflect.Type) bool { - if t == nil { - return false - } - - t = unpackType(t) - return t == reflect.TypeFor[time.Duration]() -} - func isStruct(t reflect.Type) bool { if t == nil { return false diff --git a/tools/exec.go b/tools/exec.go index d6dc3ad..63d0ab9 100644 --- a/tools/exec.go +++ b/tools/exec.go @@ -44,7 +44,3 @@ func execInternal(command string, args ...string) error { return nil } - -func execTransparent(command string, args ...string) error { - return execc(os.Stdin, os.Stdout, os.Stderr, command, args, nil) -} diff --git a/tools/execwand.go b/tools/execwand.go index 1ed7965..4cd062d 100644 --- a/tools/execwand.go +++ b/tools/execwand.go @@ -15,12 +15,14 @@ import ( "unicode" ) +const selfPkg = "code.squareroundforest.org/arpio/wand" + type ExecOptions struct { - NoCache bool - ClearCache bool - CacheDir string - Import []string - InlineImport []string + NoCache bool + ClearCache bool + CacheDir string + Import []string + ReplaceModule []string } func commandReader(in io.Reader) func() ([]string, error) { @@ -84,12 +86,6 @@ func commandReader(in io.Reader) func() ([]string, error) { } if escapePartial { - if escapeOne { - escapeOne = false - currentArg = append(currentArg, r) - continue - } - if r == '\\' { escapeOne = true continue @@ -140,12 +136,11 @@ func commandReader(in io.Reader) func() ([]string, error) { } } -func hash(expression string, imports, inlineImports []string) (string, error) { +func hash(expression string, imports []string) (string, error) { h := fnv.New128() h.Write([]byte(expression)) - allImports := append(imports, inlineImports...) - sort.Strings(allImports) - for _, i := range allImports { + sort.Strings(imports) + for _, i := range imports { h.Write([]byte(i)) } @@ -162,7 +157,7 @@ func hash(expression string, imports, inlineImports []string) (string, error) { return strings.TrimPrefix(buf.String(), "_"), nil } -func printGoFile(fn string, expression string, imports []string, inlineImports []string) error { +func printGoFile(fn string, expression string, imports []string) error { f, err := os.Create(fn) if err != nil { return err @@ -179,23 +174,29 @@ func printGoFile(fn string, expression string, imports []string, inlineImports [ fprintf("package main\n") for _, i := range imports { - fprintf("import \"%s\"\n", strings.Split(i, "@")[0]) + ii := strings.Split(i, "=") + p := ii[0] + if len(ii) > 1 { + p = strings.Join(ii[1:], "=") + } + + if len(ii) == 1 { + fprintf("import \"%s\"\n", strings.Split(p, "@")[0]) + } else { + fprintf("import %s \"%s\"\n", ii[0], strings.Split(p, "@")[0]) + } } - for _, i := range inlineImports { - fprintf("import . \"%s\"\n", strings.Split(i, "@")[0]) - } - - fprintf("import \"code.squareroundforest.org/arpio/wand\"\n") + fprintf("import \"%s\"\n", selfPkg) fprintf("func main() {\n") fprintf("wand.Exec(%s)\n", expression) fprintf("}") return err } -func execWand(o ExecOptions, args []string) error { +func execWand(o ExecOptions, stdin io.Reader, stdout, stderr io.Writer, args []string) error { expression, args := args[0], args[1:] - commandHash, err := hash(expression, o.Import, o.InlineImport) + commandHash, err := hash(expression, o.Import) if err != nil { return err } @@ -233,6 +234,14 @@ func execWand(o ExecOptions, args []string) error { return nil } + goReplace := func(replace string) error { + if err := execInternal("go mod edit -replace", replace); err != nil { + return fmt.Errorf("failed to get go module: %w", err) + } + + return nil + } + if err := os.Chdir(commandDir); err != nil { return fmt.Errorf("failed to switch to temporary directory: %w", err) } @@ -244,31 +253,44 @@ func execWand(o ExecOptions, args []string) error { return fmt.Errorf("failed to initialize temporary module: %w", err) } + var hasSelf bool for _, pkg := range o.Import { - if err := goGet(pkg); err != nil { + pp := strings.Split(pkg, "=") + p := pp[0] + if len(pp) > 1 { + p = strings.Join(pp[1:], "=") + } + + if err := goGet(p); err != nil { + return err + } + + if p == selfPkg { + hasSelf = true + } + } + + if !hasSelf { + if err := goGet(selfPkg); err != nil { return err } } - for _, pkg := range o.InlineImport { - if err := goGet(pkg); err != nil { + for _, replace := range o.ReplaceModule { + if err := goReplace(replace); err != nil { return err } } - - if err := goGet("code.squareroundforest.org/arpio/wand"); err != nil { - return err - } } goFile := path.Join(commandDir, fmt.Sprintf("%s.go", commandHash)) if _, err := os.Stat(goFile); err != nil { - if err := printGoFile(goFile, expression, o.Import, o.InlineImport); err != nil { + if err := printGoFile(goFile, expression, o.Import); err != nil { return fmt.Errorf("failed to create temporary go file: %w", err) } } - if err := execTransparent("go run", append([]string{commandDir}, args...)...); err != nil { + if err := execc(stdin, stdout, stderr, "go run", append([]string{commandDir}, args...), nil); err != nil { return err } @@ -281,7 +303,7 @@ func execWand(o ExecOptions, args []string) error { return nil } -func readExec(o ExecOptions, stdin io.Reader) error { +func readExec(o ExecOptions, stdin io.Reader, stdout, stderr io.Writer) error { readCommand := commandReader(stdin) for { args, err := readCommand() @@ -297,16 +319,20 @@ func readExec(o ExecOptions, stdin io.Reader) error { continue } - if err := execWand(o, args); err != nil { - fmt.Fprintln(os.Stderr, err) + if err := execWand(o, stdin, stdout, stderr, args); err != nil { + fmt.Fprintln(stderr, err) } } } -func Exec(o ExecOptions, stdin io.Reader, args ...string) error { +func execInput(o ExecOptions, stdin io.Reader, stdout, stderr io.Writer, args ...string) error { if len(args) == 0 { - return readExec(o, stdin) + return readExec(o, stdin, stdout, stderr) } - return execWand(o, args) + return execWand(o, stdin, stdout, stderr, args) +} + +func Exec(o ExecOptions, stdin io.Reader, stdout io.Writer, args ...string) error { + return execInput(o, stdin, stdout, os.Stderr, args...) } diff --git a/tools/execwand_test.go b/tools/execwand_test.go new file mode 100644 index 0000000..3fb662e --- /dev/null +++ b/tools/execwand_test.go @@ -0,0 +1,202 @@ +package tools + +import ( + "bytes" + "code.squareroundforest.org/arpio/notation" + "fmt" + "os" + "path/filepath" + "testing" +) + +func TestExec(t *testing.T) { + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + + cacheDir := filepath.Join(wd, "../internal/tests/tmpdir") + selfReplace := filepath.Join(wd, "..") + baseOpt := ExecOptions{ + ClearCache: true, + CacheDir: cacheDir, + ReplaceModule: []string{fmt.Sprintf("%s=%s", selfPkg, selfReplace)}, + } + + t.Run("stdin", func(t *testing.T) { + var stdout, stderr bytes.Buffer + in := bytes.NewBufferString("strings.Split 1,2,3 ,") + o := baseOpt + o.Import = []string{"strings"} + if err := execInput(o, in, &stdout, &stderr); err != nil { + t.Fatal(err) + } + + if stderr.String() != "" { + t.Fatal(stderr.String()) + } + + if stdout.String() != "1\n2\n3\n" { + t.Fatal(stdout.String()) + } + }) + + t.Run("stdin multiple lines", func(t *testing.T) { + var stdout, stderr bytes.Buffer + in := bytes.NewBufferString("strings.Split 1,2,3 ,\nstrings.Split 4,5,6 ,") + o := baseOpt + o.Import = []string{"strings"} + if err := execInput(o, in, &stdout, &stderr); err != nil { + t.Fatal(err) + } + + if stderr.String() != "" { + t.Fatal(stderr.String()) + } + + if stdout.String() != "1\n2\n3\n4\n5\n6\n" { + t.Fatal(stdout.String()) + } + }) + + t.Run("args", func(t *testing.T) { + var stdin, stdout, stderr bytes.Buffer + o := baseOpt + o.Import = []string{"strings"} + if err := execInput(o, &stdin, &stdout, &stderr, "strings.Split", "1,2,3", ","); err != nil { + t.Fatal(err) + } + + if stderr.String() != "" { + t.Fatal(stderr.String()) + } + + if stdout.String() != "1\n2\n3\n" { + t.Fatal(stdout.String()) + } + }) + + t.Run("inline import", func(t *testing.T) { + var stdin, stdout, stderr bytes.Buffer + o := baseOpt + o.Import = []string{".=strings"} + if err := execInput(o, &stdin, &stdout, &stderr, "Split", "1,2,3", ","); err != nil { + t.Fatal(err) + } + + if stderr.String() != "" { + t.Fatal(stderr.String()) + } + + if stdout.String() != "1\n2\n3\n" { + t.Fatal(stdout.String()) + } + }) + + t.Run("named import", func(t *testing.T) { + var stdin, stdout, stderr bytes.Buffer + o := baseOpt + o.Import = []string{"str=strings"} + if err := execInput(o, &stdin, &stdout, &stderr, "str.Split", "1,2,3", ","); err != nil { + t.Fatal(err) + } + + if stderr.String() != "" { + t.Fatal(stderr.String()) + } + + if stdout.String() != "1\n2\n3\n" { + t.Fatal(stdout.String()) + } + }) + + t.Run("io args", func(t *testing.T) { + var stdout, stderr bytes.Buffer + in := bytes.NewBuffer([]byte{0, 1, 2}) + o := baseOpt + o.Import = []string{"io", "bytes"} + expr := `func(in io.Reader) (out io.Reader) { + out = bytes.NewBuffer(nil) + buf := make([]byte, 1) + for { + n, err := in.Read(buf) + if n == 1 { + buf[0] = buf[0] * 2 + out.(io.Writer).Write(buf) + } + + if err != nil { + return out + } + } + + return out + }` + + if err := execInput(o, in, &stdout, &stderr, expr); err != nil { + t.Log(stderr.String()) + t.Fatal(err) + } + + if stderr.String() != "" { + t.Fatal(stderr.String()) + } + + if stdout.Len() != 3 || stdout.Bytes()[0] != 0 || stdout.Bytes()[1] != 2 || stdout.Bytes()[2] != 4 { + t.Fatal(notation.Sprint(stdout.Bytes())) + } + }) + + t.Run("escape", func(t *testing.T) { + t.Run("full", func(t *testing.T) { + var stdout, stderr bytes.Buffer + in := bytes.NewBufferString("'func(a string) { println(a) }' 'foo'") + if err := execInput(baseOpt, in, &stdout, &stderr); err != nil { + t.Log(stderr.String()) + t.Fatal(err) + } + + if stderr.String() != "foo\n" { + t.Fatal(stderr.String()) + } + + if stdout.String() != "" { + t.Fatal(stdout.String()) + } + }) + + t.Run("one", func(t *testing.T) { + var stdout, stderr bytes.Buffer + in := bytes.NewBufferString("'func(a string) { println(a) }' foo\\ bar") + if err := execInput(baseOpt, in, &stdout, &stderr); err != nil { + t.Log(stderr.String()) + t.Fatal(err) + } + + if stderr.String() != "foo bar\n" { + t.Fatal(stderr.String()) + } + + if stdout.String() != "" { + t.Fatal(stdout.String()) + } + }) + + t.Run("one and partial", func(t *testing.T) { + var stdout, stderr bytes.Buffer + in := bytes.NewBufferString("'func(a string) { println(a) }' \"\\'foo\\'\"") + if err := execInput(baseOpt, in, &stdout, &stderr); err != nil { + t.Log(stderr.String()) + t.Fatal(err) + } + + if stderr.String() != "'foo'\n" { + t.Fatal(stderr.String()) + } + + if stdout.String() != "" { + t.Fatal(stdout.String()) + } + }) + }) +} diff --git a/tools/lib_test.go b/tools/lib_test.go new file mode 100644 index 0000000..28db554 --- /dev/null +++ b/tools/lib_test.go @@ -0,0 +1,314 @@ +package tools_test + +import ( + "bytes" + "code.squareroundforest.org/arpio/wand/tools" + "testing" +) + +func TestDocreflect(t *testing.T) { + var b bytes.Buffer + if err := tools.Docreflect(&b, "testlib", "code.squareroundforest.org/arpio/wand/internal/tests/testlib"); err != nil { + t.Fatal(err) + } + + const expect = `/* +Generated with https://code.squareroundforest.org/arpio/docreflect +*/ + + +package testlib +import "code.squareroundforest.org/arpio/docreflect" +func init() { +docreflect.Register("code.squareroundforest.org/arpio/wand/internal/tests/testlib", "") +docreflect.Register("code.squareroundforest.org/arpio/wand/internal/tests/testlib.Bar", "\nfunc(out, a, b, c)") +docreflect.Register("code.squareroundforest.org/arpio/wand/internal/tests/testlib.Baz", "\nfunc(o)") +docreflect.Register("code.squareroundforest.org/arpio/wand/internal/tests/testlib.CustomHelp", "\nfunc(o)") +docreflect.Register("code.squareroundforest.org/arpio/wand/internal/tests/testlib.Foo", "Foo sums three numbers.\nIt prints the sum to stdout.\n\nThe input numbers can be any integer.\n\nfunc(a, b, c)") +docreflect.Register("code.squareroundforest.org/arpio/wand/internal/tests/testlib.OptionWithHelp", "") +docreflect.Register("code.squareroundforest.org/arpio/wand/internal/tests/testlib.OptionWithHelp.Help", "Custom help.\n") +docreflect.Register("code.squareroundforest.org/arpio/wand/internal/tests/testlib.Options", "") +docreflect.Register("code.squareroundforest.org/arpio/wand/internal/tests/testlib.Options.Bar", "Bars, any number.\n") +docreflect.Register("code.squareroundforest.org/arpio/wand/internal/tests/testlib.Options.Duration", "Duration is another option.\n") +docreflect.Register("code.squareroundforest.org/arpio/wand/internal/tests/testlib.Options.Foo", "Foo is an option.\n") +docreflect.Register("code.squareroundforest.org/arpio/wand/internal/tests/testlib.Options.Some", "Some is an option of any type.\n") +docreflect.Register("code.squareroundforest.org/arpio/wand/internal/tests/testlib.Options.Time", "Time is the third option here.\n") +}` + + if b.String() != expect { + t.Fatal(b.String()) + } +} + +func TestMan(t *testing.T) { + var b bytes.Buffer + if err := tools.Man( + &b, + tools.ManOptions{DateString: "2025-12-09", Version: "v0.9"}, + "../internal/tests/testlib/cmd", + ); err != nil { + t.Fatal(err) + } + + const expect = `.TH "test" 1 "December 2025" "v0.9" "User Commands" +.br +.sp 1v +.in 0 +.ti 0 +\fBName:\fR +.br +.sp 1v +.in 4 +.ti 4 +test +.br +.sp 1v +.in 0 +.ti 0 +\fBSynopsis:\fR +.br +.sp 1v +.nf + test [options]... [--] + test +.fi +.br +.sp 1v +.in 0 +.ti 0 +\fBOptions:\fR +.br +.sp 1v +.in 12 +.ti 4 +--help:\~Show help. +.br +.sp 1v +.in 0 +.ti 0 +\fBSubcommands:\fR +.br +.sp 1v +.in 0 +.ti 0 +Show help for each subcommand by calling help or --help. +.br +.sp 1v +.in 2 +.ti 2 +\fBtest foo (default)\fR +.br +.sp 1v +.in 4 +.ti 4 +\fBSynopsis:\fR +.br +.sp 1v +.nf + test foo [options]... [--] + test foo +.fi +.br +.sp 1v +.in 4 +.ti 4 +\fBOptions:\fR +.br +.sp 1v +.in 12 +.ti 4 +--help:\~Show help. +.br +.sp 1v +.in 2 +.ti 2 +\fBtest bar\fR +.br +.sp 1v +.in 4 +.ti 4 +\fBSynopsis:\fR +.br +.sp 1v +.nf + test bar [options]... [--] + test bar +.fi +.br +.sp 1v +.in 4 +.ti 4 +\fBOptions:\fR +.br +.sp 1v +.in 12 +.ti 4 +--help:\~Show help. +.br +.sp 1v +.in 2 +.ti 2 +\fBtest baz\fR +.br +.sp 1v +.in 4 +.ti 4 +\fBSynopsis:\fR +.br +.sp 1v +.nf + test baz [options]... + test baz +.fi +.br +.sp 1v +.in 4 +.ti 4 +\fBOptions:\fR +.br +.sp 1v +.in 25 +.ti 4 +--bar string [*]:\~\~\~\~ +.br +.in 25 +.ti 4 +--duration duration:\~ +.br +.in 25 +.ti 4 +--foo int:\~\~\~\~\~\~\~\~\~\~\~ +.br +.in 25 +.ti 4 +--some any:\~\~\~\~\~\~\~\~\~\~ +.br +.in 25 +.ti 4 +--time time:\~\~\~\~\~\~\~\~\~ +.br +.in 25 +.ti 4 +--help:\~\~\~\~\~\~\~\~\~\~\~\~\~\~Show help. +.br +.sp 1v +.in 0 +.ti 0 +\fBEnvironment variables:\fR +.br +.sp 1v +.in 4 +.ti 4 +Every command line option's value can also be provided as an environment variable. Environment variable names need to use snake casing like myapp_foo_bar_baz or MYAPP_FOO_BAR_BAZ, or other casing that doesn't include the '-' dash character, and they need to be prefixed with the name of the application, as in the base name of the command. +.br +.sp 1v +.in 4 +.ti 4 +When both the environment variable and the command line option is defined, the command line option overrides the environment variable. Multiple values for the same environment variable can be defined by concatenating the values with the ':' separator character. When overriding multiple values with command line options, all the environment values of the same field are dropped. +.br +.sp 1v +.in 4 +.ti 4 +\fBExample environment variable:\fR +.br +.sp 1v +.nf + TEST_FOO=42 +.fi +` + + if b.String() != expect { + t.Fatal(b.String()) + } +} + +func TestMarkdown(t *testing.T) { + var b bytes.Buffer + if err := tools.Markdown(&b, tools.MarkdownOptions{}, "../internal/tests/testlib/cmd"); err != nil { + t.Fatal(err) + } + + const expect = `# test + +## Synopsis: + +` + "```" + ` +test [options]... [--] +test +` + "```" + ` + +## Options: + +- --help: Show help. + +## Subcommands: + +Show help for each subcommand by calling \ help or \ --help. + +### test foo (default) + +#### Synopsis: + +` + "```" + ` +test foo [options]... [--] +test foo +` + "```" + ` + +#### Options: + +- --help: Show help. + +### test bar + +#### Synopsis: + +` + "```" + ` +test bar [options]... [--] +test bar +` + "```" + ` + +#### Options: + +- --help: Show help. + +### test baz + +#### Synopsis: + +` + "```" + ` +test baz [options]... +test baz +` + "```" + ` + +#### Options: + +- --bar string \[\*\]: +- --duration duration: +- --foo int: +- --some any: +- --time time: +- --help: Show help. + +## Environment variables: + +Every command line option's value can also be provided as an environment variable. Environment variable names +need to use snake casing like myapp\_foo\_bar\_baz or MYAPP\_FOO\_BAR\_BAZ, or other casing that doesn't include the +'-' dash character, and they need to be prefixed with the name of the application, as in the base name of the +command. + +When both the environment variable and the command line option is defined, the command line option overrides the +environment variable. Multiple values for the same environment variable can be defined by concatenating the +values with the ':' separator character. When overriding multiple values with command line options, all the +environment values of the same field are dropped. + +### Example environment variable: + +` + "```" + ` +TEST_FOO=42 +` + "```" + ` +` + + if b.String() != expect { + t.Fatal(b.String()) + } +}