Skip to content

Commit 55a7fdf

Browse files
committed
Added is_key operator
1 parent 3dd5f0c commit 55a7fdf

File tree

5 files changed

+90
-0
lines changed

5 files changed

+90
-0
lines changed

pkg/yqlib/doc/operators/keys.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,43 @@ will output
118118
comment on key
119119
```
120120

121+
## Check node is a key
122+
Given a sample.yml file of:
123+
```yaml
124+
a:
125+
b:
126+
- cat
127+
c: frog
128+
```
129+
then
130+
```bash
131+
yq '[... | { "p": path | join("."), "isKey": is_key, "tag": tag }]' sample.yml
132+
```
133+
will output
134+
```yaml
135+
- p: ""
136+
isKey: false
137+
tag: '!!map'
138+
- p: a
139+
isKey: true
140+
tag: '!!str'
141+
- p: a
142+
isKey: false
143+
tag: '!!map'
144+
- p: a.b
145+
isKey: true
146+
tag: '!!str'
147+
- p: a.b
148+
isKey: false
149+
tag: '!!seq'
150+
- p: a.b.0
151+
isKey: false
152+
tag: '!!str'
153+
- p: a.c
154+
isKey: true
155+
tag: '!!str'
156+
- p: a.c
157+
isKey: false
158+
tag: '!!str'
159+
```
160+

pkg/yqlib/lexer_participle.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ var participleYqRules = []*participleYqRule{
123123

124124
simpleOp("keys", keysOpType),
125125
simpleOp("key", getKeyOpType),
126+
simpleOp("is_?key", isKeyOpType),
126127

127128
simpleOp("file_?name|fileName", getFilenameOpType),
128129
simpleOp("file_?index|fileIndex|fi", getFileIndexOpType),

pkg/yqlib/lib.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ var getStyleOpType = &operationType{Type: "GET_STYLE", NumArgs: 0, Precedence: 5
121121
var getTagOpType = &operationType{Type: "GET_TAG", NumArgs: 0, Precedence: 50, Handler: getTagOperator}
122122

123123
var getKeyOpType = &operationType{Type: "GET_KEY", NumArgs: 0, Precedence: 50, Handler: getKeyOperator}
124+
var isKeyOpType = &operationType{Type: "IS_KEY", NumArgs: 0, Precedence: 50, Handler: isKeyOperator}
124125
var getParentOpType = &operationType{Type: "GET_PARENT", NumArgs: 0, Precedence: 50, Handler: getParentOperator}
125126

126127
var getCommentOpType = &operationType{Type: "GET_COMMENT", NumArgs: 0, Precedence: 50, Handler: getCommentsOperator}

pkg/yqlib/operator_keys.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ import (
77
"gopkg.in/yaml.v3"
88
)
99

10+
func isKeyOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
11+
log.Debugf("-- isKeyOperator")
12+
13+
var results = list.New()
14+
15+
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
16+
candidate := el.Value.(*CandidateNode)
17+
18+
results.PushBack(createBooleanCandidate(candidate, candidate.IsMapKey))
19+
}
20+
21+
return context.ChildContext(results), nil
22+
}
23+
1024
func getKeyOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
1125
log.Debugf("-- getKeyOperator")
1226

pkg/yqlib/operator_keys_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,32 @@ import (
44
"testing"
55
)
66

7+
var expectedIsKey = `D0, P[], (!!seq)::- p: ""
8+
isKey: false
9+
tag: '!!map'
10+
- p: a
11+
isKey: true
12+
tag: '!!str'
13+
- p: a
14+
isKey: false
15+
tag: '!!map'
16+
- p: a.b
17+
isKey: true
18+
tag: '!!str'
19+
- p: a.b
20+
isKey: false
21+
tag: '!!seq'
22+
- p: a.b.0
23+
isKey: false
24+
tag: '!!str'
25+
- p: a.c
26+
isKey: true
27+
tag: '!!str'
28+
- p: a.c
29+
isKey: false
30+
tag: '!!str'
31+
`
32+
733
var keysOperatorScenarios = []expressionScenario{
834
{
935
description: "Map keys",
@@ -75,6 +101,14 @@ var keysOperatorScenarios = []expressionScenario{
75101
"D0, P[a x], (!!str)::comment on key\n",
76102
},
77103
},
104+
{
105+
description: "Check node is a key",
106+
document: "a: \n b: [cat]\n c: frog\n",
107+
expression: `[... | { "p": path | join("."), "isKey": is_key, "tag": tag }]`,
108+
expected: []string{
109+
expectedIsKey,
110+
},
111+
},
78112
}
79113

80114
func TestKeysOperatorScenarios(t *testing.T) {

0 commit comments

Comments
 (0)