diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 5c26a5b2a5f5..a1a7b88cc099 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -400,6 +400,7 @@ impl MappableCommand { decrement, "Decrement", record_macro, "Record macro", replay_macro, "Replay macro", + show_subtree, "Show tree-sitter subtree under primary selection", ); } @@ -5388,8 +5389,8 @@ fn hover(cx: &mut Context) { // skip if contents empty let contents = ui::Markdown::new(contents, editor.syn_loader.clone()); - let popup = Popup::new("documentation", contents); - if let Some(doc_popup) = compositor.find_id("documentation") { + let popup = Popup::new("hover", contents); + if let Some(doc_popup) = compositor.find_id("hover") { *doc_popup = popup; } else { compositor.push(Box::new(popup)); @@ -6210,3 +6211,33 @@ fn replay_macro(cx: &mut Context) { }, )); } + +fn show_subtree(cx: &mut Context) { + let (view, doc) = current!(cx.editor); + + if let Some(syntax) = doc.syntax() { + let primary_selection = doc.selection(view.id).primary(); + let text = doc.text(); + let from = text.char_to_byte(primary_selection.from()); + let to = text.char_to_byte(primary_selection.to()); + if let Some(selected_node) = syntax + .tree() + .root_node() + .descendant_for_byte_range(from, to) + { + let contents = format!("```tsq\n{}\n```", selected_node.to_sexp()); + + cx.callback = Some(Box::new( + move |compositor: &mut Compositor, cx: &mut compositor::Context| { + let contents = ui::Markdown::new(contents, cx.editor.syn_loader.clone()); + let popup = Popup::new("hover", contents); + if let Some(doc_popup) = compositor.find_id("hover") { + *doc_popup = popup; + } else { + compositor.push(Box::new(popup)); + } + }, + )); + } + } +} diff --git a/languages.toml b/languages.toml index 3e2e7b15c730..92602f0a7adb 100644 --- a/languages.toml +++ b/languages.toml @@ -377,6 +377,7 @@ scope = "source.tsq" file-types = ["scm"] roots = [] comment-token = ";" +injection-regex = "tsq" indent = { tab-width = 2, unit = " " } [[language]]