Skip to content

Commit 760ca8a

Browse files
authored
Fix retain_tabs behavior with Empty nodes in the list (#275)
* Add failing unit test * Add two fixes
1 parent fb67c8f commit 760ca8a

File tree

1 file changed

+50
-1
lines changed

1 file changed

+50
-1
lines changed

src/dock_state/tree/mod.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,16 @@ impl<Tab> Tree<Tab> {
653653
level += 1;
654654
}
655655
}
656+
// Ensure that there are no trailing `Node::Empty` items
657+
while let Some(last_index) = self.nodes.len().checked_sub(1).map(NodeIndex) {
658+
if self[last_index].is_empty()
659+
&& last_index.parent().is_some_and(|pi| !self[pi].is_parent())
660+
{
661+
self.nodes.pop();
662+
} else {
663+
break;
664+
}
665+
}
656666
}
657667

658668
/// Pushes a tab to the first `Leaf` it finds or create a new leaf if an `Empty` node is encountered.
@@ -833,7 +843,10 @@ impl<Tab> Tree<Tab> {
833843
fn balance(&mut self, emptied_nodes: HashSet<NodeIndex>) {
834844
let mut emptied_parents = HashSet::default();
835845
for parent_index in emptied_nodes.into_iter().filter_map(|ni| ni.parent()) {
836-
if self[parent_index.left()].is_empty() && self[parent_index.right()].is_empty() {
846+
if !self[parent_index].is_parent() {
847+
continue;
848+
} else if self[parent_index.left()].is_empty() && self[parent_index.right()].is_empty()
849+
{
837850
self[parent_index] = Node::Empty;
838851
emptied_parents.insert(parent_index);
839852
} else if self[parent_index.left()].is_empty() {
@@ -938,3 +951,39 @@ where
938951
self.find_tab_from(|tab| tab == needle_tab)
939952
}
940953
}
954+
955+
#[cfg(test)]
956+
mod test {
957+
use super::*;
958+
959+
#[derive(Copy, Clone, Debug, PartialEq)]
960+
struct Tab(u64);
961+
962+
/// Checks that `retain` works after removing a node
963+
#[test]
964+
fn remove_and_retain() {
965+
let mut tree: Tree<Tab> = Tree::new(vec![]);
966+
tree.push_to_focused_leaf(Tab(0));
967+
let (n0, _t0) = tree.find_tab(&Tab(0)).unwrap();
968+
tree.split_below(n0, 0.5, vec![Tab(1)]);
969+
970+
let i1 = tree.find_tab(&Tab(1)).unwrap();
971+
tree.remove_tab(i1);
972+
assert_eq!(tree.nodes.len(), 1);
973+
974+
tree.retain_tabs(|_| true);
975+
assert!(tree.find_tab(&Tab(0)).is_some());
976+
}
977+
978+
/// Tests whether `retain_tabs` works correctly with trailing `Empty` nodes
979+
#[test]
980+
fn retain_trailing_empty() {
981+
let mut tree: Tree<Tab> = Tree::new(vec![]);
982+
tree.push_to_focused_leaf(Tab(0));
983+
tree.nodes.push(Node::Empty);
984+
tree.nodes.push(Node::Empty);
985+
986+
tree.retain_tabs(|_| true);
987+
assert!(tree.find_tab(&Tab(0)).is_some());
988+
}
989+
}

0 commit comments

Comments
 (0)