|
|
@ -129,60 +129,25 @@ impl<'a, T> DoubleEndedIterator for TreeIter<'a, T> {
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a, T> ExactSizeIterator for TreeIter<'a, T> {}
|
|
|
|
impl<'a, T> ExactSizeIterator for TreeIter<'a, T> {}
|
|
|
|
|
|
|
|
|
|
|
|
impl<T: Clone + TreeItem> Tree<T> {
|
|
|
|
|
|
|
|
pub fn filter<P>(tree: &Tree<T>, predicate: &P) -> Option<Tree<T>>
|
|
|
|
|
|
|
|
where
|
|
|
|
|
|
|
|
P: Fn(&T) -> bool,
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let children = tree
|
|
|
|
|
|
|
|
.children
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.filter_map(|tree| Self::filter(tree, predicate))
|
|
|
|
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
|
|
|
if tree.item.is_parent() || predicate(&tree.item) {
|
|
|
|
|
|
|
|
let mut tree = Tree {
|
|
|
|
|
|
|
|
item: tree.item.clone(),
|
|
|
|
|
|
|
|
parent_index: tree.parent_index,
|
|
|
|
|
|
|
|
index: tree.index,
|
|
|
|
|
|
|
|
is_opened: tree.is_opened,
|
|
|
|
|
|
|
|
children,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
tree.regenerate_index();
|
|
|
|
|
|
|
|
Some(tree)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<T: TreeItem> Tree<T> {
|
|
|
|
impl<T: TreeItem> Tree<T> {
|
|
|
|
fn open(&mut self, filter: &String) -> Result<()> {
|
|
|
|
fn open(&mut self, filter: &String) -> Result<()> {
|
|
|
|
if self.item.is_parent() {
|
|
|
|
if self.item.is_parent() {
|
|
|
|
self.children = vec_to_tree(
|
|
|
|
self.children = self.get_filtered_children(filter)?;
|
|
|
|
self.item
|
|
|
|
|
|
|
|
.get_children()?
|
|
|
|
|
|
|
|
.into_iter()
|
|
|
|
|
|
|
|
.filter(|item| item.name().to_lowercase().contains(&filter.to_lowercase()))
|
|
|
|
|
|
|
|
.collect(),
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
self.is_opened = true;
|
|
|
|
self.is_opened = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn close(&mut self) {
|
|
|
|
|
|
|
|
self.is_opened = false;
|
|
|
|
|
|
|
|
self.children = vec![];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn refresh(&mut self, filter: &String) -> Result<()> {
|
|
|
|
fn refresh(&mut self, filter: &String) -> Result<()> {
|
|
|
|
if !self.is_opened {
|
|
|
|
if !self.is_opened {
|
|
|
|
return Ok(());
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let latest_children = vec_to_tree(
|
|
|
|
let latest_children = self.get_filtered_children(filter)?;
|
|
|
|
self.item
|
|
|
|
|
|
|
|
.get_children()?
|
|
|
|
|
|
|
|
.into_iter()
|
|
|
|
|
|
|
|
.filter(|item| {
|
|
|
|
|
|
|
|
item.is_parent() || item.name().to_lowercase().contains(&filter.to_lowercase())
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.collect(),
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
let filtered = std::mem::replace(&mut self.children, vec![])
|
|
|
|
let filtered = std::mem::replace(&mut self.children, vec![])
|
|
|
|
.into_iter()
|
|
|
|
.into_iter()
|
|
|
|
// Remove children that does not exists in latest_children
|
|
|
|
// Remove children that does not exists in latest_children
|
|
|
@ -216,6 +181,18 @@ impl<T: TreeItem> Tree<T> {
|
|
|
|
Ok(())
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn get_filtered_children(&self, filter: &String) -> Result<Vec<Tree<T>>> {
|
|
|
|
|
|
|
|
Ok(vec_to_tree(
|
|
|
|
|
|
|
|
self.item
|
|
|
|
|
|
|
|
.get_children()?
|
|
|
|
|
|
|
|
.into_iter()
|
|
|
|
|
|
|
|
.filter(|item| {
|
|
|
|
|
|
|
|
item.is_parent() || item.name().to_lowercase().contains(&filter.to_lowercase())
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.collect(),
|
|
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn sort(&mut self) {
|
|
|
|
fn sort(&mut self) {
|
|
|
|
self.children
|
|
|
|
self.children
|
|
|
|
.sort_by(|a, b| tree_item_cmp(&a.item, &b.item))
|
|
|
|
.sort_by(|a, b| tree_item_cmp(&a.item, &b.item))
|
|
|
@ -514,23 +491,9 @@ impl<T: TreeItem> TreeView<T> {
|
|
|
|
selected_index: usize,
|
|
|
|
selected_index: usize,
|
|
|
|
filter: &String,
|
|
|
|
filter: &String,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
// if let Some(next_level) = self.next_item().map(|elem| elem.level) {
|
|
|
|
let selected_item = self.get_mut(selected_index);
|
|
|
|
// let current = self.find_by_index(selected_index);
|
|
|
|
|
|
|
|
// let current_level = current.level;
|
|
|
|
|
|
|
|
// if next_level > current_level {
|
|
|
|
|
|
|
|
// // if let Some(mut on_folded_fn) = self.on_folded_fn.take() {
|
|
|
|
|
|
|
|
// // on_folded_fn(&mut current.item, cx, params);
|
|
|
|
|
|
|
|
// // self.on_folded_fn = Some(on_folded_fn);
|
|
|
|
|
|
|
|
// // }
|
|
|
|
|
|
|
|
// self.fold_current_child();
|
|
|
|
|
|
|
|
// return;
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
let mut selected_item = self.get_mut(selected_index);
|
|
|
|
|
|
|
|
if selected_item.is_opened {
|
|
|
|
if selected_item.is_opened {
|
|
|
|
selected_item.is_opened = false;
|
|
|
|
selected_item.close();
|
|
|
|
selected_item.children = vec![];
|
|
|
|
|
|
|
|
self.regenerate_index();
|
|
|
|
self.regenerate_index();
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -553,15 +516,6 @@ impl<T: TreeItem> TreeView<T> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn fold_current_child(&mut self) {
|
|
|
|
|
|
|
|
if let Some(parent) = self.current_parent_mut() {
|
|
|
|
|
|
|
|
parent.is_opened = false;
|
|
|
|
|
|
|
|
parent.children = vec![];
|
|
|
|
|
|
|
|
self.selected = parent.index;
|
|
|
|
|
|
|
|
self.regenerate_index()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn search_next(&mut self, s: &str) {
|
|
|
|
pub fn search_next(&mut self, s: &str) {
|
|
|
|
let skip = std::cmp::max(2, self.save_view.0 + 1);
|
|
|
|
let skip = std::cmp::max(2, self.save_view.0 + 1);
|
|
|
|
self.set_selected(
|
|
|
|
self.set_selected(
|
|
|
@ -684,14 +638,6 @@ impl<T: TreeItem> TreeView<T> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn current_parent_mut(&mut self) -> Option<&mut Tree<T>> {
|
|
|
|
|
|
|
|
if let Some(parent_index) = self.current().parent_index {
|
|
|
|
|
|
|
|
Some(self.get_mut(parent_index))
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn current_item(&self) -> &T {
|
|
|
|
pub fn current_item(&self) -> &T {
|
|
|
|
&self.current().item
|
|
|
|
&self.current().item
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -718,10 +664,10 @@ impl<T: TreeItem> TreeView<T> {
|
|
|
|
let item_name = item.name();
|
|
|
|
let item_name = item.name();
|
|
|
|
if !tree.is_opened {
|
|
|
|
if !tree.is_opened {
|
|
|
|
tree.open(filter)?;
|
|
|
|
tree.open(filter)?;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
tree.refresh(filter)?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tree.children.push(Tree::new(item, vec![]));
|
|
|
|
|
|
|
|
tree.children
|
|
|
|
|
|
|
|
.sort_by(|a, b| tree_item_cmp(&a.item, &b.item));
|
|
|
|
|
|
|
|
self.regenerate_index();
|
|
|
|
self.regenerate_index();
|
|
|
|
|
|
|
|
|
|
|
|
let tree = self.get(index);
|
|
|
|
let tree = self.get(index);
|
|
|
@ -893,7 +839,6 @@ impl<T: TreeItem + Clone> TreeView<T> {
|
|
|
|
key!('j') | key!(Tab) | key!(Down) | ctrl!('j') => self.move_down(1.max(count)),
|
|
|
|
key!('j') | key!(Tab) | key!(Down) | ctrl!('j') => self.move_down(1.max(count)),
|
|
|
|
key!('z') => {
|
|
|
|
key!('z') => {
|
|
|
|
self.on_next_key = Some(Box::new(|_, tree, event| match event.into() {
|
|
|
|
self.on_next_key = Some(Box::new(|_, tree, event| match event.into() {
|
|
|
|
key!('f') => tree.fold_current_child(),
|
|
|
|
|
|
|
|
key!('z') => tree.align_view_center(),
|
|
|
|
key!('z') => tree.align_view_center(),
|
|
|
|
key!('t') => tree.align_view_top(),
|
|
|
|
key!('t') => tree.align_view_top(),
|
|
|
|
key!('b') => tree.align_view_bottom(),
|
|
|
|
key!('b') => tree.align_view_bottom(),
|
|
|
@ -965,8 +910,6 @@ fn index_elems<T>(parent_index: usize, elems: Vec<Tree<T>>) -> Vec<Tree<T>> {
|
|
|
|
mod test_tree {
|
|
|
|
mod test_tree {
|
|
|
|
use helix_core::movement::Direction;
|
|
|
|
use helix_core::movement::Direction;
|
|
|
|
|
|
|
|
|
|
|
|
use crate::ui::TreeItem;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use super::Tree;
|
|
|
|
use super::Tree;
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[test]
|
|
|
@ -1118,95 +1061,6 @@ mod test_tree {
|
|
|
|
assert_eq!(result, Some(3));
|
|
|
|
assert_eq!(result, Some(3));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
|
|
fn test_filter() {
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
|
|
|
|
|
|
struct MyItem<'a>(bool, &'a str);
|
|
|
|
|
|
|
|
impl<'a> TreeItem for MyItem<'a> {
|
|
|
|
|
|
|
|
type Params = ();
|
|
|
|
|
|
|
|
fn name(&self) -> String {
|
|
|
|
|
|
|
|
self.0.to_string()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_child(&self, _: &Self) -> bool {
|
|
|
|
|
|
|
|
!self.0
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_parent(&self) -> bool {
|
|
|
|
|
|
|
|
self.0
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
|
|
|
|
|
|
|
self.1.cmp(other.1)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
let tree = Tree::new(
|
|
|
|
|
|
|
|
MyItem(false, ".cargo"),
|
|
|
|
|
|
|
|
vec![
|
|
|
|
|
|
|
|
Tree::new(
|
|
|
|
|
|
|
|
MyItem(true, "spam"),
|
|
|
|
|
|
|
|
vec![Tree::new(MyItem(false, "Cargo.toml"), vec![])],
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
Tree::new(
|
|
|
|
|
|
|
|
MyItem(true, "Cargo.toml"),
|
|
|
|
|
|
|
|
vec![Tree::new(MyItem(false, "pam"), vec![])],
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
Tree::new(MyItem(false, "hello"), vec![]),
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let result = Tree::filter(&tree, &|item| item.1.to_lowercase().contains("cargo"));
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
|
|
result,
|
|
|
|
|
|
|
|
Some(Tree::new(
|
|
|
|
|
|
|
|
MyItem(false, ".cargo"),
|
|
|
|
|
|
|
|
vec![
|
|
|
|
|
|
|
|
Tree::new(
|
|
|
|
|
|
|
|
MyItem(true, "spam"),
|
|
|
|
|
|
|
|
vec![Tree::new(MyItem(false, "Cargo.toml"), vec![])]
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
Tree {
|
|
|
|
|
|
|
|
is_opened: true,
|
|
|
|
|
|
|
|
..Tree::new(MyItem(true, "Cargo.toml"), vec![])
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let result = Tree::filter(&tree, &|item| item.1.to_lowercase().contains("pam"));
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
|
|
result,
|
|
|
|
|
|
|
|
Some(Tree::new(
|
|
|
|
|
|
|
|
MyItem(false, ".cargo"),
|
|
|
|
|
|
|
|
vec![
|
|
|
|
|
|
|
|
Tree {
|
|
|
|
|
|
|
|
is_opened: true,
|
|
|
|
|
|
|
|
..Tree::new(MyItem(true, "spam"), vec![])
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
Tree::new(
|
|
|
|
|
|
|
|
MyItem(true, "Cargo.toml"),
|
|
|
|
|
|
|
|
vec![Tree::new(MyItem(false, "pam"), vec![])]
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let result = Tree::filter(&tree, &|item| item.1.to_lowercase().contains("helix"));
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
|
|
result,
|
|
|
|
|
|
|
|
Some(Tree::new(
|
|
|
|
|
|
|
|
MyItem(false, ".cargo"),
|
|
|
|
|
|
|
|
vec![
|
|
|
|
|
|
|
|
Tree {
|
|
|
|
|
|
|
|
is_opened: true,
|
|
|
|
|
|
|
|
..Tree::new(MyItem(true, "spam"), vec![])
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
Tree {
|
|
|
|
|
|
|
|
is_opened: true,
|
|
|
|
|
|
|
|
..Tree::new(MyItem(true, "Cargo.toml"), vec![])
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[test]
|
|
|
|
fn test_remove() {
|
|
|
|
fn test_remove() {
|
|
|
|
let mut tree = Tree::new(
|
|
|
|
let mut tree = Tree::new(
|
|
|
|