mirror of https://github.com/helix-editor/helix
66 lines
1.6 KiB
Rust
66 lines
1.6 KiB
Rust
|
use std::fmt;
|
||
|
|
||
|
use tree_sitter::{Node, TreeCursor};
|
||
|
|
||
|
pub fn pretty_print_tree<W: fmt::Write>(fmt: &mut W, node: Node) -> fmt::Result {
|
||
|
if node.child_count() == 0 {
|
||
|
if node_is_visible(&node) {
|
||
|
write!(fmt, "({})", node.kind())
|
||
|
} else {
|
||
|
write!(fmt, "\"{}\"", node.kind())
|
||
|
}
|
||
|
} else {
|
||
|
pretty_print_tree_impl(fmt, &mut node.walk(), 0)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn pretty_print_tree_impl<W: fmt::Write>(
|
||
|
fmt: &mut W,
|
||
|
cursor: &mut TreeCursor,
|
||
|
depth: usize,
|
||
|
) -> fmt::Result {
|
||
|
let node = cursor.node();
|
||
|
let visible = node_is_visible(&node);
|
||
|
|
||
|
if visible {
|
||
|
let indentation_columns = depth * 2;
|
||
|
write!(fmt, "{:indentation_columns$}", "")?;
|
||
|
|
||
|
if let Some(field_name) = cursor.field_name() {
|
||
|
write!(fmt, "{}: ", field_name)?;
|
||
|
}
|
||
|
|
||
|
write!(fmt, "({}", node.kind())?;
|
||
|
}
|
||
|
|
||
|
// Handle children.
|
||
|
if cursor.goto_first_child() {
|
||
|
loop {
|
||
|
if node_is_visible(&cursor.node()) {
|
||
|
fmt.write_char('\n')?;
|
||
|
}
|
||
|
|
||
|
pretty_print_tree_impl(fmt, cursor, depth + 1)?;
|
||
|
|
||
|
if !cursor.goto_next_sibling() {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let moved = cursor.goto_parent();
|
||
|
// The parent of the first child must exist, and must be `node`.
|
||
|
debug_assert!(moved);
|
||
|
debug_assert!(cursor.node() == node);
|
||
|
}
|
||
|
|
||
|
if visible {
|
||
|
fmt.write_char(')')?;
|
||
|
}
|
||
|
|
||
|
Ok(())
|
||
|
}
|
||
|
|
||
|
fn node_is_visible(node: &Node) -> bool {
|
||
|
node.is_missing() || (node.is_named() && node.language().node_kind_is_visible(node.kind_id()))
|
||
|
}
|