Skip to content

Commit

Permalink
Add support for reading JSON5 (closes #13)
Browse files Browse the repository at this point in the history
  • Loading branch information
xrstf committed Dec 31, 2023
1 parent 6537c24 commit 6ddddb9
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 17 deletions.
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ or normalizing data configurable.
* **Optional Type Safety**: Choose between pedantic, strict or humane typing for your programs.
Strict allows nearly no type conversions, humane allows for things like `1` (int) turning into
`"1"` (string) when needed.
* **Flexible**: The Rudi CLI interpreter (`rudi`) supports reading/writing JSON, YAML and TOML.
* **Flexible**: The Rudi CLI interpreter (`rudi`) supports reading/writing JSON,
[JSON5](https://json5.org/), [YAML](https://yaml.org/) and [TOML](https://toml.io/en/).

## Installation

Expand Down Expand Up @@ -125,16 +126,22 @@ Usage of rudi:

#### File Handling

Rudi can load JSON, JSON5, YAML and TOML files and will determine the file format based on the
file extension (`.json` for JSON, `.json5` for JSON5, `.yml` and `.yaml` for YAML and `.tml` /
`.toml` for TOML). For data provided via stdin, `rudi` by default assumes YAML (or JSON) encoding.
If you want to use TOML/JSON5 instead, you must use the `--stdin-format` flag.

The first loaded file is known as the "document". Its content is available via path expressions like
`.foo[0]`. All loaded files are also available via the `$files` variable (i.e. `.` is the same as
`$files[0]` for reading, but when writing data, there is a difference between both notations; refer
to the docs for `set` for more information). Additionally the filenames are available in the
`$filenames` variable.

For data provided via stdin, `rudi` by default assumes YAML (or JSON) encoding. If you want to use
TOML instead, you must pass `--stdin-format=toml`. When files are used, the format is deduced from
the file extension: `.toml` and `.tml` are parsed as TOML, everything else uses YAML decoding by
default.
Additional raw files can be loaded using the `--var` flag: To load files, the format for this flag
is `ENCODING:file:FILENAME`, for example `--var "myvar=yaml:file:config.kubeconfig"`. This allows
you to load files regardless of their extension and also allows to load raw files (that will be
kept as strings) using `"myvar=raw:file:logo.png"`. Raw file encoding is not supported for files
given as arguments, those files must have a recognized file extension.

### Embedding

Expand Down
7 changes: 7 additions & 0 deletions cmd/rudi/encoding/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"go.xrstf.de/rudi/cmd/rudi/types"

"github.com/BurntSushi/toml"
"github.com/titanous/json5"
"gopkg.in/yaml.v3"
)

Expand All @@ -32,6 +33,12 @@ func Decode(input io.Reader, enc types.Encoding) (any, error) {
return nil, fmt.Errorf("failed to parse file as JSON: %w", err)
}

case types.Json5Encoding:
decoder := json5.NewDecoder(input)
if err := decoder.Decode(&data); err != nil {
return nil, fmt.Errorf("failed to parse file as JSON5: %w", err)
}

case types.YamlEncoding:
decoder := yaml.NewDecoder(input)
if err := decoder.Decode(&data); err != nil {
Expand Down
1 change: 1 addition & 0 deletions cmd/rudi/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/chzyer/readline v1.5.1
github.com/muesli/termenv v0.15.2
github.com/spf13/pflag v1.0.5
github.com/titanous/json5 v1.0.0
go.xrstf.de/rudi v0.5.1
go.xrstf.de/rudi-contrib/semver v0.1.5
go.xrstf.de/rudi-contrib/set v0.1.1
Expand Down
10 changes: 10 additions & 0 deletions cmd/rudi/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f h1:7LYC+Yfkj3CTRcShK0KOL/w6iTiKyqqBA9a41Wnggw8=
github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f/go.mod h1:pFlLw2CfqZiIBOx6BuCeRLCrfxBJipTY0nIOF/VbGcI=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
Expand All @@ -31,8 +33,12 @@ github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/robertkrimen/otto v0.2.1 h1:FVP0PJ0AHIjC+N4pKCG9yCDz6LHNPCwi/GKID5pGGF0=
github.com/robertkrimen/otto v0.2.1/go.mod h1:UPwtJ1Xu7JrLcZjNWN8orJaM5n5YEtqL//farB5FlRY=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/titanous/json5 v1.0.0 h1:hJf8Su1d9NuI/ffpxgxQfxh/UiBFZX7bMPid0rIL/7s=
github.com/titanous/json5 v1.0.0/go.mod h1:7JH1M8/LHKc6cyP5o5g3CSaRj+mBrIimTxzpvmckH8c=
github.com/xrstf/colorjson v0.0.0-20231123184920-5ea6fecf578f h1:gVBqsyWwyxxzSGjfeOZVHGWMQNN7pgMwJzKdJc8sHzs=
github.com/xrstf/colorjson v0.0.0-20231123184920-5ea6fecf578f/go.mod h1:AY6XdslHQYqT5ivYt21gXNpCjsck8iEoytnNfz3COxY=
go.xrstf.de/rudi-contrib/semver v0.1.5 h1:qnp5dfoHk7X7EBuBHGplUfbtfpHcOD9f9zXo+GegErI=
Expand All @@ -48,8 +54,12 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/apimachinery v0.29.0 h1:+ACVktwyicPz0oc6MTMLwa2Pw3ouLAfAon1wPLtG48o=
Expand Down
4 changes: 2 additions & 2 deletions cmd/rudi/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ func NewDefaultOptions() Options {
func (o *Options) AddFlags(fs *pflag.FlagSet) {
fs.SortFlags = false

stdinFormatFlag := newEnumFlag(&o.StdinFormat, types.AllEncodings...)
outputFormatFlag := newEnumFlag(&o.OutputFormat, types.AllEncodings...)
stdinFormatFlag := newEnumFlag(&o.StdinFormat, types.InputEncodings...)
outputFormatFlag := newEnumFlag(&o.OutputFormat, types.OutputEncodings...)
coalescingFlag := newEnumFlag(&o.Coalescing, types.AllCoalescings...)

fs.BoolVarP(&o.Interactive, "interactive", "i", o.Interactive, "Start an interactive REPL to run expressions.")
Expand Down
32 changes: 22 additions & 10 deletions cmd/rudi/types/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,30 @@ func (e Encoding) IsValid() bool {
}

const (
RawEncoding Encoding = "raw"
JsonEncoding Encoding = "json"
YamlEncoding Encoding = "yaml"
TomlEncoding Encoding = "toml"
RawEncoding Encoding = "raw"
JsonEncoding Encoding = "json"
Json5Encoding Encoding = "json5"
YamlEncoding Encoding = "yaml"
TomlEncoding Encoding = "toml"
)

var AllEncodings = []Encoding{
RawEncoding,
JsonEncoding,
YamlEncoding,
TomlEncoding,
}
var (
AllEncodings = []Encoding{
RawEncoding,
JsonEncoding,
Json5Encoding,
YamlEncoding,
TomlEncoding,
}

InputEncodings = AllEncodings
OutputEncodings = []Encoding{
RawEncoding,
JsonEncoding,
YamlEncoding,
TomlEncoding,
}
)

type Coalescing string

Expand Down
2 changes: 2 additions & 0 deletions cmd/rudi/util/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ func getFileFormat(filename string) types.Encoding {
switch strings.ToLower(filepath.Ext(filename)) {
case ".json":
return types.JsonEncoding
case ".json5":
return types.Json5Encoding
case ".tml", ".toml":
return types.TomlEncoding
default:
Expand Down

0 comments on commit 6ddddb9

Please sign in to comment.