Start work on language config overrides
Co-authored-by: Julia Risley <julia@zed.dev>
This commit is contained in:
parent
86371d9f5e
commit
1851e2e77c
8 changed files with 189 additions and 23 deletions
|
@ -22,7 +22,10 @@ use lazy_static::lazy_static;
|
|||
use parking_lot::{Mutex, RwLock};
|
||||
use postage::watch;
|
||||
use regex::Regex;
|
||||
use serde::{de, Deserialize, Deserializer};
|
||||
use serde::{
|
||||
de::{self},
|
||||
Deserialize, Deserializer,
|
||||
};
|
||||
use serde_json::Value;
|
||||
use std::{
|
||||
any::Any,
|
||||
|
@ -243,6 +246,45 @@ pub struct LanguageConfig {
|
|||
pub line_comment: Option<Arc<str>>,
|
||||
#[serde(default)]
|
||||
pub block_comment: Option<(Arc<str>, Arc<str>)>,
|
||||
#[serde(default)]
|
||||
pub overrides: HashMap<String, LanguageConfigOverride>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct LanguageConfigYeet {
|
||||
language: Arc<Language>,
|
||||
override_id: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct LanguageConfigOverride {
|
||||
#[serde(default)]
|
||||
pub line_comment: Override<Arc<str>>,
|
||||
#[serde(default)]
|
||||
pub block_comment: Override<(Arc<str>, Arc<str>)>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum Override<T> {
|
||||
Remove { remove: bool },
|
||||
Set(T),
|
||||
}
|
||||
|
||||
impl<T> Default for Override<T> {
|
||||
fn default() -> Self {
|
||||
Override::Remove { remove: false }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Override<T> {
|
||||
fn as_option<'a>(this: Option<&'a Self>, original: &'a Option<T>) -> Option<&'a T> {
|
||||
match this {
|
||||
Some(Self::Set(value)) => Some(value),
|
||||
Some(Self::Remove { remove: true }) => None,
|
||||
Some(Self::Remove { remove: false }) | None => original.as_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for LanguageConfig {
|
||||
|
@ -257,6 +299,7 @@ impl Default for LanguageConfig {
|
|||
autoclose_before: Default::default(),
|
||||
line_comment: Default::default(),
|
||||
block_comment: Default::default(),
|
||||
overrides: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -311,6 +354,7 @@ pub struct Grammar {
|
|||
pub(crate) indents_config: Option<IndentConfig>,
|
||||
pub(crate) outline_config: Option<OutlineConfig>,
|
||||
pub(crate) injection_config: Option<InjectionConfig>,
|
||||
pub(crate) override_config: Option<OverrideConfig>,
|
||||
pub(crate) highlight_map: Mutex<HighlightMap>,
|
||||
}
|
||||
|
||||
|
@ -336,6 +380,11 @@ struct InjectionConfig {
|
|||
patterns: Vec<InjectionPatternConfig>,
|
||||
}
|
||||
|
||||
struct OverrideConfig {
|
||||
query: Query,
|
||||
values: HashMap<u32, LanguageConfigOverride>,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
struct InjectionPatternConfig {
|
||||
language: Option<Box<str>>,
|
||||
|
@ -635,6 +684,7 @@ impl Language {
|
|||
outline_config: None,
|
||||
indents_config: None,
|
||||
injection_config: None,
|
||||
override_config: None,
|
||||
ts_language,
|
||||
highlight_map: Default::default(),
|
||||
})
|
||||
|
@ -775,6 +825,25 @@ impl Language {
|
|||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn with_override_query(mut self, source: &str) -> Result<Self> {
|
||||
let query = Query::new(self.grammar_mut().ts_language, source)?;
|
||||
|
||||
let mut values = HashMap::default();
|
||||
for (ix, name) in query.capture_names().iter().enumerate() {
|
||||
if let Some(override_name) = name.strip_prefix("override.") {
|
||||
let value = self
|
||||
.config
|
||||
.overrides
|
||||
.remove(override_name)
|
||||
.ok_or_else(|| anyhow!("no such override {override_name}"))?;
|
||||
values.insert(ix as u32, value);
|
||||
}
|
||||
}
|
||||
|
||||
self.grammar_mut().override_config = Some(OverrideConfig { query, values });
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn grammar_mut(&mut self) -> &mut Grammar {
|
||||
Arc::get_mut(self.grammar.as_mut().unwrap()).unwrap()
|
||||
}
|
||||
|
@ -800,17 +869,6 @@ impl Language {
|
|||
self.config.name.clone()
|
||||
}
|
||||
|
||||
pub fn line_comment_prefix(&self) -> Option<&Arc<str>> {
|
||||
self.config.line_comment.as_ref()
|
||||
}
|
||||
|
||||
pub fn block_comment_delimiters(&self) -> Option<(&Arc<str>, &Arc<str>)> {
|
||||
self.config
|
||||
.block_comment
|
||||
.as_ref()
|
||||
.map(|(start, end)| (start, end))
|
||||
}
|
||||
|
||||
pub async fn disk_based_diagnostic_sources(&self) -> &[String] {
|
||||
match self.adapter.as_ref() {
|
||||
Some(adapter) => &adapter.disk_based_diagnostic_sources,
|
||||
|
@ -886,10 +944,6 @@ impl Language {
|
|||
result
|
||||
}
|
||||
|
||||
pub fn brackets(&self) -> &[BracketPair] {
|
||||
&self.config.brackets
|
||||
}
|
||||
|
||||
pub fn path_suffixes(&self) -> &[String] {
|
||||
&self.config.path_suffixes
|
||||
}
|
||||
|
@ -912,6 +966,43 @@ impl Language {
|
|||
}
|
||||
}
|
||||
|
||||
impl LanguageConfigYeet {
|
||||
pub fn line_comment_prefix(&self) -> Option<&Arc<str>> {
|
||||
Override::as_option(
|
||||
self.over_ride().map(|o| &o.line_comment),
|
||||
&self.language.config.line_comment,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn block_comment_delimiters(&self) -> Option<(&Arc<str>, &Arc<str>)> {
|
||||
Override::as_option(
|
||||
self.over_ride().map(|o| &o.block_comment),
|
||||
&self.language.config.block_comment,
|
||||
)
|
||||
.map(|e| (&e.0, &e.1))
|
||||
}
|
||||
|
||||
pub fn brackets(&self) -> &[BracketPair] {
|
||||
&self.language.config.brackets
|
||||
}
|
||||
|
||||
pub fn should_autoclose_before(&self, c: char) -> bool {
|
||||
c.is_whitespace() || self.language.config.autoclose_before.contains(c)
|
||||
}
|
||||
|
||||
fn over_ride(&self) -> Option<&LanguageConfigOverride> {
|
||||
self.override_id.and_then(|id| {
|
||||
self.language
|
||||
.grammar
|
||||
.as_ref()?
|
||||
.override_config
|
||||
.as_ref()?
|
||||
.values
|
||||
.get(&id)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Language {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.id().hash(state)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue