mirror of
https://github.com/mikefarah/yq.git
synced 2024-11-12 05:38:04 +00:00
Added alias operator;
alias, anchor and explode ops are now all documented together
This commit is contained in:
parent
f112bde5fe
commit
1b0bce5da6
@ -1,29 +0,0 @@
|
||||
|
||||
## Get anchor
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a: &billyBob cat
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq eval '.a | anchor' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
billyBob
|
||||
```
|
||||
|
||||
## Set anchor name
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a: cat
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq eval '.a anchor = "foobar"' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
a: &foobar cat
|
||||
```
|
||||
|
@ -1,4 +1,67 @@
|
||||
Explodes (or dereferences) aliases and anchors.
|
||||
Use the `alias` and `anchor` operators to read and write yaml aliases and anchors. The `explode` operator normalises a yaml file (dereference aliases and remove anchor names).
|
||||
|
||||
`yq` supports merge aliases (like `<<: *blah`) however this is no longer in the standard yaml spec (1.2) and so `yq` will automatically add the `!!merge` tag to these nodes as it is effectively a custom tag.
|
||||
|
||||
|
||||
## Get anchor
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a: &billyBob cat
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq eval '.a | anchor' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
billyBob
|
||||
```
|
||||
|
||||
## Set anchor
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a: cat
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq eval '.a anchor = "foobar"' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
a: &foobar cat
|
||||
```
|
||||
|
||||
## Get alias
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
b: &billyBob meow
|
||||
a: *billyBob
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq eval '.a | alias' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
billyBob
|
||||
```
|
||||
|
||||
## Set alias
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
b: &meow purr
|
||||
a: cat
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq eval '.a alias = "meow"' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
b: &meow purr
|
||||
a: *meow
|
||||
```
|
||||
|
||||
## Explode alias and anchor
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
4
pkg/yqlib/doc/headers/Anchor and Aliases Operators.md
Normal file
4
pkg/yqlib/doc/headers/Anchor and Aliases Operators.md
Normal file
@ -0,0 +1,4 @@
|
||||
Use the `alias` and `anchor` operators to read and write yaml aliases and anchors. The `explode` operator normalises a yaml file (dereference aliases and remove anchor names).
|
||||
|
||||
`yq` supports merge aliases (like `<<: *blah`) however this is no longer in the standard yaml spec (1.2) and so `yq` will automatically add the `!!merge` tag to these nodes as it is effectively a custom tag.
|
||||
|
@ -1 +0,0 @@
|
||||
Explodes (or dereferences) aliases and anchors.
|
@ -37,6 +37,7 @@ var AssignStyle = &OperationType{Type: "ASSIGN_STYLE", NumArgs: 2, Precedence: 4
|
||||
var AssignTag = &OperationType{Type: "ASSIGN_TAG", NumArgs: 2, Precedence: 40, Handler: AssignTagOperator}
|
||||
var AssignComment = &OperationType{Type: "ASSIGN_COMMENT", NumArgs: 2, Precedence: 40, Handler: AssignCommentsOperator}
|
||||
var AssignAnchor = &OperationType{Type: "ASSIGN_ANCHOR", NumArgs: 2, Precedence: 40, Handler: AssignAnchorOperator}
|
||||
var AssignAlias = &OperationType{Type: "ASSIGN_ALIAS", NumArgs: 2, Precedence: 40, Handler: AssignAliasOperator}
|
||||
|
||||
var Multiply = &OperationType{Type: "MULTIPLY", NumArgs: 2, Precedence: 45, Handler: MultiplyOperator}
|
||||
var Add = &OperationType{Type: "ADD", NumArgs: 2, Precedence: 45, Handler: AddOperator}
|
||||
@ -53,6 +54,7 @@ var GetStyle = &OperationType{Type: "GET_STYLE", NumArgs: 0, Precedence: 50, Han
|
||||
var GetTag = &OperationType{Type: "GET_TAG", NumArgs: 0, Precedence: 50, Handler: GetTagOperator}
|
||||
var GetComment = &OperationType{Type: "GET_COMMENT", NumArgs: 0, Precedence: 50, Handler: GetCommentsOperator}
|
||||
var GetAnchor = &OperationType{Type: "GET_ANCHOR", NumArgs: 0, Precedence: 50, Handler: GetAnchorOperator}
|
||||
var GetAlias = &OperationType{Type: "GET_ALIAS", NumArgs: 0, Precedence: 50, Handler: GetAliasOperator}
|
||||
var GetDocumentIndex = &OperationType{Type: "GET_DOCUMENT_INDEX", NumArgs: 0, Precedence: 50, Handler: GetDocumentIndexOperator}
|
||||
var GetFilename = &OperationType{Type: "GET_FILENAME", NumArgs: 0, Precedence: 50, Handler: GetFilenameOperator}
|
||||
var GetFileIndex = &OperationType{Type: "GET_FILE_INDEX", NumArgs: 0, Precedence: 50, Handler: GetFileIndexOperator}
|
||||
|
@ -1,48 +0,0 @@
|
||||
package yqlib
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func AssignAnchorOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode) (*list.List, error) {
|
||||
|
||||
log.Debugf("AssignAnchor operator!")
|
||||
|
||||
rhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
anchorName := ""
|
||||
if rhs.Front() != nil {
|
||||
anchorName = rhs.Front().Value.(*CandidateNode).Node.Value
|
||||
}
|
||||
|
||||
lhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Lhs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for el := lhs.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
log.Debugf("Setting anchorName of : %v", candidate.GetKey())
|
||||
candidate.Node.Anchor = anchorName
|
||||
}
|
||||
return matchingNodes, nil
|
||||
}
|
||||
|
||||
func GetAnchorOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode) (*list.List, error) {
|
||||
log.Debugf("GetAnchor operator!")
|
||||
var results = list.New()
|
||||
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
anchor := candidate.Node.Anchor
|
||||
node := &yaml.Node{Kind: yaml.ScalarNode, Value: anchor, Tag: "!!str"}
|
||||
lengthCand := &CandidateNode{Node: node, Document: candidate.Document, Path: candidate.Path}
|
||||
results.PushBack(lengthCand)
|
||||
}
|
||||
return results, nil
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package yqlib
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var anchorOperatorScenarios = []expressionScenario{
|
||||
{
|
||||
description: "Get anchor",
|
||||
document: `a: &billyBob cat`,
|
||||
expression: `.a | anchor`,
|
||||
expected: []string{
|
||||
"D0, P[a], (!!str)::billyBob\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Set anchor name",
|
||||
document: `a: cat`,
|
||||
expression: `.a anchor = "foobar"`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::a: &foobar cat\n",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestAnchorOperatorScenarios(t *testing.T) {
|
||||
for _, tt := range anchorOperatorScenarios {
|
||||
testScenario(t, &tt)
|
||||
}
|
||||
documentScenarios(t, "Anchor Operators", anchorOperatorScenarios)
|
||||
}
|
@ -6,6 +6,88 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func AssignAliasOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode) (*list.List, error) {
|
||||
|
||||
log.Debugf("AssignAlias operator!")
|
||||
|
||||
rhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aliasName := ""
|
||||
if rhs.Front() != nil {
|
||||
aliasName = rhs.Front().Value.(*CandidateNode).Node.Value
|
||||
}
|
||||
|
||||
lhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Lhs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for el := lhs.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
log.Debugf("Setting aliasName : %v", candidate.GetKey())
|
||||
candidate.Node.Kind = yaml.AliasNode
|
||||
candidate.Node.Value = aliasName
|
||||
}
|
||||
return matchingNodes, nil
|
||||
}
|
||||
|
||||
func GetAliasOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode) (*list.List, error) {
|
||||
log.Debugf("GetAlias operator!")
|
||||
var results = list.New()
|
||||
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
node := &yaml.Node{Kind: yaml.ScalarNode, Value: candidate.Node.Value, Tag: "!!str"}
|
||||
lengthCand := &CandidateNode{Node: node, Document: candidate.Document, Path: candidate.Path}
|
||||
results.PushBack(lengthCand)
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func AssignAnchorOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode) (*list.List, error) {
|
||||
|
||||
log.Debugf("AssignAnchor operator!")
|
||||
|
||||
rhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
anchorName := ""
|
||||
if rhs.Front() != nil {
|
||||
anchorName = rhs.Front().Value.(*CandidateNode).Node.Value
|
||||
}
|
||||
|
||||
lhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Lhs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for el := lhs.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
log.Debugf("Setting anchorName of : %v", candidate.GetKey())
|
||||
candidate.Node.Anchor = anchorName
|
||||
}
|
||||
return matchingNodes, nil
|
||||
}
|
||||
|
||||
func GetAnchorOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode) (*list.List, error) {
|
||||
log.Debugf("GetAnchor operator!")
|
||||
var results = list.New()
|
||||
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
anchor := candidate.Node.Anchor
|
||||
node := &yaml.Node{Kind: yaml.ScalarNode, Value: anchor, Tag: "!!str"}
|
||||
lengthCand := &CandidateNode{Node: node, Document: candidate.Document, Path: candidate.Path}
|
||||
results.PushBack(lengthCand)
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func ExplodeOperator(d *dataTreeNavigator, matchMap *list.List, pathNode *PathTreeNode) (*list.List, error) {
|
||||
log.Debugf("-- ExplodeOperation")
|
||||
|
@ -4,7 +4,39 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var explodeTest = []expressionScenario{
|
||||
var anchorOperatorScenarios = []expressionScenario{
|
||||
{
|
||||
description: "Get anchor",
|
||||
document: `a: &billyBob cat`,
|
||||
expression: `.a | anchor`,
|
||||
expected: []string{
|
||||
"D0, P[a], (!!str)::billyBob\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Set anchor",
|
||||
document: `a: cat`,
|
||||
expression: `.a anchor = "foobar"`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::a: &foobar cat\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Get alias",
|
||||
document: `{b: &billyBob meow, a: *billyBob}`,
|
||||
expression: `.a | alias`,
|
||||
expected: []string{
|
||||
"D0, P[a], (!!str)::billyBob\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Set alias",
|
||||
document: `{b: &meow purr, a: cat}`,
|
||||
expression: `.a alias = "meow"`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::{b: &meow purr, a: *meow}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Explode alias and anchor",
|
||||
document: `{f : {a: &a cat, b: *a}}`,
|
||||
@ -82,9 +114,9 @@ foobar:
|
||||
},
|
||||
}
|
||||
|
||||
func TestExplodeOperatorScenarios(t *testing.T) {
|
||||
for _, tt := range explodeTest {
|
||||
func TestAnchorAliaseOperatorScenarios(t *testing.T) {
|
||||
for _, tt := range anchorOperatorScenarios {
|
||||
testScenario(t, &tt)
|
||||
}
|
||||
documentScenarios(t, "Explode", explodeTest)
|
||||
documentScenarios(t, "Anchor and Aliases Operators", anchorOperatorScenarios)
|
||||
}
|
@ -209,6 +209,7 @@ func initLexer() (*lex.Lexer, error) {
|
||||
|
||||
lexer.Add([]byte(`tag`), opAssignableToken(GetTag, AssignTag))
|
||||
lexer.Add([]byte(`anchor`), opAssignableToken(GetAnchor, AssignAnchor))
|
||||
lexer.Add([]byte(`alias`), opAssignableToken(GetAlias, AssignAlias))
|
||||
lexer.Add([]byte(`filename`), opToken(GetFilename))
|
||||
lexer.Add([]byte(`fileIndex`), opToken(GetFileIndex))
|
||||
lexer.Add([]byte(`path`), opToken(GetPath))
|
||||
|
Loading…
Reference in New Issue
Block a user