pull/13492/merge
Rafael Oliveira 2025-06-16 08:35:52 -06:00 committed by GitHub
commit 349530bc21
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 84 additions and 1 deletions

View File

@ -1,4 +1,4 @@
use std::{borrow::Cow, collections::HashMap, iter};
use std::{borrow::Cow, collections::BTreeMap, collections::HashMap, iter};
use helix_stdx::rope::RopeSliceExt;
use tree_house::TREE_SITTER_MATCH_LIMIT;
@ -1102,6 +1102,41 @@ pub fn get_scopes<'a>(syntax: Option<&'a Syntax>, text: RopeSlice, pos: usize) -
scopes
}
pub fn get_breadcrumbs(syntax: Option<&Syntax>, text: RopeSlice, pos: usize) -> Vec<String> {
let mut breadcrumb_set: BTreeMap<usize, String> = BTreeMap::new();
if let Some(syntax) = syntax {
let pos = text.char_to_byte(pos);
let mut node = match syntax
.tree()
.root_node()
.descendant_for_byte_range(pos, pos)
{
Some(node) => node,
None => return vec![],
};
while let Some(parent) = node.parent() {
if node.is_extra() {
continue;
}
if node.is_named() {
let line_idx = text.byte_to_line(parent.start_byte());
let line: String = text.line(line_idx).into();
breadcrumb_set.insert(line_idx, format!("{}: {}", line_idx + 1, line.trim_end()));
}
node = parent;
}
}
let breadcrumbs: Vec<String> = breadcrumb_set
.into_iter()
.map(|(_k, v)| v.into())
// Remove the `source_code` node
.skip(1)
.collect();
breadcrumbs
}
#[cfg(test)]
mod test {
use super::*;

View File

@ -1667,6 +1667,43 @@ fn tree_sitter_scopes(
Ok(())
}
fn tree_sitter_breadcrumbs(
cx: &mut compositor::Context,
_args: Args,
event: PromptEvent,
) -> anyhow::Result<()> {
if event != PromptEvent::Validate {
return Ok(());
}
let (view, doc) = current!(cx.editor);
let text = doc.text().slice(..);
let pos = doc.selection(view.id).primary().cursor(text);
let breadcrumbs = indent::get_breadcrumbs(doc.syntax(), text, pos);
let language = match doc.language_config() {
Some(l) => &l.language_id,
None => "txt",
};
let contents = format!("```{}\n{}\n```\n", language, breadcrumbs.join("\n"));
let callback = async move {
let call: job::Callback = Callback::EditorCompositor(Box::new(
move |editor: &mut Editor, compositor: &mut Compositor| {
let contents = ui::Markdown::new(contents, editor.syn_loader.clone());
let popup = Popup::new("hover", contents).auto_close(true);
compositor.replace_or_push("hover", popup);
},
));
Ok(call)
};
cx.jobs.callback(callback);
Ok(())
}
fn tree_sitter_highlight_name(
cx: &mut compositor::Context,
_args: Args,
@ -3191,6 +3228,17 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
..Signature::DEFAULT
},
},
TypableCommand {
name: "tree-sitter-breadcrumbs",
aliases: &["breadcrumbs", "bread"],
doc: "Display lines of parents to reach the token under the cursor. Useful to know where you are in the program.",
fun: tree_sitter_breadcrumbs,
completer: CommandCompleter::none(),
signature: Signature {
positionals: (0, Some(0)),
..Signature::DEFAULT
},
},
TypableCommand {
name: "tree-sitter-highlight-name",
aliases: &[],