aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwojciechkepka2021-06-19 11:26:52 +0000
committerBlaž Hrastnik2021-06-19 15:07:13 +0000
commitce97a2f05fcddf81d8210ec6b25411f8fd7d867a (patch)
tree577068168aa16545f85aac310c2a10ae2c078842
parentf424a61054a0495336862ff8d90627fb6f5ce572 (diff)
Add ability to change theme on editor
-rw-r--r--Cargo.lock7
-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
-rw-r--r--helix-term/src/application.rs40
-rw-r--r--helix-term/src/ui/completion.rs43
-rw-r--r--helix-term/src/ui/markdown.rs31
-rw-r--r--helix-view/src/document.rs43
-rw-r--r--helix-view/src/editor.rs75
10 files changed, 240 insertions, 140 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 24c277e1..896f7bc1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -18,6 +18,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61"
[[package]]
+name = "arc-swap"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e906254e445520903e7fc9da4f709886c84ae4bc4ddaf0e093188d66df4dc820"
+
+[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -254,6 +260,7 @@ dependencies = [
name = "helix-core"
version = "0.2.0"
dependencies = [
+ "arc-swap",
"etcetera",
"helix-syntax",
"once_cell",
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.
diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index 2fae467f..08853ed0 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -1,5 +1,6 @@
+use helix_core::syntax;
use helix_lsp::{lsp, LspProgressMap};
-use helix_view::{document::Mode, Document, Editor, Theme, View};
+use helix_view::{document::Mode, theme, Document, Editor, Theme, View};
use crate::{args::Args, compositor::Compositor, config::Config, keymap::Keymaps, ui};
@@ -14,7 +15,7 @@ use std::{
time::Duration,
};
-use anyhow::Error;
+use anyhow::{Context, Error};
use crossterm::{
event::{Event, EventStream},
@@ -36,6 +37,8 @@ pub struct Application {
compositor: Compositor,
editor: Editor,
+ theme_loader: Arc<theme::Loader>,
+ syn_loader: Arc<syntax::Loader>,
callbacks: LspCallbacks,
lsp_progress: LspProgressMap,
@@ -47,7 +50,34 @@ impl Application {
use helix_view::editor::Action;
let mut compositor = Compositor::new()?;
let size = compositor.size();
- let mut editor = Editor::new(size);
+
+ let conf_dir = helix_core::config_dir();
+
+ let theme_loader =
+ std::sync::Arc::new(theme::Loader::new(&conf_dir, &helix_core::runtime_dir()));
+
+ // load $HOME/.config/helix/languages.toml, fallback to default config
+ let lang_conf = std::fs::read(conf_dir.join("languages.toml"));
+ let lang_conf = lang_conf
+ .as_deref()
+ .unwrap_or(include_bytes!("../../languages.toml"));
+
+ let theme = if let Some(theme) = &config.global.theme {
+ match theme_loader.load(theme) {
+ Ok(theme) => theme,
+ Err(e) => {
+ log::warn!("failed to load theme `{}` - {}", theme, e);
+ theme_loader.default()
+ }
+ }
+ } else {
+ theme_loader.default()
+ };
+
+ let syn_loader_conf = toml::from_slice(lang_conf).expect("Could not parse languages.toml");
+ let syn_loader = std::sync::Arc::new(syntax::Loader::new(syn_loader_conf));
+
+ let mut editor = Editor::new(size, theme_loader.clone(), syn_loader.clone());
let mut editor_view = Box::new(ui::EditorView::new(config.keymaps));
compositor.push(editor_view);
@@ -72,10 +102,14 @@ impl Application {
editor.new_file(Action::VerticalSplit);
}
+ editor.set_theme(theme);
+
let mut app = Self {
compositor,
editor,
+ theme_loader,
+ syn_loader,
callbacks: FuturesUnordered::new(),
lsp_progress: LspProgressMap::new(),
lsp_progress_enabled: config.global.lsp_progress,
diff --git a/helix-term/src/ui/completion.rs b/helix-term/src/ui/completion.rs
index 06ed966d..88a71534 100644
--- a/helix-term/src/ui/completion.rs
+++ b/helix-term/src/ui/completion.rs
@@ -246,34 +246,43 @@ impl Component for Completion {
value: contents,
})) => {
// TODO: convert to wrapped text
- Markdown::new(format!(
- "```{}\n{}\n```\n{}",
- language,
- option.detail.as_deref().unwrap_or_default(),
- contents.clone()
- ))
+ Markdown::new(
+ format!(
+ "```{}\n{}\n```\n{}",
+ language,
+ option.detail.as_deref().unwrap_or_default(),
+ contents.clone()
+ ),
+ cx.editor.syn_loader.clone(),
+ )
}
Some(lsp::Documentation::MarkupContent(lsp::MarkupContent {
kind: lsp::MarkupKind::Markdown,
value: contents,
})) => {
// TODO: set language based on doc scope
- Markdown::new(format!(
- "```{}\n{}\n```\n{}",
- language,
- option.detail.as_deref().unwrap_or_default(),
- contents.clone()
- ))
+ Markdown::new(
+ format!(
+ "```{}\n{}\n```\n{}",
+ language,
+ option.detail.as_deref().unwrap_or_default(),
+ contents.clone()
+ ),
+ cx.editor.syn_loader.clone(),
+ )
}
None if option.detail.is_some() => {
// TODO: copied from above
// TODO: set language based on doc scope
- Markdown::new(format!(
- "```{}\n{}\n```",
- language,
- option.detail.as_deref().unwrap_or_default(),
- ))
+ Markdown::new(
+ format!(
+ "```{}\n{}\n```",
+ language,
+ option.detail.as_deref().unwrap_or_default(),
+ ),
+ cx.editor.syn_loader.clone(),
+ )
}
None => return,
};
diff --git a/helix-term/src/ui/markdown.rs b/helix-term/src/ui/markdown.rs
index be113747..91086f7b 100644
--- a/helix-term/src/ui/markdown.rs
+++ b/helix-term/src/ui/markdown.rs
@@ -7,25 +7,34 @@ use tui::{
text::Text,
};
-use std::borrow::Cow;
+use std::{borrow::Cow, sync::Arc};
-use helix_core::Position;
+use helix_core::{syntax, Position};
use helix_view::{Editor, Theme};
pub struct Markdown {
contents: String,
+
+ config_loader: Arc<syntax::Loader>,
}
// TODO: pre-render and self reference via Pin
// better yet, just use Tendril + subtendril for references
impl Markdown {
- pub fn new(contents: String) -> Self {
- Self { contents }
+ pub fn new(contents: String, config_loader: Arc<syntax::Loader>) -> Self {
+ Self {
+ contents,
+ config_loader,
+ }
}
}
-fn parse<'a>(contents: &'a str, theme: Option<&Theme>) -> tui::text::Text<'a> {
+fn parse<'a>(
+ contents: &'a str,
+ theme: Option<&Theme>,
+ loader: &syntax::Loader,
+) -> tui::text::Text<'a> {
use pulldown_cmark::{CodeBlockKind, CowStr, Event, Options, Parser, Tag};
use tui::text::{Span, Spans, Text};
@@ -79,9 +88,7 @@ fn parse<'a>(contents: &'a str, theme: Option<&Theme>) -> tui::text::Text<'a> {
use helix_core::Rope;
let rope = Rope::from(text.as_ref());
- let syntax = syntax::LOADER
- .get()
- .unwrap()
+ let syntax = loader
.language_config_for_scope(&format!("source.{}", language))
.and_then(|config| config.highlight_config(theme.scopes()))
.map(|config| Syntax::new(&rope, config));
@@ -101,9 +108,7 @@ fn parse<'a>(contents: &'a str, theme: Option<&Theme>) -> tui::text::Text<'a> {
}
HighlightEvent::Source { start, end } => {
let style = match highlights.first() {
- Some(span) => {
- theme.get(theme.scopes()[span.0].as_str())
- }
+ Some(span) => theme.get(&theme.scopes()[span.0]),
None => text_style,
};
@@ -196,7 +201,7 @@ impl Component for Markdown {
fn render(&self, area: Rect, surface: &mut Surface, cx: &mut Context) {
use tui::widgets::{Paragraph, Widget, Wrap};
- let text = parse(&self.contents, Some(&cx.editor.theme));
+ let text = parse(&self.contents, Some(&cx.editor.theme), &self.config_loader);
let par = Paragraph::new(text)
.wrap(Wrap { trim: false })
@@ -207,7 +212,7 @@ impl Component for Markdown {
}
fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> {
- let contents = parse(&self.contents, None);
+ let contents = parse(&self.contents, None, &self.config_loader);
let padding = 2;
let width = std::cmp::min(contents.width() as u16 + padding, viewport.0);
let height = std::cmp::min(contents.height() as u16 + padding, viewport.1);
diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs
index e9a8097c..4d5a23b6 100644
--- a/helix-view/src/document.rs
+++ b/helix-view/src/document.rs
@@ -9,11 +9,11 @@ use std::sync::Arc;
use helix_core::{
chars::{char_is_linebreak, char_is_whitespace},
history::History,
- syntax::{LanguageConfiguration, LOADER},
+ syntax::{self, LanguageConfiguration},
ChangeSet, Diagnostic, Rope, Selection, State, Syntax, Transaction,
};
-use crate::{DocumentId, ViewId};
+use crate::{DocumentId, Theme, ViewId};
use std::collections::HashMap;
@@ -236,7 +236,11 @@ impl Document {
}
// TODO: async fn?
- pub fn load(path: PathBuf) -> Result<Self, Error> {
+ pub fn load(
+ path: PathBuf,
+ theme: Option<&Theme>,
+ config_loader: Option<&syntax::Loader>,
+ ) -> Result<Self, Error> {
use std::{fs::File, io::BufReader};
let doc = if !path.exists() {
@@ -256,6 +260,10 @@ impl Document {
doc.set_path(&path)?;
doc.detect_indent_style();
+ if let Some(loader) = config_loader {
+ doc.detect_language(theme, loader);
+ }
+
Ok(doc)
}
@@ -330,12 +338,10 @@ impl Document {
}
}
- fn detect_language(&mut self) {
- if let Some(path) = self.path() {
- let loader = LOADER.get().unwrap();
- let language_config = loader.language_config_for_file_name(path);
- let scopes = loader.scopes();
- self.set_language(language_config, scopes);
+ pub fn detect_language(&mut self, theme: Option<&Theme>, config_loader: &syntax::Loader) {
+ if let Some(path) = &self.path {
+ let language_config = config_loader.language_config_for_file_name(path);
+ self.set_language(theme, language_config);
}
}
@@ -472,18 +478,16 @@ impl Document {
// and error out when document is saved
self.path = Some(path);
- // try detecting the language based on filepath
- self.detect_language();
-
Ok(())
}
pub fn set_language(
&mut self,
+ theme: Option<&Theme>,
language_config: Option<Arc<helix_core::syntax::LanguageConfiguration>>,
- scopes: &[String],
) {
if let Some(language_config) = language_config {
+ let scopes = theme.map(|theme| theme.scopes()).unwrap_or(&[]);
if let Some(highlight_config) = language_config.highlight_config(scopes) {
let syntax = Syntax::new(&self.text, highlight_config);
self.syntax = Some(syntax);
@@ -497,12 +501,15 @@ impl Document {
};
}
- pub fn set_language2(&mut self, scope: &str) {
- let loader = LOADER.get().unwrap();
- let language_config = loader.language_config_for_scope(scope);
- let scopes = loader.scopes();
+ pub fn set_language2(
+ &mut self,
+ scope: &str,
+ theme: Option<&Theme>,
+ config_loader: Arc<syntax::Loader>,
+ ) {
+ let language_config = config_loader.language_config_for_scope(scope);
- self.set_language(language_config, scopes);
+ self.set_language(theme, language_config);
}
pub fn set_language_server(&mut self, language_server: Option<Arc<helix_lsp::Client>>) {
diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs
index db8ae87a..83d5cbf6 100644
--- a/helix-view/src/editor.rs
+++ b/helix-view/src/editor.rs
@@ -1,10 +1,14 @@
-use crate::{theme::Theme, tree::Tree, Document, DocumentId, RegisterSelection, View, ViewId};
+use crate::{
+ theme::{self, Theme},
+ tree::Tree,
+ Document, DocumentId, RegisterSelection, View, ViewId,
+};
+use helix_core::syntax;
use tui::layout::Rect;
use tui::terminal::CursorKind;
use futures_util::future;
-use std::path::PathBuf;
-use std::time::Duration;
+use std::{path::PathBuf, sync::Arc, time::Duration};
use slotmap::SlotMap;
@@ -24,6 +28,9 @@ pub struct Editor {
pub theme: Theme,
pub language_servers: helix_lsp::Registry,
+ pub syn_loader: Arc<syntax::Loader>,
+ pub theme_loader: Arc<theme::Loader>,
+
pub status_msg: Option<(String, Severity)>,
}
@@ -35,27 +42,11 @@ pub enum Action {
}
impl Editor {
- pub fn new(mut area: tui::layout::Rect) -> Self {
- use helix_core::config_dir;
- let config = std::fs::read(config_dir().join("theme.toml"));
- // load $HOME/.config/helix/theme.toml, fallback to default config
- let toml = config
- .as_deref()
- .unwrap_or(include_bytes!("../../theme.toml"));
- let theme: Theme = toml::from_slice(toml).expect("failed to parse theme.toml");
-
- // initialize language registry
- use helix_core::syntax::{Loader, LOADER};
-
- // load $HOME/.config/helix/languages.toml, fallback to default config
- let config = std::fs::read(helix_core::config_dir().join("languages.toml"));
- let toml = config
- .as_deref()
- .unwrap_or(include_bytes!("../../languages.toml"));
-
- let config = toml::from_slice(toml).expect("Could not parse languages.toml");
- LOADER.get_or_init(|| Loader::new(config, theme.scopes().to_vec()));
-
+ pub fn new(
+ mut area: tui::layout::Rect,
+ themes: Arc<theme::Loader>,
+ config_loader: Arc<syntax::Loader>,
+ ) -> Self {
let language_servers = helix_lsp::Registry::new();
// HAXX: offset the render area height by 1 to account for prompt/commandline
@@ -66,8 +57,10 @@ impl Editor {
documents: SlotMap::with_key(),
count: None,
selected_register: RegisterSelection::default(),
- theme,
+ theme: themes.default(),
language_servers,
+ syn_loader: config_loader,
+ theme_loader: themes,
registers: Registers::default(),
status_msg: None,
}
@@ -85,6 +78,32 @@ impl Editor {
self.status_msg = Some((error, Severity::Error));
}
+ pub fn set_theme(&mut self, theme: Theme) {
+ let scopes = theme.scopes();
+ for config in self
+ .syn_loader
+ .language_configs_iter()
+ .filter(|cfg| cfg.is_highlight_initialized())
+ {
+ config.highlight_config(scopes);
+ }
+
+ self.theme = theme;
+ self._refresh();
+ }
+
+ pub fn set_theme_from_name(&mut self, theme: &str) {
+ let theme = match self.theme_loader.load(theme.as_ref()) {
+ Ok(theme) => theme,
+ Err(e) => {
+ log::warn!("failed setting theme `{}` - {}", theme, e);
+ return;
+ }
+ };
+
+ self.set_theme(theme);
+ }
+
fn _refresh(&mut self) {
for (view, _) in self.tree.views_mut() {
let doc = &self.documents[view.doc];
@@ -168,7 +187,7 @@ impl Editor {
let id = if let Some(id) = id {
id
} else {
- let mut doc = Document::load(path)?;
+ let mut doc = Document::load(path, Some(&self.theme), Some(&self.syn_loader))?;
// try to find a language server based on the language name
let language_server = doc
@@ -254,6 +273,10 @@ impl Editor {
self.documents.iter().map(|(_id, doc)| doc)
}
+ pub fn documents_mut(&mut self) -> impl Iterator<Item = &mut Document> {
+ self.documents.iter_mut().map(|(_id, doc)| doc)
+ }
+
// pub fn current_document(&self) -> Document {
// let id = self.view().doc;
// let doc = &mut editor.documents[id];