Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-syntax/src/pretty_print.rs')
| -rw-r--r-- | helix-syntax/src/pretty_print.rs | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/helix-syntax/src/pretty_print.rs b/helix-syntax/src/pretty_print.rs new file mode 100644 index 00000000..bd108229 --- /dev/null +++ b/helix-syntax/src/pretty_print.rs @@ -0,0 +1,65 @@ +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())) +} |