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.rs65
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()))
+}