mirror of
				https://github.com/taigrr/yq
				synced 2025-01-18 04:53:17 -08:00 
			
		
		
		
	wip
This commit is contained in:
		
							parent
							
								
									94a563dfd8
								
							
						
					
					
						commit
						f46c60f74d
					
				
							
								
								
									
										38
									
								
								pkg/yqlib/doc/Keys.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								pkg/yqlib/doc/Keys.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
			
		||||
 | 
			
		||||
## Get Keys
 | 
			
		||||
Given a sample.yml file of:
 | 
			
		||||
```yaml
 | 
			
		||||
a:
 | 
			
		||||
  b: cat
 | 
			
		||||
  c: dog
 | 
			
		||||
  d: frog
 | 
			
		||||
```
 | 
			
		||||
then
 | 
			
		||||
```bash
 | 
			
		||||
yq eval '.a | keys' sample.yml
 | 
			
		||||
```
 | 
			
		||||
will output
 | 
			
		||||
```yaml
 | 
			
		||||
3
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Set key style
 | 
			
		||||
Given a sample.yml file of:
 | 
			
		||||
```yaml
 | 
			
		||||
a:
 | 
			
		||||
  b: cat
 | 
			
		||||
  c: dog
 | 
			
		||||
  d: frog
 | 
			
		||||
```
 | 
			
		||||
then
 | 
			
		||||
```bash
 | 
			
		||||
yq eval '(.a | keys) style = 'single'' sample.yml
 | 
			
		||||
```
 | 
			
		||||
will output
 | 
			
		||||
```yaml
 | 
			
		||||
a:
 | 
			
		||||
  b: cat
 | 
			
		||||
  c: dog
 | 
			
		||||
  d: frog
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
@ -49,6 +49,7 @@ var CreateMap = &OperationType{Type: "CREATE_MAP", NumArgs: 2, Precedence: 40, H
 | 
			
		||||
var ShortPipe = &OperationType{Type: "SHORT_PIPE", NumArgs: 2, Precedence: 45, Handler: PipeOperator}
 | 
			
		||||
 | 
			
		||||
var Length = &OperationType{Type: "LENGTH", NumArgs: 0, Precedence: 50, Handler: LengthOperator}
 | 
			
		||||
var Keys = &OperationType{Type: "KEYS", NumArgs: 0, Precedence: 50, Handler: KeysOperator}
 | 
			
		||||
var Collect = &OperationType{Type: "COLLECT", NumArgs: 0, Precedence: 50, Handler: CollectOperator}
 | 
			
		||||
var GetStyle = &OperationType{Type: "GET_STYLE", NumArgs: 0, Precedence: 50, Handler: GetStyleOperator}
 | 
			
		||||
var GetTag = &OperationType{Type: "GET_TAG", NumArgs: 0, Precedence: 50, Handler: GetTagOperator}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										34
									
								
								pkg/yqlib/operator_keys.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								pkg/yqlib/operator_keys.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
			
		||||
package yqlib
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"container/list"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	yaml "gopkg.in/yaml.v3"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func KeysOperator(d *dataTreeNavigator, matchMap *list.List, pathNode *PathTreeNode) (*list.List, error) {
 | 
			
		||||
	log.Debugf("-- KeyOperation")
 | 
			
		||||
	var results = list.New()
 | 
			
		||||
 | 
			
		||||
	for el := matchMap.Front(); el != nil; el = el.Next() {
 | 
			
		||||
		candidate := el.Value.(*CandidateNode)
 | 
			
		||||
		targetNode := UnwrapDoc(candidate.Node)
 | 
			
		||||
 | 
			
		||||
		switch targetNode.Kind {
 | 
			
		||||
		case yaml.MappingNode:
 | 
			
		||||
			node := &yaml.Node{Kind: yaml.SequenceNode, Value: fmt.Sprintf("%v", length), Tag: "!!int"}
 | 
			
		||||
 | 
			
		||||
		case yaml.SequenceNode:
 | 
			
		||||
			length = len(targetNode.Content)
 | 
			
		||||
		default:
 | 
			
		||||
			length = 0
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", length), Tag: "!!int"}
 | 
			
		||||
		lengthCand := &CandidateNode{Node: node, Document: candidate.Document, Path: candidate.Path}
 | 
			
		||||
		results.PushBack(lengthCand)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return results, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										88
									
								
								pkg/yqlib/operator_keys_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								pkg/yqlib/operator_keys_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,88 @@
 | 
			
		||||
package yqlib
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var keyOperatorScenarios = []expressionScenario{
 | 
			
		||||
	{
 | 
			
		||||
		description: "Get Keys of map",
 | 
			
		||||
		document:    `{a: {b: cat, c: dog, d: frog}}`,
 | 
			
		||||
		expression:  `.a | keys`,
 | 
			
		||||
		expected: []string{
 | 
			
		||||
			"D0, P[a], (!!seq)::- b\n- c\n- d\n",
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		skipDoc:    true,
 | 
			
		||||
		document:   `{a1: {b: cat, c: dog, d: frog}, a2: {e: cat, f: dog, g: frog}}`,
 | 
			
		||||
		expression: `(.a1, .a2) | keys`,
 | 
			
		||||
		expected: []string{
 | 
			
		||||
			"D0, P[a1], (!!seq)::- b\n- c\n- d\n",
 | 
			
		||||
			"D0, P[a2], (!!seq)::- e\n- f\n- g\n",
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		description: "Get Keys of array",
 | 
			
		||||
		document:    `{a: [0,1,2]}`,
 | 
			
		||||
		expression:  `.a | keys`,
 | 
			
		||||
		expected: []string{
 | 
			
		||||
			"D0, P[a], (!!seq)::0\n",
 | 
			
		||||
			"D0, P[a], (!!int)::1\n",
 | 
			
		||||
			"D0, P[a], (!!int)::2\n",
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		description: "Set key style",
 | 
			
		||||
		document:    `{a: {b: cat, c: dog, d: frog}}`,
 | 
			
		||||
		expression:  `(.a | keys | ..) style = 'single'`,
 | 
			
		||||
		expected: []string{
 | 
			
		||||
			"D0, P[], (!!doc)::{a: {'b': cat, 'c': dog, 'd': frog}}\n",
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		description: "Set key alias",
 | 
			
		||||
		document:    `{a: {b: cat, c: dog, d: frog}}`,
 | 
			
		||||
		expression:  `(.a | keys | .. | select(.=="b")) alias = 'boo'`,
 | 
			
		||||
		expected: []string{
 | 
			
		||||
			"D0, P[], (!!doc)::{a: {*meow: cat, c: dog, d: frog}}\n",
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		description: "Set key alias",
 | 
			
		||||
		document:    `{a: {b: cat, c: dog, d: frog}}`,
 | 
			
		||||
		expression:  `(.a | key("b")) alias = 'boo'`,
 | 
			
		||||
		expected: []string{
 | 
			
		||||
			"D0, P[], (!!doc)::{a: {*meow: cat, c: dog, d: frog}}\n",
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		skipDoc:    true,
 | 
			
		||||
		document:   `{a: [0,1,2]}`,
 | 
			
		||||
		expression: `(.a | keys) style = 'single'`,
 | 
			
		||||
		expected: []string{
 | 
			
		||||
			"D0, P[a], (!!int)::0\n",
 | 
			
		||||
			"D0, P[a], (!!int)::1\n",
 | 
			
		||||
			"D0, P[a], (!!int)::2\n",
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		skipDoc:    true,
 | 
			
		||||
		document:   `a: cat`,
 | 
			
		||||
		expression: `.a | keys`,
 | 
			
		||||
		expected:   []string{},
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		skipDoc:    true,
 | 
			
		||||
		document:   `{}`,
 | 
			
		||||
		expression: `.a | keys`,
 | 
			
		||||
		expected:   []string{},
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestKeyOperatorScenarios(t *testing.T) {
 | 
			
		||||
	for _, tt := range keyOperatorScenarios {
 | 
			
		||||
		testScenario(t, &tt)
 | 
			
		||||
	}
 | 
			
		||||
	documentScenarios(t, "Keys", keyOperatorScenarios)
 | 
			
		||||
}
 | 
			
		||||
@ -182,6 +182,7 @@ func initLexer() (*lex.Lexer, error) {
 | 
			
		||||
	lexer.Add([]byte(`,`), opToken(Union))
 | 
			
		||||
	lexer.Add([]byte(`:\s*`), opToken(CreateMap))
 | 
			
		||||
	lexer.Add([]byte(`length`), opToken(Length))
 | 
			
		||||
	lexer.Add([]byte(`keys`), opToken(Keys))
 | 
			
		||||
	lexer.Add([]byte(`sortKeys`), opToken(SortKeys))
 | 
			
		||||
	lexer.Add([]byte(`select`), opToken(Select))
 | 
			
		||||
	lexer.Add([]byte(`has`), opToken(Has))
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								pkg/yqlib/test.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								pkg/yqlib/test.yml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
{
 | 
			
		||||
  "a1": {
 | 
			
		||||
    "b": "cat",
 | 
			
		||||
    "c": "dog"
 | 
			
		||||
  },
 | 
			
		||||
  "a2": {
 | 
			
		||||
    "d": "cat",
 | 
			
		||||
    "e": "dog"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user