From 3d46b9546e1ccf131ce4dbcbfc12f6e37fa301ea Mon Sep 17 00:00:00 2001 From: ewy Date: Mon, 1 Jun 2026 19:37:34 +0200 Subject: default to manpage view for help --- completion/completion.go | 4 +-- indexers/pikdex/meta_test.go | 8 +++--- man/data.go | 43 ------------------------------ man/help.txt | 37 -------------------------- man/man.go | 50 ----------------------------------- man/man_test.go | 2 +- man/manview/data.go | 43 ++++++++++++++++++++++++++++++ man/manview/help.txt | 37 ++++++++++++++++++++++++++ man/manview/manview.go | 36 +++++++++++++++++++++++++ man/manview/templates/pik.1.man.tmpl | 31 ++++++++++++++++++++++ man/manview/version.txt | 1 + man/templates/pik.1.man.tmpl | 31 ---------------------- man/version.txt | 1 - man/view.go | 51 ++++++++++++++++++++++++++++++++++++ modes.go | 18 +++++-------- 15 files changed, 212 insertions(+), 181 deletions(-) delete mode 100644 man/data.go delete mode 100644 man/help.txt delete mode 100644 man/man.go create mode 100644 man/manview/data.go create mode 100644 man/manview/help.txt create mode 100644 man/manview/manview.go create mode 100644 man/manview/templates/pik.1.man.tmpl create mode 100644 man/manview/version.txt delete mode 100644 man/templates/pik.1.man.tmpl delete mode 100644 man/version.txt create mode 100644 man/view.go diff --git a/completion/completion.go b/completion/completion.go index 0fbe877..6fc719f 100644 --- a/completion/completion.go +++ b/completion/completion.go @@ -54,7 +54,7 @@ func Add(shell string) *spool.ExitCode { return &spool.CompletionFailure } successMessage(shell, f) - return nil + return &spool.Success } func successMessage(shell string, file string) { @@ -65,5 +65,5 @@ func successMessage(shell string, file string) { // because it is baked in with the program it should always be version-appropriate func Echo() *spool.ExitCode { _, _ = spool.Print("%s", completionCode) - return nil + return &spool.Success } diff --git a/indexers/pikdex/meta_test.go b/indexers/pikdex/meta_test.go index e04815f..8980d8c 100644 --- a/indexers/pikdex/meta_test.go +++ b/indexers/pikdex/meta_test.go @@ -11,7 +11,7 @@ func TestContentLines(t *testing.T) { in := `asdf hjkl` result := contentLines(in) - assert.Equal(t, "asdf", "hjkl", result) + assert.Equal(t, []string{"asdf", "hjkl"}, result) } func TestContentLines_EmptyLine(t *testing.T) { @@ -19,13 +19,13 @@ func TestContentLines_EmptyLine(t *testing.T) { hjkl` result := contentLines(in) - assert.Equal(t, "asdf", "hjkl", result) + assert.Equal(t, []string{"asdf", "hjkl"}, result) } func TestContentLines_Empty(t *testing.T) { in := `` result := contentLines(in) - assert.Equal(t, nil, result) + assert.Len(t, result, 0) } func TestContentLines_Comment(t *testing.T) { @@ -35,5 +35,5 @@ asdf # iuyyiuoui hjkl` result := contentLines(in) - assert.Equal(t, "asdf", "hjkl", result) + assert.Equal(t, []string{"asdf", "hjkl"}, result) } diff --git a/man/data.go b/man/data.go deleted file mode 100644 index 322da8f..0000000 --- a/man/data.go +++ /dev/null @@ -1,43 +0,0 @@ -package main - -import ( - _ "embed" - _ "github.com/ewy1/pik/flags" - "github.com/ewy1/pik/spool" - "github.com/spf13/pflag" - "runtime" - "runtime/debug" - "time" -) - -//go:embed version.txt -var version string - -type ManData struct { - Flags []pflag.Flag - Now string - Revision string - Runtime string - Version string - ExitCodes map[int]*spool.ExitCode -} - -func NewData() ManData { - var flags []pflag.Flag - pflag.Parse() - pflag.VisitAll(func(flag *pflag.Flag) { - flags = append(flags, *flag) - }) - info, ok := debug.ReadBuildInfo() - if !ok { - _, _ = spool.Panic(spool.NoDebugInfo, "could not read debug info\n") - } - return ManData{ - Flags: flags, - Now: time.Now().Format(time.DateTime), - Runtime: runtime.Version(), - Version: version, - Revision: info.Main.Version, - ExitCodes: spool.CodeMap, - } -} diff --git a/man/help.txt b/man/help.txt deleted file mode 100644 index 8c7e943..0000000 --- a/man/help.txt +++ /dev/null @@ -1,37 +0,0 @@ -Usage: pik [OPTION]... [SOURCE] [TARGET] [ARG]... - -This help content is being replaced with manual pages. To view them, try `man pik`. - -If no arguments are provided, the TUI will open. - -Otherwise, pik will attempt to run the $TARGET script in $SOURCE. - -OPTIONS: - --help - print this information - -a, --all - in addition to crawling, also load all cached sources - -h, --here - run in the current working directory instead of the source folder - -@, --at [LOCATION] - run at $LOCATION instead of the source folder - -s, --single - skip triggers (pre, post, final targets) - -d, --dry - instead of running targets, echo their command - -r, --root - prefix target command with sudo - -y, --yes - assume yes for yes/no prompts - --env [ENVTYPE] [--env [OTHER]]... - load environment files that look like they belong to this category - -v, --version - print pik version and exit - -l, --list - list all available sources and targets instead of doing anything interactive - -i, -inline - disable TUI alt screen - --edit - open the target in $EDITOR instead of running it - --install-completion - install completion in your shell rc file (bash or zsh currently supported) diff --git a/man/man.go b/man/man.go deleted file mode 100644 index 49018ed..0000000 --- a/man/man.go +++ /dev/null @@ -1,50 +0,0 @@ -package main - -import ( - "embed" - "github.com/ewy1/pik/spool" - "github.com/spf13/pflag" - "os" - "path/filepath" - "strings" - "text/template" -) - -//go:embed templates -var templates embed.FS - -var ManOutput = pflag.String(manFlagName, "out", "directory to write man pages to (gets created)") - -const manFlagName = "man-output" -const templateDir = "templates" -const manExtension = ".man" -const templateExtension = ".tmpl" - -func main() { - pflag.Parse() - tmpl, err := template.ParseFS(templates, filepath.Join(templateDir, "*")) - if err != nil { - _, _ = spool.Panic(spool.ManFailure, "%v\n", err) - return - } - err = os.MkdirAll(*ManOutput, os.ModePerm) - if err != nil { - _, _ = spool.Panic(spool.ManFailure, "%v\n", err) - } - d := NewData() - for _, t := range tmpl.Templates() { - if !strings.HasSuffix(t.Name(), manExtension+templateExtension) { - continue - } - - resultFile, err := os.OpenFile(filepath.Join(*ManOutput, strings.TrimSuffix(strings.TrimSuffix(t.Name(), templateExtension), manExtension)), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600) - if err != nil { - _, _ = spool.Panic(spool.ManFailure, "%v\n", err) - } - - err = t.Execute(resultFile, d) - if err != nil { - _, _ = spool.Panic(spool.ManFailure, "%v\n", err) - } - } -} diff --git a/man/man_test.go b/man/man_test.go index 4b48c0f..7643677 100644 --- a/man/man_test.go +++ b/man/man_test.go @@ -14,5 +14,5 @@ func TestMan(t *testing.T) { err := pflag.Set(manFlagName, d) assert.NoError(t, err) assert.NotPanics(t, main) - assert.FileExists(t, filepath.Join(d, "pik.1.man")) + assert.FileExists(t, filepath.Join(d, "pik.1")) } diff --git a/man/manview/data.go b/man/manview/data.go new file mode 100644 index 0000000..7e42fcc --- /dev/null +++ b/man/manview/data.go @@ -0,0 +1,43 @@ +package manview + +import ( + _ "embed" + _ "github.com/ewy1/pik/flags" + "github.com/ewy1/pik/spool" + "github.com/spf13/pflag" + "runtime" + "runtime/debug" + "time" +) + +//go:embed version.txt +var version string + +type ManData struct { + Flags []pflag.Flag + Now string + Revision string + Runtime string + Version string + ExitCodes map[int]*spool.ExitCode +} + +func NewData() ManData { + var flags []pflag.Flag + pflag.Parse() + pflag.VisitAll(func(flag *pflag.Flag) { + flags = append(flags, *flag) + }) + info, ok := debug.ReadBuildInfo() + if !ok { + _, _ = spool.Panic(spool.NoDebugInfo, "could not read debug info\n") + } + return ManData{ + Flags: flags, + Now: time.Now().Format(time.DateTime), + Runtime: runtime.Version(), + Version: version, + Revision: info.Main.Version, + ExitCodes: spool.CodeMap, + } +} diff --git a/man/manview/help.txt b/man/manview/help.txt new file mode 100644 index 0000000..8c7e943 --- /dev/null +++ b/man/manview/help.txt @@ -0,0 +1,37 @@ +Usage: pik [OPTION]... [SOURCE] [TARGET] [ARG]... + +This help content is being replaced with manual pages. To view them, try `man pik`. + +If no arguments are provided, the TUI will open. + +Otherwise, pik will attempt to run the $TARGET script in $SOURCE. + +OPTIONS: + --help + print this information + -a, --all + in addition to crawling, also load all cached sources + -h, --here + run in the current working directory instead of the source folder + -@, --at [LOCATION] + run at $LOCATION instead of the source folder + -s, --single + skip triggers (pre, post, final targets) + -d, --dry + instead of running targets, echo their command + -r, --root + prefix target command with sudo + -y, --yes + assume yes for yes/no prompts + --env [ENVTYPE] [--env [OTHER]]... + load environment files that look like they belong to this category + -v, --version + print pik version and exit + -l, --list + list all available sources and targets instead of doing anything interactive + -i, -inline + disable TUI alt screen + --edit + open the target in $EDITOR instead of running it + --install-completion + install completion in your shell rc file (bash or zsh currently supported) diff --git a/man/manview/manview.go b/man/manview/manview.go new file mode 100644 index 0000000..777f2cd --- /dev/null +++ b/man/manview/manview.go @@ -0,0 +1,36 @@ +package manview + +import ( + "embed" + _ "embed" + "github.com/ewy1/pik/spool" + "os" + "os/exec" + "strings" + "text/template" +) + +//go:embed templates +var pageTemplates embed.FS + +var page = template.Must(template.ParseFS(pageTemplates, "templates/*")) + +func View(fallback string) error { + man, manErr := exec.LookPath("man") + if manErr != nil { + _, err := spool.Print("%v\n", fallback) + return err + } else { + t := &strings.Builder{} + err := page.Execute(t, NewData()) + if err != nil { + return err + } + reader := strings.NewReader(t.String()) + cmd := exec.Command(man, "-l", "-") + cmd.Stdin = reader + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() + } +} diff --git a/man/manview/templates/pik.1.man.tmpl b/man/manview/templates/pik.1.man.tmpl new file mode 100644 index 0000000..53f1cfd --- /dev/null +++ b/man/manview/templates/pik.1.man.tmpl @@ -0,0 +1,31 @@ +{{- /*gotype: github.com/ewy1/pik/man.ManData*/ -}} +.TH PIK 1 {{.Version}} {{.Runtime}} +.sh NAME +pik \- file based task runner +.SH SYNOPSIS +.B pik +[\fIOPTION\fR]... [[\fISOURCE\fR] [\fITARGET\fR]] [\fIARG\fR]... +.SH DESCRIPTION +.B pik +executes scripts from the .pik folder or external runners. +.SH EXAMPLES +Given a .pik folder in your current working directory containing "script.sh", calling +.B pik script +will start that script. +.PP To start a script from another location, pass that as the SOURCE before the TARGET. +Example: +.B pik project build +will start ../../.pik/build.py if it exists. +.SH OPTIONS +{{ range .Flags -}} +.TP +.BR \-\-{{.Name }} {{ if .Shorthand }}, \-{{ .Shorthand }}{{ end }} = {{ .Value.Type }} {{ if .DefValue }} ({{.DefValue}}) {{- end }} +{{ .Usage }} +{{ end }} +.SH EXIT CODES +If the target runs and returns a non-zero error code, we pass that forward instead. +{{ range .ExitCodes -}} +.TP +.BR {{ .Value }} +{{ .Message }} +{{ end }} \ No newline at end of file diff --git a/man/manview/version.txt b/man/manview/version.txt new file mode 100644 index 0000000..3b2e7a0 --- /dev/null +++ b/man/manview/version.txt @@ -0,0 +1 @@ +0.0.0-dev \ No newline at end of file diff --git a/man/templates/pik.1.man.tmpl b/man/templates/pik.1.man.tmpl deleted file mode 100644 index 53f1cfd..0000000 --- a/man/templates/pik.1.man.tmpl +++ /dev/null @@ -1,31 +0,0 @@ -{{- /*gotype: github.com/ewy1/pik/man.ManData*/ -}} -.TH PIK 1 {{.Version}} {{.Runtime}} -.sh NAME -pik \- file based task runner -.SH SYNOPSIS -.B pik -[\fIOPTION\fR]... [[\fISOURCE\fR] [\fITARGET\fR]] [\fIARG\fR]... -.SH DESCRIPTION -.B pik -executes scripts from the .pik folder or external runners. -.SH EXAMPLES -Given a .pik folder in your current working directory containing "script.sh", calling -.B pik script -will start that script. -.PP To start a script from another location, pass that as the SOURCE before the TARGET. -Example: -.B pik project build -will start ../../.pik/build.py if it exists. -.SH OPTIONS -{{ range .Flags -}} -.TP -.BR \-\-{{.Name }} {{ if .Shorthand }}, \-{{ .Shorthand }}{{ end }} = {{ .Value.Type }} {{ if .DefValue }} ({{.DefValue}}) {{- end }} -{{ .Usage }} -{{ end }} -.SH EXIT CODES -If the target runs and returns a non-zero error code, we pass that forward instead. -{{ range .ExitCodes -}} -.TP -.BR {{ .Value }} -{{ .Message }} -{{ end }} \ No newline at end of file diff --git a/man/version.txt b/man/version.txt deleted file mode 100644 index 3b2e7a0..0000000 --- a/man/version.txt +++ /dev/null @@ -1 +0,0 @@ -0.0.0-dev \ No newline at end of file diff --git a/man/view.go b/man/view.go new file mode 100644 index 0000000..bb4aac4 --- /dev/null +++ b/man/view.go @@ -0,0 +1,51 @@ +package main + +import ( + "embed" + "github.com/ewy1/pik/man/manview" + "github.com/ewy1/pik/spool" + "github.com/spf13/pflag" + "os" + "path/filepath" + "strings" + "text/template" +) + +//go:embed manview/templates +var templates embed.FS + +var ManOutput = pflag.String(manFlagName, "out", "directory to write man pages to (gets created)") + +const manFlagName = "man-output" +const templateDir = "templates" +const manExtension = ".man" +const templateExtension = ".tmpl" + +func main() { + pflag.Parse() + tmpl, err := template.ParseFS(templates, "*/*/*.tmpl") + if err != nil { + _, _ = spool.Panic(spool.ManFailure, "%v\n", err) + return + } + err = os.MkdirAll(*ManOutput, os.ModePerm) + if err != nil { + _, _ = spool.Panic(spool.ManFailure, "%v\n", err) + } + d := manview.NewData() + for _, t := range tmpl.Templates() { + if !strings.HasSuffix(t.Name(), manExtension+templateExtension) { + continue + } + + resultFile, err := os.OpenFile(filepath.Join(*ManOutput, strings.TrimSuffix(strings.TrimSuffix(t.Name(), templateExtension), manExtension)), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600) + if err != nil { + _, _ = spool.Panic(spool.ManFailure, "%v\n", err) + } + + err = t.Execute(resultFile, d) + if err != nil { + _, _ = spool.Panic(spool.ManFailure, "%v\n", err) + } + } +} diff --git a/modes.go b/modes.go index b8da9b0..ec0545f 100644 --- a/modes.go +++ b/modes.go @@ -2,9 +2,9 @@ package main import ( _ "embed" - "errors" "github.com/ewy1/pik/completion" "github.com/ewy1/pik/flags" + "github.com/ewy1/pik/man/manview" "github.com/ewy1/pik/model" "github.com/ewy1/pik/paths" "github.com/ewy1/pik/run" @@ -18,14 +18,10 @@ import ( // ModeMap maps flags to specific operation modes type ModeMap[T any] map[*bool]T -// Continue can be returned as an error to continue program flow -var Continue = errors.New("not an error; continue flow") -var Success = errors.New("not an error; finished operations") - -//go:embed man/help.txt +//go:embed man/manview/help.txt var help string -//go:embed man/version.txt +//go:embed man/manview/version.txt var version string // Traverse checks the entries of the map. If any flags are set on, @@ -55,8 +51,8 @@ var uninitializedModes = ModeMap[func() *spool.ExitCode]{ return completion.Echo() }, flags.Help: func() *spool.ExitCode { - _, _ = spool.Print("%s\n", help) - return nil + _ = manview.View(help) + return &spool.Success }, } @@ -74,7 +70,7 @@ var statelessModes = ModeMap[func() *spool.ExitCode]{ flags.Profile: func() *spool.ExitCode { fd, err := os.Create("pik-profile.out") if err != nil { - return &spool.FatalWriteFailure + return &spool.ProfilingFailure } runtime.SetCPUProfileRate(1000) err = pprof.StartCPUProfile(profileFd) @@ -86,8 +82,6 @@ var statelessModes = ModeMap[func() *spool.ExitCode]{ }, } -var NoTargetsError = errors.New("no targets or sources to list") - // statefulModes are program modes which require a built state to be executed var statefulModes = ModeMap[func(st *model.State) *spool.ExitCode]{ flags.List: func(st *model.State) *spool.ExitCode { -- cgit v1.3.1