package main import ( "bufio" "fmt" "io" "log" "os/exec" ) // 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() { sc := bufio.NewScanner(r.out) sc.Split(bufio.ScanLines) for sc.Scan() { l := sc.Text() if l != "" && l != "\n" { r.Chan <- l } } if sc.Err() != nil { log.Println("pajen: output read error: %s", sc.Err()) } }