mirror of
https://github.com/mikefarah/yq.git
synced 2025-01-23 14:16:10 +00:00
Added Alternative op
This commit is contained in:
parent
1fb37785d6
commit
a23272727d
73
pkg/yqlib/doc/Alternative (Default value).md
Normal file
73
pkg/yqlib/doc/Alternative (Default value).md
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
This operator is used to provide alternative (or default) values when a particular expression is either null or false.
|
||||||
|
|
||||||
|
## LHS is defined
|
||||||
|
Given a sample.yml file of:
|
||||||
|
```yaml
|
||||||
|
a: bridge
|
||||||
|
```
|
||||||
|
then
|
||||||
|
```bash
|
||||||
|
yq eval '.a // "hello"' sample.yml
|
||||||
|
```
|
||||||
|
will output
|
||||||
|
```yaml
|
||||||
|
bridge
|
||||||
|
```
|
||||||
|
|
||||||
|
## LHS is not defined
|
||||||
|
Given a sample.yml file of:
|
||||||
|
```yaml
|
||||||
|
{}
|
||||||
|
```
|
||||||
|
then
|
||||||
|
```bash
|
||||||
|
yq eval '.a // "hello"' sample.yml
|
||||||
|
```
|
||||||
|
will output
|
||||||
|
```yaml
|
||||||
|
hello
|
||||||
|
```
|
||||||
|
|
||||||
|
## LHS is null
|
||||||
|
Given a sample.yml file of:
|
||||||
|
```yaml
|
||||||
|
a: ~
|
||||||
|
```
|
||||||
|
then
|
||||||
|
```bash
|
||||||
|
yq eval '.a // "hello"' sample.yml
|
||||||
|
```
|
||||||
|
will output
|
||||||
|
```yaml
|
||||||
|
hello
|
||||||
|
```
|
||||||
|
|
||||||
|
## LHS is false
|
||||||
|
Given a sample.yml file of:
|
||||||
|
```yaml
|
||||||
|
a: false
|
||||||
|
```
|
||||||
|
then
|
||||||
|
```bash
|
||||||
|
yq eval '.a // "hello"' sample.yml
|
||||||
|
```
|
||||||
|
will output
|
||||||
|
```yaml
|
||||||
|
hello
|
||||||
|
```
|
||||||
|
|
||||||
|
## RHS is an expression
|
||||||
|
Given a sample.yml file of:
|
||||||
|
```yaml
|
||||||
|
a: false
|
||||||
|
b: cat
|
||||||
|
```
|
||||||
|
then
|
||||||
|
```bash
|
||||||
|
yq eval '.a // .b' sample.yml
|
||||||
|
```
|
||||||
|
will output
|
||||||
|
```yaml
|
||||||
|
cat
|
||||||
|
```
|
||||||
|
|
1
pkg/yqlib/doc/headers/Alternative (Default value).md
Normal file
1
pkg/yqlib/doc/headers/Alternative (Default value).md
Normal file
@ -0,0 +1 @@
|
|||||||
|
This operator is used to provide alternative (or default) values when a particular expression is either null or false.
|
@ -39,6 +39,7 @@ var AssignComment = &OperationType{Type: "ASSIGN_COMMENT", NumArgs: 2, Precedenc
|
|||||||
|
|
||||||
var Multiply = &OperationType{Type: "MULTIPLY", NumArgs: 2, Precedence: 45, Handler: MultiplyOperator}
|
var Multiply = &OperationType{Type: "MULTIPLY", NumArgs: 2, Precedence: 45, Handler: MultiplyOperator}
|
||||||
var Add = &OperationType{Type: "ADD", NumArgs: 2, Precedence: 45, Handler: AddOperator}
|
var Add = &OperationType{Type: "ADD", NumArgs: 2, Precedence: 45, Handler: AddOperator}
|
||||||
|
var Alternative = &OperationType{Type: "ALTERNATIVE", NumArgs: 2, Precedence: 45, Handler: AlternativeOperator}
|
||||||
|
|
||||||
var Equals = &OperationType{Type: "EQUALS", NumArgs: 2, Precedence: 40, Handler: EqualsOperator}
|
var Equals = &OperationType{Type: "EQUALS", NumArgs: 2, Precedence: 40, Handler: EqualsOperator}
|
||||||
var CreateMap = &OperationType{Type: "CREATE_MAP", NumArgs: 2, Precedence: 40, Handler: CreateMapOperator}
|
var CreateMap = &OperationType{Type: "CREATE_MAP", NumArgs: 2, Precedence: 40, Handler: CreateMapOperator}
|
||||||
|
55
pkg/yqlib/oeprator_alternative_test.go
Normal file
55
pkg/yqlib/oeprator_alternative_test.go
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package yqlib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var alternativeOperatorScenarios = []expressionScenario{
|
||||||
|
{
|
||||||
|
description: "LHS is defined",
|
||||||
|
expression: `.a // "hello"`,
|
||||||
|
document: `{a: bridge}`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[a], (!!str)::bridge\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "LHS is not defined",
|
||||||
|
expression: `.a // "hello"`,
|
||||||
|
document: `{}`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[], (!!str)::hello\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "LHS is null",
|
||||||
|
expression: `.a // "hello"`,
|
||||||
|
document: `{a: ~}`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[], (!!str)::hello\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "LHS is false",
|
||||||
|
expression: `.a // "hello"`,
|
||||||
|
document: `{a: false}`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[], (!!str)::hello\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "RHS is an expression",
|
||||||
|
expression: `.a // .b`,
|
||||||
|
document: `{a: false, b: cat}`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[b], (!!str)::cat\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAlternativeOperatorScenarios(t *testing.T) {
|
||||||
|
for _, tt := range alternativeOperatorScenarios {
|
||||||
|
testScenario(t, &tt)
|
||||||
|
}
|
||||||
|
documentScenarios(t, "Alternative (Default value)", alternativeOperatorScenarios)
|
||||||
|
}
|
28
pkg/yqlib/operator_alternative.go
Normal file
28
pkg/yqlib/operator_alternative.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package yqlib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"container/list"
|
||||||
|
)
|
||||||
|
|
||||||
|
// corssFunction no matches
|
||||||
|
// can boolean use crossfunction
|
||||||
|
|
||||||
|
func AlternativeOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode) (*list.List, error) {
|
||||||
|
log.Debugf("-- alternative")
|
||||||
|
return crossFunction(d, matchingNodes, pathNode, alternativeFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func alternativeFunc(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||||
|
lhs.Node = UnwrapDoc(lhs.Node)
|
||||||
|
rhs.Node = UnwrapDoc(rhs.Node)
|
||||||
|
log.Debugf("Alternative LHS: %v", lhs.Node.Tag)
|
||||||
|
log.Debugf("- RHS: %v", rhs.Node.Tag)
|
||||||
|
|
||||||
|
isTrue, err := isTruthy(lhs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if isTrue {
|
||||||
|
return lhs, nil
|
||||||
|
}
|
||||||
|
return rhs, nil
|
||||||
|
}
|
@ -201,6 +201,7 @@ func initLexer() (*lex.Lexer, error) {
|
|||||||
lexer.Add([]byte(`or`), opToken(Or))
|
lexer.Add([]byte(`or`), opToken(Or))
|
||||||
lexer.Add([]byte(`and`), opToken(And))
|
lexer.Add([]byte(`and`), opToken(And))
|
||||||
lexer.Add([]byte(`not`), opToken(Not))
|
lexer.Add([]byte(`not`), opToken(Not))
|
||||||
|
lexer.Add([]byte(`\/\/`), opToken(Alternative))
|
||||||
|
|
||||||
lexer.Add([]byte(`documentIndex`), opToken(GetDocumentIndex))
|
lexer.Add([]byte(`documentIndex`), opToken(GetDocumentIndex))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user