From ce97a2f05fcddf81d8210ec6b25411f8fd7d867a Mon Sep 17 00:00:00 2001 From: wojciechkepka Date: Sat, 19 Jun 2021 13:26:52 +0200 Subject: Add ability to change theme on editor --- helix-core/src/indent.rs | 37 ++++++++--------- helix-core/src/lib.rs | 2 +- helix-core/src/syntax.rs | 101 +++++++++++++++++++++++++++-------------------- 3 files changed, 77 insertions(+), 63 deletions(-) (limited to 'helix-core/src') diff --git a/helix-core/src/indent.rs b/helix-core/src/indent.rs index 58124ed2..8e0379e2 100644 --- a/helix-core/src/indent.rs +++ b/helix-core/src/indent.rs @@ -254,26 +254,23 @@ where Configuration, IndentationConfiguration, Lang, LanguageConfiguration, Loader, }; use once_cell::sync::OnceCell; - let loader = Loader::new( - Configuration { - language: vec![LanguageConfiguration { - scope: "source.rust".to_string(), - file_types: vec!["rs".to_string()], - language_id: Lang::Rust, - highlight_config: OnceCell::new(), - // - roots: vec![], - auto_format: false, - language_server: None, - indent: Some(IndentationConfiguration { - tab_width: 4, - unit: String::from(" "), - }), - indent_query: OnceCell::new(), - }], - }, - Vec::new(), - ); + let loader = Loader::new(Configuration { + language: vec![LanguageConfiguration { + scope: "source.rust".to_string(), + file_types: vec!["rs".to_string()], + language_id: Lang::Rust, + highlight_config: OnceCell::new(), + // + roots: vec![], + auto_format: false, + language_server: None, + indent: Some(IndentationConfiguration { + tab_width: 4, + unit: String::from(" "), + }), + indent_query: OnceCell::new(), + }], + }); // set runtime path so we can find the queries let mut runtime = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); diff --git a/helix-core/src/lib.rs b/helix-core/src/lib.rs index 03741719..d669fa49 100644 --- a/helix-core/src/lib.rs +++ b/helix-core/src/lib.rs @@ -50,7 +50,7 @@ pub fn find_root(root: Option<&str>) -> Option { } #[cfg(not(embed_runtime))] -fn runtime_dir() -> std::path::PathBuf { +pub fn runtime_dir() -> std::path::PathBuf { if let Ok(dir) = std::env::var("HELIX_RUNTIME") { return dir.into(); } diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs index ae058eb1..78623fd6 100644 --- a/helix-core/src/syntax.rs +++ b/helix-core/src/syntax.rs @@ -1,6 +1,8 @@ use crate::{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,35 +145,48 @@ fn read_query(language: &str, filename: &str) -> String { } impl LanguageConfiguration { - pub fn highlight_config(&self, scopes: &[String]) -> Option> { - self.highlight_config - .get_or_init(|| { - let language = get_language_name(self.language_id).to_ascii_lowercase(); + fn initialize_highlight(&self, scopes: &[String]) -> Option> { + 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)) - } - }) - .clone() + 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 highlight_config(&self, scopes: &[String]) -> Option> { + if let Some(config) = self.highlight_config.get() { + if let Some(config) = config { + config.configure(scopes); + } + config.clone() + } else { + 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> { @@ -190,22 +205,18 @@ impl LanguageConfiguration { } } -pub static LOADER: OnceCell = OnceCell::new(); - #[derive(Debug)] pub struct Loader { // highlight_names ? language_configs: Vec>, language_config_ids_by_file_type: HashMap, // Vec - scopes: Vec, } impl Loader { - pub fn new(config: Configuration, scopes: Vec) -> 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 +236,6 @@ impl Loader { loader } - pub fn scopes(&self) -> &[String] { - &self.scopes - } - pub fn language_config_for_file_name(&self, path: &Path) -> Option> { // Find all the language configurations that match this file name // or a suffix of the file name. @@ -253,6 +260,10 @@ impl Loader { .find(|config| config.scope == scope) .cloned() } + + pub fn language_configs_iter(&self) -> impl Iterator> { + self.language_configs.iter() + } } pub struct TsParser { @@ -771,7 +782,7 @@ pub struct HighlightConfiguration { combined_injections_query: Option, locals_pattern_index: usize, highlights_pattern_index: usize, - highlight_indices: Vec>, + highlight_indices: ArcSwap>>, non_local_variable_patterns: Vec, injection_content_capture_index: Option, injection_language_capture_index: Option, @@ -923,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, @@ -956,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('.') { @@ -982,7 +996,10 @@ impl HighlightConfiguration { } } best_index.map(Highlight) - })); + }) + .collect(); + + self.highlight_indices.store(Arc::new(indices)); } } @@ -1561,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. -- cgit v1.2.3-70-g09d2