mirror of https://git.jolheiser.com/cfg.git
130 lines
2.4 KiB
Go
130 lines
2.4 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"errors"
|
||
|
"flag"
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/pelletier/go-toml/v2"
|
||
|
"github.com/philandstuff/dhall-golang/v6"
|
||
|
"github.com/tailscale/hujson"
|
||
|
"go.jolheiser.com/nixfig"
|
||
|
"gopkg.in/yaml.v3"
|
||
|
)
|
||
|
|
||
|
func maine() error {
|
||
|
var unmarshal func([]byte, any) error
|
||
|
var marshal func(any) ([]byte, error)
|
||
|
|
||
|
fs := flag.NewFlagSet("cfg", flag.ExitOnError)
|
||
|
fromFunc := func(s string) error {
|
||
|
switch strings.ToLower(s) {
|
||
|
case "json", "jsonc":
|
||
|
unmarshal = func(b []byte, a any) error {
|
||
|
b, err := hujson.Standardize(b)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return json.Unmarshal(b, a)
|
||
|
}
|
||
|
case "yaml":
|
||
|
unmarshal = yaml.Unmarshal
|
||
|
case "toml":
|
||
|
unmarshal = toml.Unmarshal
|
||
|
case "dhall":
|
||
|
unmarshal = dhall.Unmarshal
|
||
|
case "nix":
|
||
|
unmarshal = nixfig.Unmarshal
|
||
|
default:
|
||
|
return fmt.Errorf("unknown format %q", s)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
fs.Func("from", "The format to convert from", fromFunc)
|
||
|
fs.Func("f", "--from", fromFunc)
|
||
|
toFunc := func(s string) error {
|
||
|
switch strings.ToLower(s) {
|
||
|
case "json", "jsonc":
|
||
|
marshal = func(a any) ([]byte, error) {
|
||
|
return json.MarshalIndent(a, "", "\t")
|
||
|
}
|
||
|
case "yaml":
|
||
|
marshal = yaml.Marshal
|
||
|
case "toml":
|
||
|
marshal = toml.Marshal
|
||
|
case "nix":
|
||
|
marshal = nixfig.Marshal
|
||
|
default:
|
||
|
return fmt.Errorf("unknown format %q", s)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
fs.Func("to", "The format to convert to", toFunc)
|
||
|
fs.Func("t", "--to", toFunc)
|
||
|
if err := fs.Parse(os.Args[1:]); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if fs.NArg() < 1 {
|
||
|
return errors.New("cfg requires at least an input file")
|
||
|
}
|
||
|
|
||
|
in := fs.Arg(0)
|
||
|
if unmarshal == nil {
|
||
|
if err := fromFunc(strings.TrimPrefix(filepath.Ext(fs.Arg(0)), ".")); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
out := os.Stdout
|
||
|
if fs.NArg() > 1 {
|
||
|
fi, err := os.Create(fs.Arg(1))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
defer fi.Close()
|
||
|
out = fi
|
||
|
|
||
|
if marshal == nil {
|
||
|
if err := toFunc(strings.TrimPrefix(filepath.Ext(fs.Arg(1)), ".")); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
} else if marshal == nil {
|
||
|
marshal = json.Marshal
|
||
|
}
|
||
|
|
||
|
var data any
|
||
|
|
||
|
inData, err := os.ReadFile(in)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if err := unmarshal(inData, &data); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
outData, err := marshal(data)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if _, err := out.Write(outData); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func main() {
|
||
|
if err := maine(); err != nil {
|
||
|
fmt.Println(err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
}
|