package main import ( "fmt" "io" "log" "os/exec" "strings" ) // Pajen represents an instance of the pajen.pl script running in infinite // generation mode. type Pajen struct { Chan chan string proc *exec.Cmd out io.ReadCloser } // NewPajen starts the pajen script at the path given. func NewPajen(path string) (*Pajen, error) { p := new(Pajen) p.proc = exec.Command("/usr/bin/perl", path, "-i") p.proc.Stdin = p pi, err := p.proc.StdoutPipe() if err != nil { return nil, fmt.Errorf("pajen: pipe pajen.pl: %w", err) } p.out = pi p.proc.Stderr = p.proc.Stdout p.Chan = make(chan string) if err := p.proc.Start(); err != nil { return nil, fmt.Errorf("pajen: start pajen.pl: %w", err) } go p.run() return p, nil } // Read feeds constant newlines to the program. func (r *Pajen) Read(b []byte) (int, error) { if len(b) < 1 { return 0, nil } return copy(b, []byte("\n")), nil } func (r *Pajen) run() { buf := make([]byte, 255) for { _, err := r.out.Read(buf) if err != nil { log.Println("pajen read error:", err) return } wk := string(buf) lines := strings.Split(wk, "\n") for _, l := range lines { if l != "" && l != "\n" { r.Chan <- l } } } }