Skip to content

Commit 56cc4ce

Browse files
committed
Refactor tree-sitter debug to output s-exp
1 parent 25e1c1f commit 56cc4ce

1 file changed

Lines changed: 42 additions & 39 deletions

File tree

  • crates/plotnik-cli/src/commands/debug

crates/plotnik-cli/src/commands/debug/source.rs

Lines changed: 42 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -56,76 +56,79 @@ pub fn parse_tree(source: &str, lang: Lang) -> tree_sitter::Tree {
5656
}
5757

5858
pub fn format_ast(tree: &tree_sitter::Tree, source: &str, include_anonymous: bool) -> String {
59-
let mut output = String::new();
60-
format_node(&mut output, tree.root_node(), source, 0, include_anonymous);
61-
output
59+
format_node(tree.root_node(), source, 0, include_anonymous) + "\n"
6260
}
6361

6462
fn format_node(
65-
out: &mut String,
6663
node: tree_sitter::Node,
6764
source: &str,
6865
depth: usize,
6966
include_anonymous: bool,
70-
) {
71-
format_node_with_field(out, node, None, source, depth, include_anonymous);
67+
) -> String {
68+
format_node_with_field(node, None, source, depth, include_anonymous)
7269
}
7370

7471
fn format_node_with_field(
75-
out: &mut String,
7672
node: tree_sitter::Node,
7773
field_name: Option<&str>,
7874
source: &str,
7975
depth: usize,
8076
include_anonymous: bool,
81-
) {
77+
) -> String {
8278
if !include_anonymous && !node.is_named() {
83-
return;
79+
return String::new();
8480
}
8581

8682
let indent = " ".repeat(depth);
8783
let kind = node.kind();
8884
let field_prefix = field_name.map(|f| format!("{}: ", f)).unwrap_or_default();
8985

90-
if node.child_count() == 0 {
91-
let text = node
92-
.utf8_text(source.as_bytes())
93-
.unwrap_or("<invalid utf8>");
94-
if text == kind {
95-
out.push_str(&format!(
96-
"{}{}\"{}\"\n",
97-
indent,
98-
field_prefix,
99-
escape_string(kind)
100-
));
101-
} else {
102-
let escaped = escape_string(text);
103-
out.push_str(&format!(
104-
"{}{}{} \"{}\"\n",
105-
indent, field_prefix, kind, escaped
106-
));
107-
}
108-
} else {
109-
out.push_str(&format!("{}{}{}\n", indent, field_prefix, kind));
110-
86+
let children: Vec<_> = {
11187
let mut cursor = node.walk();
88+
let mut result = Vec::new();
11289
if cursor.goto_first_child() {
11390
loop {
11491
let child = cursor.node();
115-
let child_field = cursor.field_name();
116-
format_node_with_field(
117-
out,
118-
child,
119-
child_field,
120-
source,
121-
depth + 1,
122-
include_anonymous,
123-
);
92+
if include_anonymous || child.is_named() {
93+
result.push((child, cursor.field_name()));
94+
}
12495
if !cursor.goto_next_sibling() {
12596
break;
12697
}
12798
}
12899
}
100+
result
101+
};
102+
103+
if children.is_empty() {
104+
let text = node
105+
.utf8_text(source.as_bytes())
106+
.unwrap_or("<invalid utf8>");
107+
if text == kind {
108+
format!("{}{}(\"{}\")", indent, field_prefix, escape_string(kind))
109+
} else {
110+
format!(
111+
"{}{}({} \"{}\")",
112+
indent,
113+
field_prefix,
114+
kind,
115+
escape_string(text)
116+
)
117+
}
118+
} else {
119+
let mut out = format!("{}{}({}", indent, field_prefix, kind);
120+
for (child, child_field) in children {
121+
out.push('\n');
122+
out.push_str(&format_node_with_field(
123+
child,
124+
child_field,
125+
source,
126+
depth + 1,
127+
include_anonymous,
128+
));
129+
}
130+
out.push(')');
131+
out
129132
}
130133
}
131134

0 commit comments

Comments
 (0)