formidable/internal/command/edit.go

106 lines
2.1 KiB
Go

package command
import (
"context"
"fmt"
"log"
"os"
"os/exec"
"strings"
"forge.cadoles.com/wpetit/formidable/internal/server"
"github.com/pkg/errors"
_ "github.com/santhosh-tekuri/jsonschema/v5/httploader"
"github.com/urfave/cli/v2"
)
func Edit() *cli.Command {
flags := commonFlags()
flags = append(flags, &cli.StringFlag{
Name: "browser",
EnvVars: []string{"FORMIDABLE_BROWSER"},
Value: "w3m",
})
return &cli.Command{
Name: "edit",
Usage: "Display a form for given schema and values",
Flags: flags,
Action: func(ctx *cli.Context) error {
browser := ctx.String("browser")
schema, err := loadSchema(ctx)
if err != nil {
return errors.Wrap(err, "could not load schema")
}
values, err := loadValues(ctx)
if err != nil {
return errors.Wrap(err, "could not load values")
}
defaults, err := loadDefaults(ctx)
if err != nil {
return errors.Wrap(err, "could not load defaults")
}
srvCtx, srvCancel := context.WithCancel(ctx.Context)
defer srvCancel()
srv := server.New(
server.WithSchema(schema),
server.WithValues(values),
server.WithDefaults(defaults),
server.WithOnUpdate(func(values interface{}) error {
if err := outputValues(ctx, values); err != nil {
return errors.Wrap(err, "could not output updated values")
}
return nil
}),
)
addrs, srvErrs := srv.Start(srvCtx)
url := fmt.Sprintf("http://%s", (<-addrs).String())
url = strings.Replace(url, "0.0.0.0", "127.0.0.1", 1)
log.Printf("listening on %s", url)
cmdErrs := make(chan error)
cmdCtx, cmdCancel := context.WithCancel(ctx.Context)
defer cmdCancel()
go func() {
defer func() {
close(cmdErrs)
}()
cmd := exec.CommandContext(cmdCtx, browser, url)
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
cmd.Env = os.Environ()
if err := cmd.Run(); err != nil {
cmdErrs <- errors.WithStack(err)
}
}()
select {
case err := <-cmdErrs:
srvCancel()
return errors.WithStack(err)
case err := <-srvErrs:
cmdCancel()
return errors.WithStack(err)
}
},
}
}