mirror of
https://github.com/mikefarah/yq.git
synced 2025-01-23 14:16:10 +00:00
comment ops!
This commit is contained in:
parent
b1f139c965
commit
5ab584afac
1
pkg/yqlib/doc/.gitignore
vendored
Normal file
1
pkg/yqlib/doc/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.md
|
@ -1,64 +0,0 @@
|
||||
# Equal Operator
|
||||
## Examples
|
||||
### Example 0
|
||||
sample.yml:
|
||||
```yaml
|
||||
[cat,goat,dog]
|
||||
```
|
||||
Expression
|
||||
```bash
|
||||
yq '.[] | (. == "*at")' < sample.yml
|
||||
```
|
||||
Result
|
||||
```yaml
|
||||
true
|
||||
true
|
||||
false
|
||||
```
|
||||
### Example 1
|
||||
sample.yml:
|
||||
```yaml
|
||||
[3, 4, 5]
|
||||
```
|
||||
Expression
|
||||
```bash
|
||||
yq '.[] | (. == 4)' < sample.yml
|
||||
```
|
||||
Result
|
||||
```yaml
|
||||
false
|
||||
true
|
||||
false
|
||||
```
|
||||
### Example 2
|
||||
sample.yml:
|
||||
```yaml
|
||||
a: { cat: {b: apple, c: whatever}, pat: {b: banana} }
|
||||
```
|
||||
Expression
|
||||
```bash
|
||||
yq '.a | (.[].b == "apple")' < sample.yml
|
||||
```
|
||||
Result
|
||||
```yaml
|
||||
true
|
||||
false
|
||||
```
|
||||
### Example 3
|
||||
Expression
|
||||
```bash
|
||||
yq 'null == null' < sample.yml
|
||||
```
|
||||
Result
|
||||
```yaml
|
||||
true
|
||||
```
|
||||
### Example 4
|
||||
Expression
|
||||
```bash
|
||||
yq 'null == ~' < sample.yml
|
||||
```
|
||||
Result
|
||||
```yaml
|
||||
true
|
||||
```
|
@ -18,14 +18,12 @@ type OperationType struct {
|
||||
|
||||
// operators TODO:
|
||||
// - generator doc from operator tests
|
||||
// - stripComments not recursive
|
||||
// - set comments not recursive
|
||||
// - documentIndex - retrieves document index, can be used with select
|
||||
// - mergeAppend (merges and appends arrays)
|
||||
// - mergeEmpty (sets only if the document is empty, do I do that now?)
|
||||
// - updateTag - not recursive
|
||||
// - select by tag (tag==)
|
||||
// - get tag (tag)
|
||||
// - select by style (style==)
|
||||
// - compare ??
|
||||
// - validate ??
|
||||
// - exists
|
||||
@ -38,6 +36,7 @@ var Union = &OperationType{Type: "UNION", NumArgs: 2, Precedence: 10, Handler: U
|
||||
var Assign = &OperationType{Type: "ASSIGN", NumArgs: 2, Precedence: 40, Handler: AssignUpdateOperator}
|
||||
var AssignAttributes = &OperationType{Type: "ASSIGN_ATTRIBUTES", NumArgs: 2, Precedence: 40, Handler: AssignAttributesOperator}
|
||||
var AssignStyle = &OperationType{Type: "ASSIGN_STYLE", NumArgs: 2, Precedence: 40, Handler: AssignStyleOperator}
|
||||
var AssignComment = &OperationType{Type: "ASSIGN_COMMENT", NumArgs: 2, Precedence: 40, Handler: AssignCommentsOperator}
|
||||
|
||||
var Multiply = &OperationType{Type: "MULTIPLY", NumArgs: 2, Precedence: 40, Handler: MultiplyOperator}
|
||||
|
||||
|
47
pkg/yqlib/operator_comments.go
Normal file
47
pkg/yqlib/operator_comments.go
Normal file
@ -0,0 +1,47 @@
|
||||
package yqlib
|
||||
|
||||
import "container/list"
|
||||
|
||||
type AssignCommentPreferences struct {
|
||||
LineComment bool
|
||||
HeadComment bool
|
||||
FootComment bool
|
||||
}
|
||||
|
||||
func AssignCommentsOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode) (*list.List, error) {
|
||||
|
||||
log.Debugf("AssignComments operator!")
|
||||
|
||||
rhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
comment := ""
|
||||
if rhs.Front() != nil {
|
||||
comment = rhs.Front().Value.(*CandidateNode).Node.Value
|
||||
}
|
||||
|
||||
lhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Lhs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
preferences := pathNode.Operation.Preferences.(*AssignCommentPreferences)
|
||||
|
||||
for el := lhs.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
log.Debugf("Setting comment of : %v", candidate.GetKey())
|
||||
if preferences.LineComment {
|
||||
candidate.Node.LineComment = comment
|
||||
}
|
||||
if preferences.HeadComment {
|
||||
candidate.Node.HeadComment = comment
|
||||
}
|
||||
if preferences.FootComment {
|
||||
candidate.Node.FootComment = comment
|
||||
}
|
||||
|
||||
}
|
||||
return matchingNodes, nil
|
||||
}
|
55
pkg/yqlib/operator_comments_test.go
Normal file
55
pkg/yqlib/operator_comments_test.go
Normal file
@ -0,0 +1,55 @@
|
||||
package yqlib
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var commentOperatorScenarios = []expressionScenario{
|
||||
{
|
||||
description: "Add line comment",
|
||||
document: `a: cat`,
|
||||
expression: `.a lineComment="single"`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::a: cat # single\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Add head comment",
|
||||
document: `a: cat`,
|
||||
expression: `. headComment="single"`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::# single\n\na: cat\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Add foot comment, using an expression",
|
||||
document: `a: cat`,
|
||||
expression: `. footComment=.a`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::a: cat\n\n# cat\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Remove comment",
|
||||
document: "a: cat # comment\nb: dog # leave this",
|
||||
expression: `.a lineComment=""`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::a: cat\nb: dog # leave this\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Remove all comments",
|
||||
document: "# hi\n\na: cat # comment\n\n# great\n",
|
||||
expression: `.. comments=""`,
|
||||
expected: []string{
|
||||
"D0, P[], (!!map)::a: cat\n",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestCommentOperatorScenarios(t *testing.T) {
|
||||
for _, tt := range commentOperatorScenarios {
|
||||
testScenario(t, &tt)
|
||||
}
|
||||
documentScenarios(t, "Comments Operator", commentOperatorScenarios)
|
||||
}
|
@ -49,5 +49,5 @@ func TestEqualOperatorScenarios(t *testing.T) {
|
||||
for _, tt := range equalsOperatorScenarios {
|
||||
testScenario(t, &tt)
|
||||
}
|
||||
documentScenarios(t, "Equal Operator", equalsOperatorScenarios)
|
||||
documentScenarios(t, "Equals Operator", equalsOperatorScenarios)
|
||||
}
|
||||
|
@ -8,8 +8,18 @@ import (
|
||||
)
|
||||
|
||||
func AssignStyleOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode) (*list.List, error) {
|
||||
customStyle := pathNode.Rhs.Operation.StringValue
|
||||
log.Debugf("AssignStyleOperator: %v", customStyle)
|
||||
|
||||
log.Debugf("AssignStyleOperator: %v")
|
||||
|
||||
rhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
customStyle := ""
|
||||
|
||||
if rhs.Front() != nil {
|
||||
customStyle = rhs.Front().Value.(*CandidateNode).Node.Value
|
||||
}
|
||||
|
||||
var style yaml.Style
|
||||
if customStyle == "tagged" {
|
||||
|
@ -12,6 +12,14 @@ var styleOperatorScenarios = []expressionScenario{
|
||||
"D0, P[], (doc)::{a: 'cat'}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Set style using a path",
|
||||
document: `{a: cat, b: double}`,
|
||||
expression: `.a style=.b`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::{a: \"cat\", b: double}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
document: `{a: "cat", b: 'dog'}`,
|
||||
expression: `.. style=""`,
|
||||
@ -42,4 +50,5 @@ func TestStyleOperatorScenarios(t *testing.T) {
|
||||
for _, tt := range styleOperatorScenarios {
|
||||
testScenario(t, &tt)
|
||||
}
|
||||
documentScenarios(t, "Style Operator", styleOperatorScenarios)
|
||||
}
|
||||
|
@ -84,9 +84,13 @@ func documentToken() lex.Action {
|
||||
}
|
||||
|
||||
func opToken(op *OperationType) lex.Action {
|
||||
return opTokenWithPrefs(op, nil)
|
||||
}
|
||||
|
||||
func opTokenWithPrefs(op *OperationType, preferences interface{}) lex.Action {
|
||||
return func(s *lex.Scanner, m *machines.Match) (interface{}, error) {
|
||||
value := string(m.Bytes)
|
||||
op := &Operation{OperationType: op, Value: op.Type, StringValue: value}
|
||||
op := &Operation{OperationType: op, Value: op.Type, StringValue: value, Preferences: preferences}
|
||||
return &Token{TokenType: OperationToken, Operation: op}, nil
|
||||
}
|
||||
}
|
||||
@ -190,6 +194,12 @@ func initLexer() (*lex.Lexer, error) {
|
||||
lexer.Add([]byte(`style\s*=`), opToken(AssignStyle))
|
||||
lexer.Add([]byte(`style`), opToken(GetStyle))
|
||||
|
||||
lexer.Add([]byte(`lineComment\s*=`), opTokenWithPrefs(AssignComment, &AssignCommentPreferences{LineComment: true}))
|
||||
lexer.Add([]byte(`headComment\s*=`), opTokenWithPrefs(AssignComment, &AssignCommentPreferences{HeadComment: true}))
|
||||
lexer.Add([]byte(`footComment\s*=`), opTokenWithPrefs(AssignComment, &AssignCommentPreferences{FootComment: true}))
|
||||
lexer.Add([]byte(`comments\s*=`), opTokenWithPrefs(AssignComment, &AssignCommentPreferences{LineComment: true, HeadComment: true, FootComment: true}))
|
||||
// lexer.Add([]byte(`style`), opToken(GetStyle))
|
||||
|
||||
// lexer.Add([]byte(`and`), opToken())
|
||||
lexer.Add([]byte(`collect`), opToken(Collect))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user