aboutsummaryrefslogtreecommitdiff
path: root/helix-core
diff options
context:
space:
mode:
authorNathan Vegdahl2021-06-20 23:09:14 +0000
committerNathan Vegdahl2021-06-20 23:09:14 +0000
commite686c3e4626fdafbcc2dab9d381eba83a5f6f974 (patch)
treea598e3fedc1f2ae78ebc6f132c81b37cedf5415d /helix-core
parent4efd6713c5b30b33c497a1f85b77a7b0a7fd17e0 (diff)
parent985625763addd839a101263ae90cfb2f205830fc (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')
-rw-r--r--helix-core/Cargo.toml5
-rw-r--r--helix-core/src/indent.rs37
-rw-r--r--helix-core/src/lib.rs10
-rw-r--r--helix-core/src/syntax.rs98
4 files changed, 84 insertions, 66 deletions
diff --git a/helix-core/Cargo.toml b/helix-core/Cargo.toml
index 13ac35fb..bab062e1 100644
--- a/helix-core/Cargo.toml
+++ b/helix-core/Cargo.toml
@@ -19,12 +19,13 @@ helix-syntax = { version = "0.2", path = "../helix-syntax" }
ropey = "1.3"
smallvec = "1.4"
tendril = "0.4.2"
-unicode-segmentation = "1.7.1"
+unicode-segmentation = "1.7"
unicode-width = "0.1"
-unicode-general-category = "0.4.0"
+unicode-general-category = "0.4"
# 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 183b9f0a..69294688 100644
--- a/helix-core/src/lib.rs
+++ b/helix-core/src/lib.rs
@@ -19,6 +19,12 @@ mod state;
pub mod syntax;
mod transaction;
+pub mod unicode {
+ pub use unicode_general_category as category;
+ pub use unicode_segmentation as segmentation;
+ pub use unicode_width as width;
+}
+
static RUNTIME_DIR: once_cell::sync::Lazy<std::path::PathBuf> =
once_cell::sync::Lazy::new(runtime_dir);
@@ -51,7 +57,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();
}
@@ -98,8 +104,6 @@ pub use ropey::{Rope, RopeSlice};
pub use tendril::StrTendril as Tendril;
-pub use unicode_general_category::get_general_category;
-
#[doc(inline)]
pub use {regex, tree_sitter};
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.