Skip to content

Commit 3338fc6

Browse files
committed
Add :tree-sitter-layers command to debug injection layers
Within a `<script>` tag in an HTML document this would show "html, javascript" for example. This could be useful for debugging injection queries or language detecting within markdown blocks.
1 parent f8b4b7a commit 3338fc6

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

book/src/generated/typable-cmd.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
| `:lsp-stop` | Stops the given language servers, or all language servers that are used by the current file if no arguments are supplied |
5959
| `:tree-sitter-scopes` | Display tree sitter scopes, primarily for theming and development. |
6060
| `:tree-sitter-highlight-name` | Display name of tree-sitter highlight scope under the cursor. |
61+
| `:tree-sitter-layers` | Display language names of tree-sitter injection layers under the cursor. |
6162
| `:debug-start`, `:dbg` | Start a debug session from a given template with given parameters. |
6263
| `:debug-remote`, `:dbg-tcp` | Connect to a debug adapter by TCP address and start a debugging session from a given template with given parameters. |
6364
| `:debug-eval` | Evaluate expression in current debug context. |

helix-term/src/commands/typed.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1848,6 +1848,56 @@ fn tree_sitter_highlight_name(
18481848
Ok(())
18491849
}
18501850

1851+
fn tree_sitter_layers(
1852+
cx: &mut compositor::Context,
1853+
_args: Args,
1854+
event: PromptEvent,
1855+
) -> anyhow::Result<()> {
1856+
if event != PromptEvent::Validate {
1857+
return Ok(());
1858+
}
1859+
1860+
let (view, doc) = current_ref!(cx.editor);
1861+
let Some(syntax) = doc.syntax() else {
1862+
bail!("Syntax information is not available");
1863+
};
1864+
1865+
let loader = cx.editor.syn_loader.load();
1866+
let text = doc.text().slice(..);
1867+
let cursor = doc.selection(view.id).primary().cursor(text);
1868+
let byte = text.char_to_byte(cursor) as u32;
1869+
let languages =
1870+
syntax
1871+
.layers_for_byte_range(byte, byte)
1872+
.fold(String::new(), |mut acc, layer| {
1873+
if !acc.is_empty() {
1874+
acc.push_str(", ");
1875+
}
1876+
acc.push_str(
1877+
&loader
1878+
.language(syntax.layer(layer).language)
1879+
.config()
1880+
.language_id,
1881+
);
1882+
acc
1883+
});
1884+
1885+
let callback = async move {
1886+
let call: job::Callback = Callback::EditorCompositor(Box::new(
1887+
move |editor: &mut Editor, compositor: &mut Compositor| {
1888+
let content = ui::Markdown::new(languages, editor.syn_loader.clone());
1889+
let popup = Popup::new("hover", content).auto_close(true);
1890+
compositor.replace_or_push("hover", popup);
1891+
},
1892+
));
1893+
Ok(call)
1894+
};
1895+
1896+
cx.jobs.callback(callback);
1897+
1898+
Ok(())
1899+
}
1900+
18511901
fn vsplit(cx: &mut compositor::Context, args: Args, event: PromptEvent) -> anyhow::Result<()> {
18521902
if event != PromptEvent::Validate {
18531903
return Ok(());
@@ -3363,6 +3413,17 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
33633413
..Signature::DEFAULT
33643414
},
33653415
},
3416+
TypableCommand {
3417+
name: "tree-sitter-layers",
3418+
aliases: &[],
3419+
doc: "Display language names of tree-sitter injection layers under the cursor.",
3420+
fun: tree_sitter_layers,
3421+
completer: CommandCompleter::none(),
3422+
signature: Signature {
3423+
positionals: (0, Some(0)),
3424+
..Signature::DEFAULT
3425+
},
3426+
},
33663427
TypableCommand {
33673428
name: "debug-start",
33683429
aliases: &["dbg"],

0 commit comments

Comments
 (0)