mirror of
https://github.com/helix-editor/helix.git
synced 2025-10-06 00:13:28 +02:00
Add syntax symbol pickers based on tags.scm queries
This commit is contained in:
@@ -20,7 +20,10 @@ use ropey::RopeSlice;
|
||||
use tree_house::{
|
||||
highlighter,
|
||||
query_iter::QueryIter,
|
||||
tree_sitter::{Grammar, InactiveQueryCursor, InputEdit, Node, Query, RopeInput, Tree},
|
||||
tree_sitter::{
|
||||
query::{InvalidPredicateError, UserPredicate},
|
||||
Grammar, InactiveQueryCursor, InputEdit, Node, Query, RopeInput, Tree,
|
||||
},
|
||||
Error, InjectionLanguageMarker, LanguageConfig as SyntaxConfig, Layer,
|
||||
};
|
||||
|
||||
@@ -28,6 +31,7 @@ use crate::{indent::IndentQuery, tree_sitter, ChangeSet, Language};
|
||||
|
||||
pub use tree_house::{
|
||||
highlighter::{Highlight, HighlightEvent},
|
||||
query_iter::QueryIterEvent,
|
||||
Error as HighlighterError, LanguageLoader, TreeCursor, TREE_SITTER_MATCH_LIMIT,
|
||||
};
|
||||
|
||||
@@ -37,6 +41,7 @@ pub struct LanguageData {
|
||||
syntax: OnceCell<Option<SyntaxConfig>>,
|
||||
indent_query: OnceCell<Option<IndentQuery>>,
|
||||
textobject_query: OnceCell<Option<TextObjectQuery>>,
|
||||
tag_query: OnceCell<Option<TagQuery>>,
|
||||
}
|
||||
|
||||
impl LanguageData {
|
||||
@@ -46,6 +51,7 @@ impl LanguageData {
|
||||
syntax: OnceCell::new(),
|
||||
indent_query: OnceCell::new(),
|
||||
textobject_query: OnceCell::new(),
|
||||
tag_query: OnceCell::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,6 +160,44 @@ impl LanguageData {
|
||||
.as_ref()
|
||||
}
|
||||
|
||||
/// Compiles the tags.scm query for a language.
|
||||
/// This function should only be used by this module or the xtask crate.
|
||||
pub fn compile_tag_query(
|
||||
grammar: Grammar,
|
||||
config: &LanguageConfiguration,
|
||||
) -> Result<Option<TagQuery>> {
|
||||
let name = &config.language_id;
|
||||
let text = read_query(name, "tags.scm");
|
||||
if text.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
let query = Query::new(grammar, &text, |_pattern, predicate| match predicate {
|
||||
// TODO: these predicates are allowed in tags.scm queries but not yet used.
|
||||
UserPredicate::IsPropertySet { key: "local", .. } => Ok(()),
|
||||
UserPredicate::Other(pred) => match pred.name() {
|
||||
"strip!" | "select-adjacent!" => Ok(()),
|
||||
_ => Err(InvalidPredicateError::unknown(predicate)),
|
||||
},
|
||||
_ => Err(InvalidPredicateError::unknown(predicate)),
|
||||
})
|
||||
.with_context(|| format!("Failed to compile tags.scm query for '{name}'"))?;
|
||||
Ok(Some(TagQuery { query }))
|
||||
}
|
||||
|
||||
fn tag_query(&self, loader: &Loader) -> Option<&TagQuery> {
|
||||
self.tag_query
|
||||
.get_or_init(|| {
|
||||
let grammar = self.syntax_config(loader)?.grammar;
|
||||
Self::compile_tag_query(grammar, &self.config)
|
||||
.map_err(|err| {
|
||||
log::error!("{err}");
|
||||
})
|
||||
.ok()
|
||||
.flatten()
|
||||
})
|
||||
.as_ref()
|
||||
}
|
||||
|
||||
fn reconfigure(&self, scopes: &[String]) {
|
||||
if let Some(Some(config)) = self.syntax.get() {
|
||||
reconfigure_highlights(config, scopes);
|
||||
@@ -339,6 +383,10 @@ impl Loader {
|
||||
self.language(lang).textobject_query(self)
|
||||
}
|
||||
|
||||
pub fn tag_query(&self, lang: Language) -> Option<&TagQuery> {
|
||||
self.language(lang).tag_query(self)
|
||||
}
|
||||
|
||||
pub fn language_server_configs(&self) -> &HashMap<String, LanguageServerConfiguration> {
|
||||
&self.language_server_configs
|
||||
}
|
||||
@@ -511,6 +559,19 @@ impl Syntax {
|
||||
{
|
||||
QueryIter::new(&self.inner, source, loader, range)
|
||||
}
|
||||
|
||||
pub fn tags<'a>(
|
||||
&'a self,
|
||||
source: RopeSlice<'a>,
|
||||
loader: &'a Loader,
|
||||
range: impl RangeBounds<u32>,
|
||||
) -> QueryIter<'a, 'a, impl FnMut(Language) -> Option<&'a Query> + 'a, ()> {
|
||||
self.query_iter(
|
||||
source,
|
||||
|lang| loader.tag_query(lang).map(|q| &q.query),
|
||||
range,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub type Highlighter<'a> = highlighter::Highlighter<'a, 'a, Loader>;
|
||||
@@ -881,6 +942,11 @@ impl TextObjectQuery {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TagQuery {
|
||||
pub query: Query,
|
||||
}
|
||||
|
||||
pub fn pretty_print_tree<W: fmt::Write>(fmt: &mut W, node: Node) -> fmt::Result {
|
||||
if node.child_count() == 0 {
|
||||
if node_is_visible(&node) {
|
||||
|
Reference in New Issue
Block a user