summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.go2
-rw-r--r--runner/gnumake/make.go89
-rw-r--r--runner/gnumake/target.go43
3 files changed, 134 insertions, 0 deletions
diff --git a/main.go b/main.go
index 35acc94..26955b2 100644
--- a/main.go
+++ b/main.go
@@ -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"
+}