Add textobjects queries (#20924)
Co-Authored-By: Max <max@zed.dev> Release Notes: - vim: Added motions `[[`, `[]`, `]]`, `][` for navigating by section, `[m`, `]m`, `[M`, `]M` for navigating by method, and `[*`, `]*`, `[/`, `]/` for comments. These currently only work for languages built in to Zed, as they are powered by new tree-sitter queries. - vim: Added new text objects: `ic`, `ac` for inside/around classes, `if`,`af` for functions/methods, and `g c` for comments. These currently only work for languages built in to Zed, as they are powered by new tree-sitter queries. --------- Co-authored-by: Max <max@zed.dev>
This commit is contained in:
parent
c443307c19
commit
75c9dc179b
28 changed files with 1205 additions and 26 deletions
|
@ -78,7 +78,7 @@ pub use language_registry::{
|
|||
};
|
||||
pub use lsp::LanguageServerId;
|
||||
pub use outline::*;
|
||||
pub use syntax_map::{OwnedSyntaxLayer, SyntaxLayer};
|
||||
pub use syntax_map::{OwnedSyntaxLayer, SyntaxLayer, TreeSitterOptions};
|
||||
pub use text::{AnchorRangeExt, LineEnding};
|
||||
pub use tree_sitter::{Node, Parser, Tree, TreeCursor};
|
||||
|
||||
|
@ -848,6 +848,7 @@ pub struct Grammar {
|
|||
pub(crate) runnable_config: Option<RunnableConfig>,
|
||||
pub(crate) indents_config: Option<IndentConfig>,
|
||||
pub outline_config: Option<OutlineConfig>,
|
||||
pub text_object_config: Option<TextObjectConfig>,
|
||||
pub embedding_config: Option<EmbeddingConfig>,
|
||||
pub(crate) injection_config: Option<InjectionConfig>,
|
||||
pub(crate) override_config: Option<OverrideConfig>,
|
||||
|
@ -873,6 +874,44 @@ pub struct OutlineConfig {
|
|||
pub annotation_capture_ix: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum TextObject {
|
||||
InsideFunction,
|
||||
AroundFunction,
|
||||
InsideClass,
|
||||
AroundClass,
|
||||
InsideComment,
|
||||
AroundComment,
|
||||
}
|
||||
|
||||
impl TextObject {
|
||||
pub fn from_capture_name(name: &str) -> Option<TextObject> {
|
||||
match name {
|
||||
"function.inside" => Some(TextObject::InsideFunction),
|
||||
"function.around" => Some(TextObject::AroundFunction),
|
||||
"class.inside" => Some(TextObject::InsideClass),
|
||||
"class.around" => Some(TextObject::AroundClass),
|
||||
"comment.inside" => Some(TextObject::InsideComment),
|
||||
"comment.around" => Some(TextObject::AroundComment),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn around(&self) -> Option<Self> {
|
||||
match self {
|
||||
TextObject::InsideFunction => Some(TextObject::AroundFunction),
|
||||
TextObject::InsideClass => Some(TextObject::AroundClass),
|
||||
TextObject::InsideComment => Some(TextObject::AroundComment),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TextObjectConfig {
|
||||
pub query: Query,
|
||||
pub text_objects_by_capture_ix: Vec<(u32, TextObject)>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct EmbeddingConfig {
|
||||
pub query: Query,
|
||||
|
@ -950,6 +989,7 @@ impl Language {
|
|||
highlights_query: None,
|
||||
brackets_config: None,
|
||||
outline_config: None,
|
||||
text_object_config: None,
|
||||
embedding_config: None,
|
||||
indents_config: None,
|
||||
injection_config: None,
|
||||
|
@ -1020,7 +1060,12 @@ impl Language {
|
|||
if let Some(query) = queries.runnables {
|
||||
self = self
|
||||
.with_runnable_query(query.as_ref())
|
||||
.context("Error loading tests query")?;
|
||||
.context("Error loading runnables query")?;
|
||||
}
|
||||
if let Some(query) = queries.text_objects {
|
||||
self = self
|
||||
.with_text_object_query(query.as_ref())
|
||||
.context("Error loading textobject query")?;
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
|
@ -1097,6 +1142,26 @@ impl Language {
|
|||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn with_text_object_query(mut self, source: &str) -> Result<Self> {
|
||||
let grammar = self
|
||||
.grammar_mut()
|
||||
.ok_or_else(|| anyhow!("cannot mutate grammar"))?;
|
||||
let query = Query::new(&grammar.ts_language, source)?;
|
||||
|
||||
let mut text_objects_by_capture_ix = Vec::new();
|
||||
for (ix, name) in query.capture_names().iter().enumerate() {
|
||||
if let Some(text_object) = TextObject::from_capture_name(name) {
|
||||
text_objects_by_capture_ix.push((ix as u32, text_object));
|
||||
}
|
||||
}
|
||||
|
||||
grammar.text_object_config = Some(TextObjectConfig {
|
||||
query,
|
||||
text_objects_by_capture_ix,
|
||||
});
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn with_embedding_query(mut self, source: &str) -> Result<Self> {
|
||||
let grammar = self
|
||||
.grammar_mut()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue