mirror of
https://github.com/mikefarah/yq.git
synced 2025-03-09 18:35:36 +00:00
wip
This commit is contained in:
parent
4c6c653d25
commit
fe8f46d475
@ -81,8 +81,7 @@ type CandidateNode struct {
|
||||
LeadingContent string
|
||||
TrailingContent string
|
||||
|
||||
Path []interface{} /// the path we took to get to this node
|
||||
Document uint // the document index of this node
|
||||
Document uint // the document index of this node
|
||||
Filename string
|
||||
|
||||
Line int
|
||||
@ -95,13 +94,13 @@ type CandidateNode struct {
|
||||
IsMapKey bool
|
||||
}
|
||||
|
||||
func (n *CandidateNode) GetKey() string {
|
||||
keyPrefix := ""
|
||||
if n.IsMapKey {
|
||||
keyPrefix = "key-"
|
||||
}
|
||||
return fmt.Sprintf("%v%v - %v", keyPrefix, n.Document, n.Path)
|
||||
}
|
||||
// func (n *CandidateNode) GetKey() string {
|
||||
// keyPrefix := ""
|
||||
// if n.IsMapKey {
|
||||
// keyPrefix = "key-"
|
||||
// }
|
||||
// return fmt.Sprintf("%v%v - %v", keyPrefix, n.Document, n.Path)
|
||||
// }
|
||||
|
||||
func (n *CandidateNode) unwrapDocument() *CandidateNode {
|
||||
if n.Kind == DocumentNode {
|
||||
@ -114,15 +113,47 @@ func (n *CandidateNode) GetNiceTag() string {
|
||||
return n.unwrapDocument().Tag
|
||||
}
|
||||
|
||||
func (n *CandidateNode) GetNicePath() string {
|
||||
if n.Path != nil && len(n.Path) >= 0 {
|
||||
pathStr := make([]string, len(n.Path))
|
||||
for i, v := range n.Path {
|
||||
pathStr[i] = fmt.Sprintf("%v", v)
|
||||
}
|
||||
return strings.Join(pathStr, ".")
|
||||
func (n *CandidateNode) getParsedKey() interface{} {
|
||||
if n.Key == nil {
|
||||
return nil
|
||||
}
|
||||
return ""
|
||||
if n.Key.Tag == "!!str" {
|
||||
return n.Key.Value
|
||||
}
|
||||
index, err := parseInt(n.Key.Value)
|
||||
if err != nil {
|
||||
return n.Key.Value
|
||||
}
|
||||
return index
|
||||
|
||||
}
|
||||
|
||||
func (n *CandidateNode) GetPath() []interface{} {
|
||||
if n.Parent != nil {
|
||||
return append(n.Parent.GetPath(), n.getParsedKey())
|
||||
}
|
||||
return []interface{}{n.getParsedKey()}
|
||||
}
|
||||
|
||||
func (n *CandidateNode) GetNicePath() string {
|
||||
var sb strings.Builder
|
||||
path := n.GetPath()
|
||||
for i, element := range path {
|
||||
elementStr := fmt.Sprintf("%v", element)
|
||||
switch element.(type) {
|
||||
case int:
|
||||
sb.WriteString("[" + elementStr + "]")
|
||||
default:
|
||||
if i == 0 {
|
||||
sb.WriteString(elementStr)
|
||||
} else if strings.ContainsRune(elementStr, '.') {
|
||||
sb.WriteString("[" + elementStr + "]")
|
||||
} else {
|
||||
sb.WriteString("." + elementStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func (n *CandidateNode) AsList() *list.List {
|
||||
@ -178,7 +209,6 @@ func (n *CandidateNode) guessTagFromCustomType() string {
|
||||
|
||||
func (n *CandidateNode) CreateReplacement(kind Kind, tag string, value string) *CandidateNode {
|
||||
return &CandidateNode{
|
||||
Path: n.createChildPath(nil),
|
||||
Parent: n.Parent,
|
||||
Key: n.Key,
|
||||
IsMapKey: n.IsMapKey,
|
||||
@ -199,20 +229,6 @@ func (n *CandidateNode) CreateReplacementWithDocWrappers(kind Kind, tag string,
|
||||
return replacement
|
||||
}
|
||||
|
||||
func (n *CandidateNode) createChildPath(path interface{}) []interface{} {
|
||||
if path == nil {
|
||||
newPath := make([]interface{}, len(n.Path))
|
||||
copy(newPath, n.Path)
|
||||
return newPath
|
||||
}
|
||||
|
||||
//don't use append as they may actually modify the path of the orignal node!
|
||||
newPath := make([]interface{}, len(n.Path)+1)
|
||||
copy(newPath, n.Path)
|
||||
newPath[len(n.Path)] = path
|
||||
return newPath
|
||||
}
|
||||
|
||||
func (n *CandidateNode) CopyChildren() []*CandidateNode {
|
||||
clonedKids := make([]*CandidateNode, len(n.Content))
|
||||
for i, child := range n.Content {
|
||||
@ -258,7 +274,6 @@ func (n *CandidateNode) doCopy(cloneContent bool) *CandidateNode {
|
||||
LeadingContent: n.LeadingContent,
|
||||
TrailingContent: n.TrailingContent,
|
||||
|
||||
Path: n.Path,
|
||||
Document: n.Document,
|
||||
Filename: n.Filename,
|
||||
|
||||
@ -290,7 +305,7 @@ func (n *CandidateNode) UpdateFrom(other *CandidateNode, prefs assignPreferences
|
||||
}
|
||||
|
||||
func (n *CandidateNode) UpdateAttributesFrom(other *CandidateNode, prefs assignPreferences) {
|
||||
log.Debug("UpdateAttributesFrom: n: %v other: %v", n.GetKey(), other.GetKey())
|
||||
log.Debug("UpdateAttributesFrom: n: %v other: %v", n.Key.Value, other.Key.Value)
|
||||
if n.Kind != other.Kind {
|
||||
// clear out the contents when switching to a different type
|
||||
// e.g. map to array
|
||||
|
@ -12,7 +12,7 @@ type DataTreeNavigator interface {
|
||||
// a new context of matching candidates
|
||||
GetMatchingNodes(context Context, expressionNode *ExpressionNode) (Context, error)
|
||||
|
||||
DeeplyAssign(context Context, rhsNode *CandidateNode) error
|
||||
DeeplyAssign(context Context, path []interface{}, rhsNode *CandidateNode) error
|
||||
}
|
||||
|
||||
type dataTreeNavigator struct {
|
||||
@ -22,7 +22,7 @@ func NewDataTreeNavigator() DataTreeNavigator {
|
||||
return &dataTreeNavigator{}
|
||||
}
|
||||
|
||||
func (d *dataTreeNavigator) DeeplyAssign(context Context, rhsCandidateNode *CandidateNode) error {
|
||||
func (d *dataTreeNavigator) DeeplyAssign(context Context, path []interface{}, rhsCandidateNode *CandidateNode) error {
|
||||
|
||||
assignmentOp := &Operation{OperationType: assignOpType, Preferences: assignPreferences{}}
|
||||
|
||||
@ -30,7 +30,7 @@ func (d *dataTreeNavigator) DeeplyAssign(context Context, rhsCandidateNode *Cand
|
||||
|
||||
assignmentOpNode := &ExpressionNode{
|
||||
Operation: assignmentOp,
|
||||
LHS: createTraversalTree(rhsCandidateNode.Path, traversePreferences{}, false),
|
||||
LHS: createTraversalTree(path, traversePreferences{}, false),
|
||||
RHS: &ExpressionNode{Operation: rhsOp},
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,6 @@ func (dec *propertiesDecoder) applyPropertyComments(context Context, path []inte
|
||||
assignmentOp := &Operation{OperationType: assignOpType, Preferences: assignPreferences{}}
|
||||
|
||||
rhsCandidateNode := &CandidateNode{
|
||||
Path: path,
|
||||
Tag: "!!str",
|
||||
Value: fmt.Sprintf("%v", path[len(path)-1]),
|
||||
HeadComment: dec.processComment(strings.Join(comments, "\n")),
|
||||
@ -86,9 +85,8 @@ func (dec *propertiesDecoder) applyProperty(context Context, properties *propert
|
||||
|
||||
rhsNode := createStringScalarNode(value)
|
||||
rhsNode.Tag = rhsNode.guessTagFromCustomType()
|
||||
rhsNode.Path = path
|
||||
|
||||
return dec.d.DeeplyAssign(context, rhsNode)
|
||||
return dec.d.DeeplyAssign(context, path, rhsNode)
|
||||
}
|
||||
|
||||
func (dec *propertiesDecoder) Decode() (*CandidateNode, error) {
|
||||
|
@ -62,12 +62,11 @@ func (dec *tomlDecoder) processKeyValueIntoMap(rootMap *CandidateNode, tomlNode
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
valueNode.Path = path
|
||||
|
||||
context := Context{}
|
||||
context = context.SingleChildContext(rootMap)
|
||||
|
||||
return dec.d.DeeplyAssign(context, valueNode)
|
||||
return dec.d.DeeplyAssign(context, path, valueNode)
|
||||
}
|
||||
|
||||
func (dec *tomlDecoder) decodeKeyValuesIntoMap(rootMap *CandidateNode, tomlNode *toml.Node) (bool, error) {
|
||||
@ -279,7 +278,6 @@ func (dec *tomlDecoder) processTable(currentNode *toml.Node) (bool, error) {
|
||||
tableNodeValue := &CandidateNode{
|
||||
Kind: MappingNode,
|
||||
Tag: "!!map",
|
||||
Path: fullPath,
|
||||
}
|
||||
|
||||
tableValue := dec.parser.Expression()
|
||||
@ -296,7 +294,7 @@ func (dec *tomlDecoder) processTable(currentNode *toml.Node) (bool, error) {
|
||||
c := Context{}
|
||||
|
||||
c = c.SingleChildContext(dec.rootMap)
|
||||
err = dec.d.DeeplyAssign(c, tableNodeValue)
|
||||
err = dec.d.DeeplyAssign(c, fullPath, tableNodeValue)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -305,7 +303,6 @@ func (dec *tomlDecoder) processTable(currentNode *toml.Node) (bool, error) {
|
||||
|
||||
func (dec *tomlDecoder) arrayAppend(context Context, path []interface{}, rhsNode *CandidateNode) error {
|
||||
rhsCandidateNode := &CandidateNode{
|
||||
Path: path,
|
||||
Kind: SequenceNode,
|
||||
Tag: "!!seq",
|
||||
Content: []*CandidateNode{rhsNode},
|
||||
@ -341,7 +338,6 @@ func (dec *tomlDecoder) processArrayTable(currentNode *toml.Node) (bool, error)
|
||||
tableNodeValue := &CandidateNode{
|
||||
Kind: MappingNode,
|
||||
Tag: "!!map",
|
||||
Path: fullPath,
|
||||
}
|
||||
|
||||
tableValue := dec.parser.Expression()
|
||||
|
@ -10,8 +10,6 @@ func createMapOperator(d *dataTreeNavigator, context Context, expressionNode *Ex
|
||||
//each matchingNodes entry should turn into a sequence of keys to create.
|
||||
//then collect object should do a cross function of the same index sequence for all matches.
|
||||
|
||||
var path []interface{}
|
||||
|
||||
var document uint
|
||||
|
||||
sequences := list.New()
|
||||
@ -36,19 +34,16 @@ func createMapOperator(d *dataTreeNavigator, context Context, expressionNode *Ex
|
||||
|
||||
node := listToNodeSeq(sequences)
|
||||
node.Document = document
|
||||
node.Path = path
|
||||
|
||||
return context.SingleChildContext(node), nil
|
||||
|
||||
}
|
||||
|
||||
func sequenceFor(d *dataTreeNavigator, context Context, matchingNode *CandidateNode, expressionNode *ExpressionNode) (*CandidateNode, error) {
|
||||
var path []interface{}
|
||||
var document uint
|
||||
var matches = list.New()
|
||||
|
||||
if matchingNode != nil {
|
||||
path = matchingNode.Path
|
||||
document = matchingNode.Document
|
||||
matches.PushBack(matchingNode)
|
||||
}
|
||||
@ -63,7 +58,6 @@ func sequenceFor(d *dataTreeNavigator, context Context, matchingNode *CandidateN
|
||||
rhs.unwrapDocument(),
|
||||
}
|
||||
node.Document = document
|
||||
node.Path = path
|
||||
|
||||
return &node, nil
|
||||
}, false)
|
||||
@ -74,7 +68,6 @@ func sequenceFor(d *dataTreeNavigator, context Context, matchingNode *CandidateN
|
||||
innerList := listToNodeSeq(mapPairs.MatchingNodes)
|
||||
innerList.Style = FlowStyle
|
||||
innerList.Document = document
|
||||
innerList.Path = path
|
||||
return innerList, nil
|
||||
}
|
||||
|
||||
|
@ -88,8 +88,9 @@ func formatDateTime(d *dataTreeNavigator, context Context, expressionNode *Expre
|
||||
}
|
||||
}
|
||||
node.Document = candidate.Document
|
||||
node.Parent = candidate.Parent
|
||||
node.Key = candidate.Key
|
||||
node.FileIndex = candidate.FileIndex
|
||||
node.Path = candidate.Path
|
||||
results.PushBack(node)
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,8 @@ func deleteChildOperator(d *dataTreeNavigator, context Context, expressionNode *
|
||||
}
|
||||
|
||||
parentNode := candidate.Parent
|
||||
childPath := candidate.Path[len(candidate.Path)-1]
|
||||
parentPath := parentNode.GetPath()
|
||||
childPath := parentPath[len(parentPath)-1]
|
||||
|
||||
if parentNode.Kind == MappingNode {
|
||||
deleteFromMap(candidate.Parent, childPath)
|
||||
@ -60,7 +61,7 @@ func deleteFromMap(candidate *CandidateNode, childPath interface{}) {
|
||||
|
||||
shouldDelete := key.Value == childPath
|
||||
|
||||
log.Debugf("shouldDelete %v ? %v", value.GetKey(), shouldDelete)
|
||||
log.Debugf("shouldDelete %v ? %v", value.ToDebugString(), shouldDelete)
|
||||
|
||||
if !shouldDelete {
|
||||
newContents = append(newContents, key, value)
|
||||
|
@ -156,9 +156,11 @@ func getPathOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
node := candidate.CreateReplacement(SequenceNode, "!!seq", "")
|
||||
|
||||
content := make([]*CandidateNode, len(candidate.Path))
|
||||
for pathIndex := 0; pathIndex < len(candidate.Path); pathIndex++ {
|
||||
path := candidate.Path[pathIndex]
|
||||
path := candidate.GetPath()
|
||||
|
||||
content := make([]*CandidateNode, len(path))
|
||||
for pathIndex := 0; pathIndex < len(path); pathIndex++ {
|
||||
path := path[pathIndex]
|
||||
content[pathIndex] = createPathNodeFor(path)
|
||||
}
|
||||
node.Content = content
|
||||
|
Loading…
Reference in New Issue
Block a user