1
0
Fork 0
nixpl/main.go

116 lines
2.0 KiB
Go

package main
import (
"bytes"
"flag"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/fsnotify/fsnotify"
)
func main() {
fs := flag.NewFlagSet("nixpl", flag.ExitOnError)
if err := fs.Parse(os.Args[1:]); err != nil {
panic(err)
}
tmp, err := os.MkdirTemp(os.TempDir(), "nixpl-*")
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
defer os.RemoveAll(tmp)
apn := filepath.Join(tmp, "repl.nix")
fi, err := os.Create(apn)
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
defer fi.Close()
if fs.Arg(0) != "" {
content, _ := os.ReadFile(fs.Arg(0))
fi.Write(content)
fi.Sync()
}
m := newModel()
go watch(apn, m)
cmd := exec.Command(os.Getenv("EDITOR"), apn)
err = m.term.Start(cmd)
if err != nil {
panic(err)
}
for {
ev := m.s.PollEvent()
if ev == nil {
break
}
m.Update(ev)
}
}
func watch(file string, m *model) {
watcher, err := fsnotify.NewWatcher()
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
defer watcher.Close()
watcher.Add(file)
fn := func() {
content, err := os.ReadFile(file)
if err != nil {
return
}
var evalBuf bytes.Buffer
var errBuf bytes.Buffer
eval := exec.Command("nix", "eval", "--expr", string(content))
eval.Stdout = &evalBuf
eval.Stderr = &errBuf
if err := eval.Run(); err != nil {
if errBuf.Len() > 0 {
m.UpdateResult(errBuf.String())
}
return
}
result := evalBuf.String()
if _, err := exec.LookPath("alejandra"); err == nil {
var formatBuf bytes.Buffer
format := exec.Command("alejandra", "-q", "-")
format.Stdin = strings.NewReader(result)
format.Stdout = &formatBuf
if err := format.Run(); err != nil {
return
}
result = formatBuf.String()
}
m.UpdateResult(result)
}
fn()
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
if event.Has(fsnotify.Write) {
fn()
}
case _, ok := <-watcher.Errors:
if !ok {
return
}
}
}
}