116 lines
2.0 KiB
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
|
|
}
|
|
}
|
|
}
|
|
}
|