feat: add fmt

Signed-off-by: jolheiser <john.olheiser@gmail.com>
main
jolheiser 2024-06-19 20:31:46 -05:00
parent 4bf09ea6cd
commit d3931c4481
Signed by: jolheiser
GPG Key ID: B853ADA5DA7BBF7A
2 changed files with 61 additions and 2 deletions

View File

@ -7,12 +7,14 @@ import (
"fmt"
"os"
"os/exec"
"strings"
)
var (
// Nix is the command to call for nix
Nix string
Nix string // Nix is the command to call for nix
Fmt []string // Fmt is the command (and args) to call to format the nix output
ErrNixNotFound = errors.New("nix was not found or set. You can set it either with `nixfig.Nix` or the `NIXFIG_NIX` environment variable")
ErrFmtNotFound = errors.New("nix formatter was not found or set. You can set it either with `nixfig.Fmt` or the `NIXFIG_FMT` environment variable")
)
func init() {
@ -21,6 +23,17 @@ func init() {
if envPath, ok := os.LookupEnv("NIXFIG_NIX"); ok {
Nix = envPath
}
for _, formatter := range []string{"alejandra", "nixfmt-rfc-style", "nixfmt"} {
fmtPath, _ := exec.LookPath(formatter)
if fmtPath != "" {
Fmt = []string{fmtPath, "--quiet"}
break
}
}
if envPath, ok := os.LookupEnv("NIXFIG_FMT"); ok {
Fmt = strings.Split(envPath, " ")
}
}
// Unmarshal unmarshals a nix expression as JSON into a struct
@ -70,3 +83,29 @@ func Marshal(v any) ([]byte, error) {
return stdout.Bytes(), nil
}
// MarshalFormat marshals a struct into a nix expression and formats it with Fmt
func MarshalFormat(v any) ([]byte, error) {
if Fmt == nil {
return nil, ErrFmtNotFound
}
data, err := Marshal(v)
if err != nil {
return nil, err
}
var stdout, stderr bytes.Buffer
cmd := exec.Command(Fmt[0], Fmt[1:]...)
cmd.Stdin = bytes.NewBuffer(data)
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("could not run %v: %w", Fmt, err)
}
if stderr.Len() > 0 {
return nil, errors.New(stderr.String())
}
return stdout.Bytes(), nil
}

View File

@ -50,6 +50,16 @@ func TestNixNotFound(t *testing.T) {
Nix = oldNix
}
func TestFmtNotFound(t *testing.T) {
oldFmt := Fmt
Fmt = nil
_, err := MarshalFormat(nil)
assert.IsError(t, err, ErrFmtNotFound)
Fmt = oldFmt
}
func TestUnmarshal(t *testing.T) {
data, err := os.ReadFile("testdata/config.nix")
assert.NoError(t, err)
@ -69,3 +79,13 @@ func TestMarshal(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, testCfg, cfg)
}
func TestMarshalFormat(t *testing.T) {
data, err := MarshalFormat(testCfg)
assert.NoError(t, err)
var cfg Config
err = Unmarshal(data, &cfg)
assert.NoError(t, err)
assert.Equal(t, testCfg, cfg)
}