Repository: zyedidia/micro
File: internal/views/splits.go (Go)

Code before:
		// Replace current node with its child node to remove chained parent
		n.parent.children[ind] = n.children[0]
		n.parent.children[ind].parent = n.parent
		if n.children[0].IsLeaf() {
			n.parent.children[ind].Kind = n.Kind
		} else {
			// Flatten the child node that replaced the current node
			n.parent.children[ind].flatten()
		}
	} else if !n.IsLeaf() && n.Kind == n.parent.Kind {
		// If we have the same kind as the parent (caused by previous flattening),
		// replace this node with its children.
		origsize := len(n.parent.children)

		// Let's say we have 5 children and want to replace [2] with its children [a] [b] [c]
		// [0] [1] [2] [3] [4] --> [0] [1] [a] [b] [c] [3] [4]
		// insertcount will be `3 - 1 = 2` in this case
		insertcount := len(n.children) - 1

		n.parent.children = append(n.parent.children, make([]*Node, insertcount)...)
		copy(n.parent.children[ind+insertcount+1:], n.parent.children[ind+1:origsize])
		copy(n.parent.children[ind:], n.parent.children)

		for i := 0; i < len(n.children); i++ {
			n.parent.children[ind+i].parent = n.parent
		}
	}

	// Update propW and propH since the parent of the children might have been updated,
	// so the children may have new siblings
	n.parent.markSizes()
}

// String returns the string form of the node and all children (used for debugging)
func (n *Node) String() string {
	var strf func(n *Node, ident int) string
	strf = func(n *Node, ident int) string {
		marker := "|"
		if n.Kind == STHoriz {
			marker = "-"
		}
		str := fmt.Sprint(strings.Repeat("\t", ident), marker, n.View, n.id)
		if n.IsLeaf() {
			str += "🍁"
		}
		str += "\n"
		for _, c := range n.children {
			str += strf(c, ident+1)
		}
		return str
	}

Review comment (bug):
I've realized it probably doesn't make sense to call `markSizes()` after return from the recursive call at line 509? Even if it doesn't cause problems, it seems it just needlessly updates the same parent that has just been updated inside the recursive call?

So, maybe for code clarity:
```
diff --git a/internal/views/splits.go b/internal/views/splits.go
index e50a471b..c3335226 100644
--- a/internal/views/splits.go
+++ b/internal/views/splits.go
@@ -500,6 +500,7 @@ func (n *Node) flatten() {
 		n.parent.children[ind].parent = n.parent
 		if n.children[0].IsLeaf() {
 			n.parent.children[ind].Kind = n.Kind
+			n.parent.markSizes()
 		} else {
 			// Flatten the child node that replaced the current node
 			n.parent.children[ind].flatten()
@@ -521,11 +522,9 @@ func (n *Node) flatten() {
 		for i := 0; i < len(n.children); i++ {
 			n.parent.children[ind+i].parent = n.parent
 		}
-	}
 
-	// Update propW and propH since the parent of the children might have been updated,
-	// so the children may have new siblings
-	n.parent.markSizes()
+		n.parent.markSizes()
+	}
 }
 
 // String returns the string form of the node and all children (used for debugging)
```

?

Or maybe just get rid of this recursion, it doesn't seem to bring much value?

BTW also I'm not sure the recursive call inside `markSizes()` is needed...

Code after:
	// Maintain the tree in a consistent state: any child node's kind (horiz vs vert)
	// should be the opposite of its parent's kind.
	if successor.IsLeaf() {
		successor.Kind = n.Kind
	} else {
		// If the successor node has children, that means it is a chained parent as well.
		// Therefore it can be replaced by its own children.
		origsize := len(n.parent.children)

		// Let's say we have 5 children and want to replace [2] with its children [a] [b] [c]
		// [0] [1] [2] [3] [4] --> [0] [1] [a] [b] [c] [3] [4]
		// insertcount will be `3 - 1 = 2` in this case
		insertcount := len(successor.children) - 1

		n.parent.children = append(n.parent.children, make([]*Node, insertcount)...)
		copy(n.parent.children[ind+insertcount+1:], n.parent.children[ind+1:origsize])
		copy(n.parent.children[ind:], successor.children)

		for i := 0; i < len(successor.children); i++ {
			n.parent.children[ind+i].parent = n.parent
		}
	}

	// Update propW and propH since the parent of the children has been updated,
	// so the children have new siblings
	n.parent.markSizes()
}

// String returns the string form of the node and all children (used for debugging)
func (n *Node) String() string {
	var strf func(n *Node, ident int) string
	strf = func(n *Node, ident int) string {
		marker := "|"
		if n.Kind == STHoriz {
			marker = "-"
		}
		str := fmt.Sprint(strings.Repeat("\t", ident), marker, n.View, n.id)
		if n.IsLeaf() {
			str += "🍁"
		}
		str += "\n"
		for _, c := range n.children {
			str += strf(c, ident+1)
		}
		return str
	}
	return strf(n, 0)
}