diff options
| -rw-r--r-- | README.md | 4 | ||||
| -rw-r--r-- | indexers/pikdex/index.go | 4 | ||||
| -rw-r--r-- | indexers/pikdex/meta.go | 33 | ||||
| -rw-r--r-- | man/manview/data.go | 6 | ||||
| -rw-r--r-- | man/manview/manview.go | 3 | ||||
| -rw-r--r-- | man/manview/templates/pik.1.man.tmpl | 31 | ||||
| -rw-r--r-- | model/tags.go | 42 | ||||
| -rw-r--r-- | run/run.go | 2 | ||||
| -rw-r--r-- | web/index.html | 6 |
9 files changed, 87 insertions, 44 deletions
@@ -82,6 +82,7 @@ pik reads the first comment line from your targets and informs you in the tui! * create any kind of target: high-level support for shell and python, and arbitrary shells with the shebang. * tab completion * currently bring-your-own integrations: `pik --completion` echoes bash completion logic +* linking sources together by `.include` and `.wants` files ### tui * tui for viewing and running targets @@ -113,9 +114,8 @@ attach to these features. * adding descriptions to external targets * expand tui: * support for categories and ordering of targets through the `.order` file - * more hotkeys (filter jumping, toggle all, etc.) + * more hotkeys (toggle all, etc.) * git pre-commit and pre-push triggers -* linking sources together by `.include` and `.wants` files ## development diff --git a/indexers/pikdex/index.go b/indexers/pikdex/index.go index 1979e4d..4dd1d36 100644 --- a/indexers/pikdex/index.go +++ b/indexers/pikdex/index.go @@ -73,10 +73,10 @@ func (u *pikdex) Index(absPath string, f fs.FS, runners []model.Runner) ([]model content, err := os.ReadFile(expectedLocation) if err != nil { - spool.Warn("%v\n", err) + _, _ = spool.Warn("%v\n", err) continue } - applier(mod, string(content)) + applier.MetaSetter(mod, string(content)) } } diff --git a/indexers/pikdex/meta.go b/indexers/pikdex/meta.go index 777df51..3eb182f 100644 --- a/indexers/pikdex/meta.go +++ b/indexers/pikdex/meta.go @@ -9,33 +9,38 @@ import ( type MetaSetter func(s *model.SourceData, content string) -var MetaFiles = map[string]MetaSetter{ - ".want": func(s *model.SourceData, content string) { +type MetaFile struct { + MetaSetter + Description string +} + +var MetaFiles = map[string]*MetaFile{ + ".want": {MetaSetter: func(s *model.SourceData, content string) { s.Wants = append(s.Wants, contentLines(content)...) - }, - ".wants": func(s *model.SourceData, content string) { + }, Description: "want[s] adds external sources to your pik state. Currently only local paths are supported, one per line. For example, including '../web' will ensure that folder will be included and callable in the pik state without having to provide the --all flag."}, + ".wants": {MetaSetter: func(s *model.SourceData, content string) { s.Wants = append(s.Wants, contentLines(content)...) - }, - ".include": func(s *model.SourceData, content string) { + }}, + ".include": {MetaSetter: func(s *model.SourceData, content string) { s.Includes = append(s.Includes, contentLines(content)...) - }, - ".includes": func(s *model.SourceData, content string) { + }, Description: "include[s] adds items from external sources to this pik source. For example, adding '../shared' will add all targets from there to this source. Triggers from the included source will work, and all targets will be ran as if they were part of the including source."}, + ".includes": {MetaSetter: func(s *model.SourceData, content string) { s.Includes = append(s.Includes, contentLines(content)...) - }, - ".alias": func(s *model.SourceData, content string) { + }}, + ".alias": {MetaSetter: func(s *model.SourceData, content string) { s.Aliases = contentLines(content) - }, - ".icon": func(s *model.SourceData, content string) { + }, Description: "alias can contain multiple lines with alternate names for this source. The first non-comment line will be used as the display name. You can use this for, for example, abbreviations."}, + ".icon": {MetaSetter: func(s *model.SourceData, content string) { lines := contentLines(content) if len(lines) == 0 { return } - icon := lines[0] + icon := string([]rune(lines[0])[:2]) desiredWidth := lipgloss.Width(icon) diff := desiredWidth - len([]rune(icon)) icon += strings.Repeat(" ", diff) s.Icon = icon - }, + }, Description: "icon can contain unicode symbols representing your source. It will be used in the TUI. It will be cropped to maximum two symbols and padded if shorter."}, } func contentLines(input string) []string { diff --git a/man/manview/data.go b/man/manview/data.go index 8c21ffd..b59c78f 100644 --- a/man/manview/data.go +++ b/man/manview/data.go @@ -3,6 +3,8 @@ package manview import ( _ "embed" _ "git.sr.ht/~ewy/pik/flags" + "git.sr.ht/~ewy/pik/indexers/pikdex" + "git.sr.ht/~ewy/pik/model" "git.sr.ht/~ewy/pik/spool" "github.com/spf13/pflag" "runtime" @@ -20,6 +22,8 @@ type ManData struct { Runtime string Version string ExitCodes map[int]*spool.ExitCode + MetaFiles map[string]*pikdex.MetaFile + TagMap map[string]*model.Tag } func NewData() ManData { @@ -39,5 +43,7 @@ func NewData() ManData { Version: version, Revision: info.Main.Version, ExitCodes: spool.CodeMap, + MetaFiles: pikdex.MetaFiles, + TagMap: model.TagMap, } } diff --git a/man/manview/manview.go b/man/manview/manview.go index 8dd7edd..6d8bfc3 100644 --- a/man/manview/manview.go +++ b/man/manview/manview.go @@ -22,7 +22,8 @@ func View(fallback string) error { return err } else { t := &strings.Builder{} - err := page.Execute(t, NewData()) + d := NewData() + err := page.Execute(t, d) if err != nil { return err } diff --git a/man/manview/templates/pik.1.man.tmpl b/man/manview/templates/pik.1.man.tmpl index 53f1cfd..e4361b0 100644 --- a/man/manview/templates/pik.1.man.tmpl +++ b/man/manview/templates/pik.1.man.tmpl @@ -1,4 +1,4 @@ -{{- /*gotype: github.com/ewy1/pik/man.ManData*/ -}} +{{- /*gotype: git.sr.ht/~ewy/pik/man/manview.ManData*/ -}} .TH PIK 1 {{.Version}} {{.Runtime}} .sh NAME pik \- file based task runner @@ -9,21 +9,46 @@ pik \- file based task runner .B pik executes scripts from the .pik folder or external runners. .SH EXAMPLES +.PP +Invoke +.B pik +without arguments to open the tui. +.PP 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. +from \fI/project/src/dir\fR (and similar paths) +will start \fI/project/.pik/build.py\fR if it exists. .SH OPTIONS {{ range .Flags -}} .TP .BR \-\-{{.Name }} {{ if .Shorthand }}, \-{{ .Shorthand }}{{ end }} = {{ .Value.Type }} {{ if .DefValue }} ({{.DefValue}}) {{- end }} {{ .Usage }} {{ end }} +.SH TARGET CONFIGURATION +Targets can be configured with tags. Tags are put in filenames, and should have a \. before and after the tag. +.PP +.B EXAMPLE: +test.here.single.sh has the 'here' and 'single' tag. +{{ range $t, $v := .TagMap }} +.TP +.BR {{ $t}} +{{ $v.Description }} +{{ end }} +.SH SOURCE CONFIGURATION +Most source configuration files can contain multiple lines, including blank lines. "#" and "//" will be interpreted as comments. +{{ range $f, $v := .MetaFiles -}} +{{- if $v.Description }} +.TP +.BR .pik/{{$f}} +{{ $v.Description }} +{{- end -}} +{{- end}} .SH EXIT CODES -If the target runs and returns a non-zero error code, we pass that forward instead. +If the target runs and returns a non-zero error code, we pass that back to the user instead. {{ range .ExitCodes -}} .TP .BR {{ .Value }} diff --git a/model/tags.go b/model/tags.go index a34f555..9c5035d 100644 --- a/model/tags.go +++ b/model/tags.go @@ -6,41 +6,47 @@ import ( ) // Tag is some text which is contained in a filename which triggers pik functionality -type Tag *string +type Tag struct { + Name string + Description string +} type TagAction func(src *Source) // New creates a new tag and registers it in the subsystems -func New(input string) Tag { - result := &input - TagMap[input] = result - TagList = append(TagList, result) - return result +func New(input string, description string) *Tag { + t := &Tag{ + Name: input, + Description: description, + } + TagMap[input] = t + TagList = append(TagList, t) + return t } var ( // Here will force the target to run in the current directory instead of the source directory - Here = New("here") + Here = New("here", "run target in the currrent working directory instead of the source root. Same as invoking with `pik --here`.") // Pre turns the target into a trigger, causing it to be triggered before another target gets ran - Pre = New("pre") + Pre = New("pre", "in non-single mode, run this target before the actually invoked target (this one must succeed)") // Post turns the target into a trigger, causing it to be triggered after another target gets ran and exits succesfully - Post = New("post") + Post = New("post", "in non-single mode, run this target after the actually invoked target (if it succeeded)") // Final turns the target into a trigger, causing it to be triggered after another target gets ran - Final = New("final") + Final = New("final", "in non-single mode, run this target after the actually invoked target regardless of failure") // Hidden means the target is not visible in the menu - Hidden = New("hidden") + Hidden = New("hidden", "do not show this target in the TUI. Still invokable through the command line.") // Single means this target will not use any triggers - Single = New("single") + Single = New("single", "do not run any triggers (like pre, post, and final). Same as invoking with `pik --single`.") // Override means this should be selected instead of a non-override target, if possible - Override = New("override") + Override = New("override", "the .override tag will make this target get selected over other targets with the same name. Use this when your machine needs a custom workflow. It is discouraged to check these into version control, as everyone will receive your override.") ) -var TagList []Tag +var TagList []*Tag -var TagMap = map[string]Tag{} +var TagMap = map[string]*Tag{} -type Tags []Tag +type Tags []*Tag -func (t Tags) AnyOf(expected ...Tag) bool { +func (t Tags) AnyOf(expected ...*Tag) bool { if len(expected) > 1 && len(t) == 0 { return false } @@ -55,7 +61,7 @@ func (t Tags) AnyOf(expected ...Tag) bool { return false } -func (t Tags) Has(expected Tag) bool { +func (t Tags) Has(expected *Tag) bool { return slices.Contains(t, expected) } @@ -57,7 +57,7 @@ func Final(source *model.Source, target model.Target) error { // ExecWithTrigger loops through a model.Source and runs targets if they match the expected model.Tag // triggers only run if their subdirectory is "in tree" -func ExecWithTrigger(source *model.Source, target model.Target, tag model.Tag) error { +func ExecWithTrigger(source *model.Source, target model.Target, tag *model.Tag) error { for _, t := range source.Targets { if t.Tags().Has(tag) { triggerSub := t.Sub() diff --git a/web/index.html b/web/index.html index 1dd9bc9..273d93d 100644 --- a/web/index.html +++ b/web/index.html @@ -56,7 +56,7 @@ <main> <section> <img src="https://uwu.ewy.one/satty-20260502-18:45:46.png" alt="screenshot of the pik terminal interface" style="margin-top: -8px;"/> - <small>these assets were all created during development and might look different</small> + <small>these assets were all created during ongoing development</small> </section> <section class="important"> <p> @@ -77,7 +77,7 @@ </section> <section> <code> - go install github.com/ewy1/pik@latest + go install https://git.sr.ht/~ewy/pik@latest </code> </section> <section class="important links"> @@ -86,7 +86,7 @@ <a href="https://git.ewy.one/">Repository</a> </li> <li> - <a href="https://github.com/ewy1/pik">Github mirror</a> + <a href="https://git.sr.ht/~ewy/pik">Sourcehut mirror</a> </li> <li> <a href="https://mepik.dev/coverage.html">Test coverage</a> |
