Skip to content

Commit

Permalink
Use same scopes on all themes
Browse files Browse the repository at this point in the history
As a consequence of this change, themes that do not have a scope defined will default
to the scope of the default theme.
  • Loading branch information
vv9k committed Jun 19, 2021
1 parent 0d23fa5 commit 136286a
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 53 deletions.
13 changes: 4 additions & 9 deletions helix-core/src/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ fn read_query(language: &str, filename: &str) -> String {
}

impl LanguageConfiguration {
pub fn highlight_config(&self, scopes: &[String]) -> Option<Arc<HighlightConfiguration>> {
pub fn highlight_config(&self, scopes: &[&str]) -> Option<Arc<HighlightConfiguration>> {
self.highlight_config
.get_or_init(|| {
let language = get_language_name(self.language_id).to_ascii_lowercase();
Expand Down Expand Up @@ -195,15 +195,13 @@ 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 {
Expand All @@ -223,10 +221,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.
Expand Down Expand Up @@ -954,7 +948,7 @@ 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<S: AsRef<str>>(&mut self, recognized_names: &[S]) {
let mut capture_parts = Vec::new();
self.highlight_indices.clear();
self.highlight_indices
Expand All @@ -965,6 +959,7 @@ impl HighlightConfiguration {
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.as_ref();
let mut len = 0;
let mut matches = true;
for part in recognized_name.split('.') {
Expand Down
5 changes: 1 addition & 4 deletions helix-term/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,7 @@ impl Application {
};

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,
theme.scopes().to_vec(),
));
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());

Expand Down
7 changes: 3 additions & 4 deletions helix-term/src/ui/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use helix_core::{
syntax::{self, HighlightEvent},
Position, Range,
};
use helix_view::{document::Mode, Document, Editor, Theme, View};
use helix_view::{document::Mode, theme, Document, Editor, Theme, View};
use std::borrow::Cow;

use crossterm::{
Expand Down Expand Up @@ -163,10 +163,9 @@ impl EditorView {
// .collect::<Vec<_>>()
// );
let style = match spans.first() {
Some(span) => theme
.scopes()
Some(span) => theme::DEFAULT_SCOPES
.get(span.0)
.map(|s| theme.get(s.as_str()))
.map(|s| theme.get(s))
.unwrap_or_else(|| theme.get("ui.text")),
None => theme.get("ui.text"),
};
Expand Down
8 changes: 3 additions & 5 deletions helix-term/src/ui/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use tui::{
use std::{borrow::Cow, sync::Arc};

use helix_core::{syntax, Position};
use helix_view::{Editor, Theme};
use helix_view::{theme, Editor, Theme};

pub struct Markdown {
contents: String,
Expand Down Expand Up @@ -90,7 +90,7 @@ fn parse<'a>(
let rope = Rope::from(text.as_ref());
let syntax = loader
.language_config_for_scope(&format!("source.{}", language))
.and_then(|config| config.highlight_config(theme.scopes()))
.and_then(|config| config.highlight_config(&theme::DEFAULT_SCOPES))
.map(|config| Syntax::new(&rope, config));

if let Some(mut syntax) = syntax {
Expand All @@ -108,9 +108,7 @@ fn parse<'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::DEFAULT_SCOPES[span.0]),
None => text_style,
};

Expand Down
24 changes: 7 additions & 17 deletions helix-view/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use helix_core::{
ChangeSet, Diagnostic, Rope, Selection, State, Syntax, Transaction,
};

use crate::{DocumentId, ViewId};
use crate::{theme, DocumentId, ViewId};

use std::collections::HashMap;

Expand Down Expand Up @@ -221,7 +221,7 @@ impl Document {
doc.detect_indent_style();

if let Some(loader) = config_loader {
doc.detect_language(None, loader);
doc.detect_language(loader);
}

Ok(doc)
Expand Down Expand Up @@ -297,19 +297,10 @@ impl Document {
}
}

pub fn detect_language(
&mut self,
theme: Option<&crate::Theme>,
config_loader: &syntax::Loader,
) {
pub fn detect_language(&mut self, config_loader: &syntax::Loader) {
if let Some(path) = &self.path {
let language_config = config_loader.language_config_for_file_name(path);
let scopes = if let Some(theme) = theme {
theme.scopes()
} else {
config_loader.scopes()
};
self.set_language(language_config, scopes);
self.set_language(language_config);
}
}

Expand Down Expand Up @@ -452,10 +443,10 @@ impl Document {
pub fn set_language(
&mut self,
language_config: Option<Arc<helix_core::syntax::LanguageConfiguration>>,
scopes: &[String],
) {
if let Some(language_config) = language_config {
if let Some(highlight_config) = language_config.highlight_config(scopes) {
if let Some(highlight_config) = language_config.highlight_config(&theme::DEFAULT_SCOPES)
{
let syntax = Syntax::new(&self.text, highlight_config);
self.syntax = Some(syntax);
// TODO: config.configure(scopes) is now delayed, is that ok?
Expand All @@ -470,9 +461,8 @@ impl Document {

pub fn set_language2(&mut self, scope: &str, config_loader: Arc<syntax::Loader>) {
let language_config = config_loader.language_config_for_scope(scope);
let scopes = config_loader.scopes();

self.set_language(language_config, scopes);
self.set_language(language_config);
}

pub fn set_language_server(&mut self, language_server: Option<Arc<helix_lsp::Client>>) {
Expand Down
6 changes: 1 addition & 5 deletions helix-view/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,8 @@ impl Editor {
}

pub fn set_theme(&mut self, theme: Theme) {
let config_loader = self.syn_loader.as_ref();
for (_, doc) in self.documents.iter_mut() {
doc.detect_language(Some(&theme), config_loader);
}
self._refresh();
self.theme = theme;
self._refresh();
}

pub fn set_theme_from_name(&mut self, theme: &str) {
Expand Down
72 changes: 63 additions & 9 deletions helix-view/src/theme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,60 @@ impl Loader {
}
}

/// A list of all theme scopes.
pub static DEFAULT_SCOPES: Lazy<Vec<&str>> = Lazy::new(|| {
let mut scopes = vec![
"attribute",
"comment",
"constant",
"constant.builtin",
"constructor",
"error",
"escape",
"function",
"function.builtin",
"function.macro",
"hint",
"info",
"keyword",
"keyword.directive",
"label",
"module",
"namespace",
"number",
"operator",
"property",
"punctuation",
"punctuation.delimiter",
"special",
"string",
"type",
"type.builtin",
"ui.background",
"ui.help",
"ui.linenr",
"ui.linenr.selected",
"ui.menu.selected",
"ui.popup",
"ui.selection",
"ui.statusline",
"ui.text",
"ui.text.focus",
"ui.window",
"variable",
"variable.builtin",
"variable.parameter",
"warning",
];

// this has to be in alphabetical order so in case of human error
// we sort it
scopes.sort();
scopes
});

#[derive(Clone, Debug)]
pub struct Theme {
scopes: Vec<String>,
styles: HashMap<String, Style>,
}

Expand All @@ -192,10 +243,18 @@ impl<'de> Deserialize<'de> for Theme {
}
}

let mut scopes: Vec<_> = styles.keys().map(ToString::to_string).collect();
scopes.sort();
// This is required so that all themes have the same scopes defined,
// otherwise changing the theme without upgrading `HighlighConfiguration`
// on `LanguageConfiguration` breaks the highlighting and there is no
// easy way to mutate the configuration.
let scopes: Vec<_> = styles.keys().map(ToString::to_string).collect();
DEFAULT_SCOPES.iter().for_each(|scope| {
if !scopes.iter().find(|s| s == scope).is_some() {
styles.insert(scope.to_string(), DEFAULT_THEME.get(scope));
}
});

Ok(Self { scopes, styles })
Ok(Self { styles })
}
}

Expand Down Expand Up @@ -291,11 +350,6 @@ impl Theme {
pub fn try_get(&self, scope: &str) -> Option<Style> {
self.styles.get(scope).copied()
}

#[inline]
pub fn scopes(&self) -> &[String] {
&self.scopes
}
}

#[test]
Expand Down

0 comments on commit 136286a

Please sign in to comment.