diff options
| -rw-r--r-- | main.go | 2 | ||||
| -rw-r--r-- | runner/gnumake/make.go | 89 | ||||
| -rw-r--r-- | runner/gnumake/target.go | 43 |
3 files changed, 134 insertions, 0 deletions
@@ -11,6 +11,7 @@ import ( "pik/menu" "pik/model" "pik/run" + "pik/runner/gnumake" "pik/runner/just" "pik/runner/python" "pik/runner/shell" @@ -25,6 +26,7 @@ var initializers = []model.HasInit{ var indexers = []model.Indexer{ pikdex.Indexer, just.Indexer, + gnumake.Indexer, } var runners = []model.Runner{ diff --git a/runner/gnumake/make.go b/runner/gnumake/make.go new file mode 100644 index 0000000..ca458bf --- /dev/null +++ b/runner/gnumake/make.go @@ -0,0 +1,89 @@ +package gnumake + +import ( + "errors" + "io/fs" + "os/exec" + "pik/identity" + "pik/model" + "pik/runner" + "regexp" + "slices" + "strings" +) + +type make struct { + path string +} + +var Indexer = &make{} + +var Makefiles = []string{ + "Makefile", + "makefile", +} + +func (m *make) Index(path string, f fs.FS, _ []model.Runner) ([]model.Target, error) { + + entries, err := fs.ReadDir(f, ".") + if err != nil { + return nil, err + } + makefile := "" + for _, e := range entries { + if !e.IsDir() && slices.Contains(Makefiles, strings.ToLower(e.Name())) { + content, err := fs.ReadFile(f, e.Name()) + if err != nil { + return nil, err + } + makefile = string(content) + break + } + } + + if makefile == "" { + return nil, nil + } + + err = m.findMake() + if err != nil { + return nil, err + } + + return ParseOutput(makefile), nil +} + +var makeRegex = regexp.MustCompile("^([a-zA-Z-]*):((.*?)# (.*))?") + +func ParseOutput(input string) []model.Target { + var targets []string + //var descriptions = make(map[string]string) + match := makeRegex.FindAllString(input, len(input)) + for _, m := range match { + targets = append(targets, m) + } + + var result []model.Target + for _, t := range targets { + result = append(result, &MakeTarget{ + BaseTarget: runner.BaseTarget{ + Identity: identity.New(t[:len(t)-1]), + }, + Name: t, + }) + } + return result +} + +var NoJustError = errors.New("no make in $PATH but source contains makefile") + +func (m *make) findMake() error { + loc, err := exec.LookPath("make") + if errors.Is(err, exec.ErrNotFound) { + return NoJustError + } else if err != nil { + return err + } + m.path = loc + return nil +} diff --git a/runner/gnumake/target.go b/runner/gnumake/target.go new file mode 100644 index 0000000..7cc2d19 --- /dev/null +++ b/runner/gnumake/target.go @@ -0,0 +1,43 @@ +package gnumake + +import ( + "os/exec" + "pik/model" + "pik/runner" +) + +type MakeTarget struct { + runner.BaseTarget + Name string + Description string +} + +func (j *MakeTarget) Create(s *model.Source) *exec.Cmd { + return exec.Command(Indexer.path, j.Identity.Full) +} + +var makeSub = []string{ + "make", +} + +func (j *MakeTarget) Sub() []string { + return makeSub +} + +func (j *MakeTarget) Label() string { + return j.Identity.Full +} + +func (j *MakeTarget) Hydrate(src *model.Source) (model.HydratedTarget, error) { + return &HydratedJustTarget{ + BaseHydration: runner.Hydrated(j), + }, nil +} + +type HydratedJustTarget struct { + runner.BaseHydration[*MakeTarget] +} + +func (h *HydratedJustTarget) Icon() string { + return "\uE673" +} |
