summaryrefslogtreecommitdiff
path: root/helix-core
diff options
context:
space:
mode:
authorwojciechkepka2021-06-19 11:26:52 +0000
committerBlaž Hrastnik2021-06-19 15:07:13 +0000
commitce97a2f05fcddf81d8210ec6b25411f8fd7d867a (patch)
tree577068168aa16545f85aac310c2a10ae2c078842 /helix-core
parentf424a61054a0495336862ff8d90627fb6f5ce572 (diff)
Add ability to change theme on editor
Diffstat (limited to 'helix-core')
-rw-r--r--helix-core/Cargo.toml1
-rw-r--r--helix-core/src/indent.rs37
-rw-r--r--helix-core/src/lib.rs2
-rw-r--r--helix-core/src/syntax.rs101
4 files changed, 78 insertions, 63 deletions
diff --git a/helix-core/Cargo.toml b/helix-core/Cargo.toml
index 13ac35fb..346dc050 100644
--- a/helix-core/Cargo.toml
+++ b/helix-core/Cargo.toml
@@ -25,6 +25,7 @@ unicode-general-category = "0.4.0"
# slab = "0.4.2"
tree-sitter = "0.19"
once_cell = "1.8"
+arc-swap = "1"
regex = "1"
serde = { version = "1.0", features = ["derive"] }
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<std::path::PathBuf> {
}
#[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<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))
- }
- })
- .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<Arc<HighlightConfiguration>> {
+ 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<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 +236,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 +260,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 {
@@ -771,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>,
@@ -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.