diff options
author | Nathan Vegdahl | 2021-06-20 23:09:14 +0000 |
---|---|---|
committer | Nathan Vegdahl | 2021-06-20 23:09:14 +0000 |
commit | e686c3e4626fdafbcc2dab9d381eba83a5f6f974 (patch) | |
tree | a598e3fedc1f2ae78ebc6f132c81b37cedf5415d /helix-core/src/syntax.rs | |
parent | 4efd6713c5b30b33c497a1f85b77a7b0a7fd17e0 (diff) | |
parent | 985625763addd839a101263ae90cfb2f205830fc (diff) |
Merge branch 'master' of github.com:helix-editor/helix into line_ending_detection
Rebasing was making me manually fix conflicts on every commit, so
merging instead.
Diffstat (limited to 'helix-core/src/syntax.rs')
-rw-r--r-- | helix-core/src/syntax.rs | 98 |
1 files changed, 57 insertions, 41 deletions
diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs index 92e52d73..63ca424e 100644 --- a/helix-core/src/syntax.rs +++ b/helix-core/src/syntax.rs @@ -1,6 +1,8 @@ use crate::{chars::char_is_line_ending, regex::Regex, Change, Rope, RopeSlice, Transaction}; pub use helix_syntax::{get_language, get_language_name, Lang}; +use arc_swap::ArcSwap; + use std::{ borrow::Cow, cell::RefCell, @@ -143,37 +145,49 @@ fn read_query(language: &str, filename: &str) -> String { } impl LanguageConfiguration { - pub fn highlight_config(&self, scopes: &[String]) -> Option<Arc<HighlightConfiguration>> { - self.highlight_config - .get_or_init(|| { - let language = get_language_name(self.language_id).to_ascii_lowercase(); + fn initialize_highlight(&self, scopes: &[String]) -> Option<Arc<HighlightConfiguration>> { + let language = get_language_name(self.language_id).to_ascii_lowercase(); - let highlights_query = read_query(&language, "highlights.scm"); - // always highlight syntax errors - // highlights_query += "\n(ERROR) @error"; + let highlights_query = read_query(&language, "highlights.scm"); + // always highlight syntax errors + // highlights_query += "\n(ERROR) @error"; - let injections_query = read_query(&language, "injections.scm"); + let injections_query = read_query(&language, "injections.scm"); - let locals_query = ""; + let locals_query = ""; - if highlights_query.is_empty() { - None - } else { - let language = get_language(self.language_id); - let mut config = HighlightConfiguration::new( - language, - &highlights_query, - &injections_query, - locals_query, - ) - .unwrap(); // TODO: no unwrap - config.configure(scopes); - Some(Arc::new(config)) - } - }) + if highlights_query.is_empty() { + None + } else { + let language = get_language(self.language_id); + let mut config = HighlightConfiguration::new( + language, + &highlights_query, + &injections_query, + locals_query, + ) + .unwrap(); // TODO: no unwrap + config.configure(scopes); + Some(Arc::new(config)) + } + } + + pub fn reconfigure(&self, scopes: &[String]) { + if let Some(Some(config)) = self.highlight_config.get() { + config.configure(scopes); + } + } + + pub fn highlight_config(&self, scopes: &[String]) -> Option<Arc<HighlightConfiguration>> { + self.highlight_config + .get_or_init(|| self.initialize_highlight(scopes)) .clone() } + pub fn is_highlight_initialized(&self) -> bool { + self.highlight_config.get().is_some() + } + pub fn indent_query(&self) -> Option<&IndentQuery> { self.indent_query .get_or_init(|| { @@ -190,22 +204,18 @@ impl LanguageConfiguration { } } -pub static LOADER: OnceCell<Loader> = OnceCell::new(); - #[derive(Debug)] pub struct Loader { // highlight_names ? language_configs: Vec<Arc<LanguageConfiguration>>, language_config_ids_by_file_type: HashMap<String, usize>, // Vec<usize> - scopes: Vec<String>, } impl Loader { - pub fn new(config: Configuration, scopes: Vec<String>) -> Self { + pub fn new(config: Configuration) -> Self { let mut loader = Self { language_configs: Vec::new(), language_config_ids_by_file_type: HashMap::new(), - scopes, }; for config in config.language { @@ -225,10 +235,6 @@ impl Loader { loader } - pub fn scopes(&self) -> &[String] { - &self.scopes - } - pub fn language_config_for_file_name(&self, path: &Path) -> Option<Arc<LanguageConfiguration>> { // Find all the language configurations that match this file name // or a suffix of the file name. @@ -253,6 +259,10 @@ impl Loader { .find(|config| config.scope == scope) .cloned() } + + pub fn language_configs_iter(&self) -> impl Iterator<Item = &Arc<LanguageConfiguration>> { + self.language_configs.iter() + } } pub struct TsParser { @@ -772,7 +782,7 @@ pub struct HighlightConfiguration { combined_injections_query: Option<Query>, locals_pattern_index: usize, highlights_pattern_index: usize, - highlight_indices: Vec<Option<Highlight>>, + highlight_indices: ArcSwap<Vec<Option<Highlight>>>, non_local_variable_patterns: Vec<bool>, injection_content_capture_index: Option<u32>, injection_language_capture_index: Option<u32>, @@ -924,7 +934,7 @@ impl HighlightConfiguration { } } - let highlight_indices = vec![None; query.capture_names().len()]; + let highlight_indices = ArcSwap::from_pointee(vec![None; query.capture_names().len()]); Ok(Self { language, query, @@ -957,17 +967,20 @@ impl HighlightConfiguration { /// /// When highlighting, results are returned as `Highlight` values, which contain the index /// of the matched highlight this list of highlight names. - pub fn configure(&mut self, recognized_names: &[String]) { + pub fn configure(&self, recognized_names: &[String]) { let mut capture_parts = Vec::new(); - self.highlight_indices.clear(); - self.highlight_indices - .extend(self.query.capture_names().iter().map(move |capture_name| { + let indices: Vec<_> = self + .query + .capture_names() + .iter() + .map(move |capture_name| { capture_parts.clear(); capture_parts.extend(capture_name.split('.')); let mut best_index = None; let mut best_match_len = 0; for (i, recognized_name) in recognized_names.iter().enumerate() { + let recognized_name = recognized_name; let mut len = 0; let mut matches = true; for part in recognized_name.split('.') { @@ -983,7 +996,10 @@ impl HighlightConfiguration { } } best_index.map(Highlight) - })); + }) + .collect(); + + self.highlight_indices.store(Arc::new(indices)); } } @@ -1562,7 +1578,7 @@ where } } - let current_highlight = layer.config.highlight_indices[capture.index as usize]; + let current_highlight = layer.config.highlight_indices.load()[capture.index as usize]; // If this node represents a local definition, then store the current // highlight value on the local scope entry representing this node. |