Skip to content

Commit

Permalink
Merge pull request #355 from TomWright/or-default
Browse files Browse the repository at this point in the history
orDefault function
  • Loading branch information
TomWright authored Oct 18, 2023
2 parents 155933f + 7ba50af commit 150ec34
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- `orDefault()` function. [See docs](https://daseldocs.tomwright.me/functions/ordefault)

### Fixed

- Resolved an issue with YAML parser that was causing strings to be read as booleans.
Expand Down
1 change: 1 addition & 0 deletions func.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ func standardFunctions() *FunctionCollection {
LastFunc,
PropertyFunc,
AppendFunc,
OrDefaultFunc,

// Filters
FilterFunc,
Expand Down
58 changes: 58 additions & 0 deletions func_or_default.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package dasel

import (
"errors"
"fmt"
)

var OrDefaultFunc = BasicFunction{
name: "orDefault",
runFn: func(c *Context, s *Step, args []string) (Values, error) {
if err := requireExactlyXArgs("orDefault", args, 2); err != nil {
return nil, err
}

input := s.inputs()

if c.CreateWhenMissing() {
input = input.initEmptydencodingMaps()
}

runSubselect := func(value Value, selector string, defaultSelector string) (Value, error) {
gotValues, err := c.subSelect(value, selector)
if err != nil {
notFound := false
if errors.Is(err, &ErrPropertyNotFound{}) {
notFound = true
} else if errors.Is(err, &ErrIndexNotFound{Index: -1}) {
notFound = true
}
if notFound {
gotValues, err = c.subSelect(value, defaultSelector)
} else {
return Value{}, err
}
}
if len(gotValues) == 1 && err == nil {
return gotValues[0], nil
}
if err != nil {
return Value{}, err
}
return Value{}, fmt.Errorf("orDefault expects selector to return exactly 1 value")
}

res := make(Values, 0)

for _, val := range input {
resolvedValue, err := runSubselect(val, args[0], args[1])
if err != nil {
return nil, err
}

res = append(res, resolvedValue)
}

return res, nil
},
}
86 changes: 86 additions & 0 deletions func_or_default_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package dasel

import (
"testing"
)

func TestOrDefaultFunc(t *testing.T) {
t.Run("Args", selectTestErr(
"orDefault()",
map[string]interface{}{},
&ErrUnexpectedFunctionArgs{
Function: "orDefault",
Args: []string{},
}),
)

t.Run("OriginalAndDefaultNotFoundProperty", selectTestErr(
"orDefault(a,b)",
map[string]interface{}{"x": "y"},
&ErrPropertyNotFound{
Property: "b",
}),
)

t.Run("OriginalAndDefaultNotFoundIndex", selectTestErr(
"orDefault(x.[1],x.[2])",
map[string]interface{}{"x": []int{1}},
&ErrIndexNotFound{
Index: 2,
}),
)

original := map[string]interface{}{
"name": map[string]interface{}{
"first": "Tom",
"last": "Wright",
},
"colours": []interface{}{
"red", "green", "blue",
},
}

t.Run(
"FirstNameOrLastName",
selectTest(
"orDefault(name.first,name.last)",
original,
[]interface{}{
"Tom",
},
),
)

t.Run(
"MiddleNameOrDefault",
selectTest(
"orDefault(name.middle,string(default))",
original,
[]interface{}{
"default",
},
),
)

t.Run(
"FirstColourOrSecondColour",
selectTest(
"orDefault(colours.[0],colours.[2])",
original,
[]interface{}{
"red",
},
),
)

t.Run(
"FourthColourOrDefault",
selectTest(
"orDefault(colours.[3],string(default))",
original,
[]interface{}{
"default",
},
),
)
}
48 changes: 48 additions & 0 deletions internal/command/select_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,54 @@ octal: 8`)),
nil,
))

t.Run("OrDefaultString", runTest(
[]string{"-r", "json", "all().orDefault(locale,string(nope))"},
[]byte(`{
"-LCr5pXw_fN32IqNDr4E": {
"bookCategory": "poetry",
"locale": "en-us",
"mediaType": "book",
"publisher": "Pomelo Books",
"title": "Sound Waves",
"type": "poetry"
},
"-LDDHjkdY0306fZdvhEQ": {
"ISBN13": "978-1534402966",
"bookCategory": "fiction",
"title": "What Can You Do with a Toolbox?",
"type": "picturebook"
}
}`),
newline([]byte(`"en-us"
"nope"`)),
nil,
nil,
))

t.Run("OrDefaultLookup", runTest(
[]string{"-r", "json", "all().orDefault(locale,bookCategory)"},
[]byte(`{
"-LCr5pXw_fN32IqNDr4E": {
"bookCategory": "poetry",
"locale": "en-us",
"mediaType": "book",
"publisher": "Pomelo Books",
"title": "Sound Waves",
"type": "poetry"
},
"-LDDHjkdY0306fZdvhEQ": {
"ISBN13": "978-1534402966",
"bookCategory": "fiction",
"title": "What Can You Do with a Toolbox?",
"type": "picturebook"
}
}`),
newline([]byte(`"en-us"
"fiction"`)),
nil,
nil,
))

t.Run("Issue364 - CSV root element part 1", runTest(
[]string{"-r", "csv", "-w", "csv", "all().merge()"},
[]byte(`A,B,C
Expand Down

0 comments on commit 150ec34

Please sign in to comment.