Skip to content

Commit

Permalink
Add theme/syntax loaders to Application, remove static LOADER
Browse files Browse the repository at this point in the history
  • Loading branch information
vv9k committed Jun 17, 2021
1 parent a7b4d17 commit 08bfe54
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 71 deletions.
2 changes: 0 additions & 2 deletions helix-core/src/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,6 @@ impl LanguageConfiguration {
}
}

pub static LOADER: OnceCell<Loader> = OnceCell::new();

#[derive(Debug)]
pub struct Loader {
// highlight_names ?
Expand Down
42 changes: 39 additions & 3 deletions helix-term/src/application.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use helix_core::syntax;
use helix_lsp::lsp;
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};

Expand All @@ -13,7 +14,7 @@ use std::{
time::Duration,
};

use anyhow::Error;
use anyhow::{Context, Error};

use crossterm::{
event::{Event, EventStream},
Expand All @@ -36,6 +37,8 @@ pub struct Application {
compositor: Compositor,
editor: Editor,

theme_loader: Arc<theme::Loader>,
syn_loader: Arc<syntax::Loader>,
callbacks: LspCallbacks,
}

Expand All @@ -44,7 +47,36 @@ 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));

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

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);
Expand All @@ -69,10 +101,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(),
};

Expand Down
43 changes: 26 additions & 17 deletions helix-term/src/ui/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down
27 changes: 17 additions & 10 deletions helix-term/src/ui/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -196,7 +203,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 })
Expand All @@ -207,7 +214,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);
Expand Down
35 changes: 21 additions & 14 deletions helix-view/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ 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,
};

Expand Down Expand Up @@ -200,7 +200,7 @@ impl Document {
}

// TODO: async fn?
pub fn load(path: PathBuf) -> Result<Self, Error> {
pub fn load(path: PathBuf, config_loader: Option<&syntax::Loader>) -> Result<Self, Error> {
use std::{fs::File, io::BufReader};

let doc = if !path.exists() {
Expand All @@ -220,6 +220,10 @@ impl Document {
doc.set_path(&path)?;
doc.detect_indent_style();

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

Ok(doc)
}

Expand Down Expand Up @@ -293,11 +297,18 @@ 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();
pub fn detect_language(
&mut self,
theme: Option<&crate::Theme>,
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);
}
}
Expand Down Expand Up @@ -435,9 +446,6 @@ impl Document {
// and error out when document is saved
self.path = Some(path);

// try detecting the language based on filepath
self.detect_language();

Ok(())
}

Expand All @@ -460,10 +468,9 @@ 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, 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);
}
Expand Down
Loading

0 comments on commit 08bfe54

Please sign in to comment.