mirror of
https://github.com/helix-editor/helix.git
synced 2024-11-25 19:03:30 +04:00
Pretty print tree-sitter-subtree
expression (#4295)
This commit is contained in:
parent
a7e7c2cc05
commit
4174b25b3d
@ -2030,6 +2030,57 @@ fn next(&mut self) -> Option<Self::Item> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn pretty_print_tree<W: fmt::Write>(fmt: &mut W, node: Node) -> fmt::Result {
|
||||||
|
pretty_print_tree_impl(fmt, node, true, None, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pretty_print_tree_impl<W: fmt::Write>(
|
||||||
|
fmt: &mut W,
|
||||||
|
node: Node,
|
||||||
|
is_root: bool,
|
||||||
|
field_name: Option<&str>,
|
||||||
|
depth: usize,
|
||||||
|
) -> fmt::Result {
|
||||||
|
fn is_visible(node: Node) -> bool {
|
||||||
|
node.is_missing()
|
||||||
|
|| (node.is_named() && node.language().node_kind_is_visible(node.kind_id()))
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_visible(node) {
|
||||||
|
let indentation_columns = depth * 2;
|
||||||
|
write!(fmt, "{:indentation_columns$}", "")?;
|
||||||
|
|
||||||
|
if let Some(field_name) = field_name {
|
||||||
|
write!(fmt, "{}: ", field_name)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(fmt, "({}", node.kind())?;
|
||||||
|
} else if is_root {
|
||||||
|
write!(fmt, "(\"{}\")", node.kind())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for child_idx in 0..node.child_count() {
|
||||||
|
if let Some(child) = node.child(child_idx) {
|
||||||
|
if is_visible(child) {
|
||||||
|
fmt.write_char('\n')?;
|
||||||
|
}
|
||||||
|
|
||||||
|
pretty_print_tree_impl(
|
||||||
|
fmt,
|
||||||
|
child,
|
||||||
|
false,
|
||||||
|
node.field_name_for_child(child_idx as u32),
|
||||||
|
depth + 1,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_visible(node) {
|
||||||
|
write!(fmt, ")")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -2201,6 +2252,63 @@ fn test_input_edits() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn assert_pretty_print(source: &str, expected: &str, start: usize, end: usize) {
|
||||||
|
let source = Rope::from_str(source);
|
||||||
|
|
||||||
|
let loader = Loader::new(Configuration { language: vec![] });
|
||||||
|
let language = get_language("Rust").unwrap();
|
||||||
|
|
||||||
|
let config = HighlightConfiguration::new(language, "", "", "").unwrap();
|
||||||
|
let syntax = Syntax::new(&source, Arc::new(config), Arc::new(loader));
|
||||||
|
|
||||||
|
let root = syntax
|
||||||
|
.tree()
|
||||||
|
.root_node()
|
||||||
|
.descendant_for_byte_range(start, end)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut output = String::new();
|
||||||
|
pretty_print_tree(&mut output, root).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(expected, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_pretty_print() {
|
||||||
|
let source = r#"/// Hello"#;
|
||||||
|
assert_pretty_print(source, "(line_comment)", 0, source.len());
|
||||||
|
|
||||||
|
// A large tree should be indented with fields:
|
||||||
|
let source = r#"fn main() {
|
||||||
|
println!("Hello, World!");
|
||||||
|
}"#;
|
||||||
|
assert_pretty_print(
|
||||||
|
source,
|
||||||
|
concat!(
|
||||||
|
"(function_item\n",
|
||||||
|
" name: (identifier)\n",
|
||||||
|
" parameters: (parameters)\n",
|
||||||
|
" body: (block\n",
|
||||||
|
" (expression_statement\n",
|
||||||
|
" (macro_invocation\n",
|
||||||
|
" macro: (identifier)\n",
|
||||||
|
" (token_tree\n",
|
||||||
|
" (string_literal))))))",
|
||||||
|
),
|
||||||
|
0,
|
||||||
|
source.len(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Selecting a token should print just that token:
|
||||||
|
let source = r#"fn main() {}"#;
|
||||||
|
assert_pretty_print(source, r#"("fn")"#, 0, 1);
|
||||||
|
|
||||||
|
// Error nodes are printed as errors:
|
||||||
|
let source = r#"}{"#;
|
||||||
|
assert_pretty_print(source, "(ERROR)", 0, source.len());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_load_runtime_file() {
|
fn test_load_runtime_file() {
|
||||||
// Test to make sure we can load some data from the runtime directory.
|
// Test to make sure we can load some data from the runtime directory.
|
||||||
|
@ -1487,7 +1487,9 @@ fn tree_sitter_subtree(
|
|||||||
.root_node()
|
.root_node()
|
||||||
.descendant_for_byte_range(from, to)
|
.descendant_for_byte_range(from, to)
|
||||||
{
|
{
|
||||||
let contents = format!("```tsq\n{}\n```", selected_node.to_sexp());
|
let mut contents = String::from("```tsq\n");
|
||||||
|
helix_core::syntax::pretty_print_tree(&mut contents, selected_node)?;
|
||||||
|
contents.push_str("\n```");
|
||||||
|
|
||||||
let callback = async move {
|
let callback = async move {
|
||||||
let call: job::Callback =
|
let call: job::Callback =
|
||||||
|
Loading…
Reference in New Issue
Block a user