@@ -1,6 +1,6 @@
11use clap::ArgMatches as Args;
22use helix_core::{indent::TAB_WIDTH, state::Mode, syntax::HighlightEvent, Position, Range, State};
3−use helix_view::{commands, keymap, prompt::Prompt, Editor, View};
3+use helix_view::{commands, keymap, prompt::Prompt, Editor, Theme, View};
44
55use std::{
66 borrow::Cow,
@@ -15,8 +15,7 @@ use anyhow::Error;
1515
1616use crossterm::{
1717 cursor,
18− cursor::position,
19− event::{self, read, Event, EventStream, KeyCode, KeyEvent},
18+ event::{read, Event, EventStream, KeyCode, KeyEvent},
2019 execute, queue,
2120 terminal::{self, disable_raw_mode, enable_raw_mode},
2221};
@@ -75,19 +74,18 @@ impl Renderer {
7574 self.cache = Surface::empty(area);
7675 }
7776
78− pub fn render_view(&mut self, view: &mut View, viewport: Rect) {
79− self.render_buffer(view, viewport);
80− self.render_statusline(view);
77+ pub fn render_view(&mut self, view: &mut View, viewport: Rect, theme: &Theme) {
78+ self.render_buffer(view, viewport, theme);
79+ self.render_statusline(view, theme);
8180 }
8281
8382 // TODO: ideally not &mut View but highlights require it because of cursor cache
84− pub fn render_buffer(&mut self, view: &mut View, viewport: Rect) {
83+ pub fn render_buffer(&mut self, view: &mut View, viewport: Rect, theme: &Theme) {
8584 let area = Rect::new(0, 0, self.size.0, self.size.1);
8685 self.surface.reset(); // reset is faster than allocating new empty surface
8786
8887 // clear with background color
89− self.surface
90− .set_style(area, view.theme.get("ui.background"));
88+ self.surface.set_style(area, theme.get("ui.background"));
9189
9290 // TODO: inefficient, should feed chunks.iter() to tree_sitter.parse_with(|offset, pos|)
9391 let source_code = view.state.doc().to_string();
@@ -150,7 +148,7 @@ impl Renderer {
150148 use helix_core::graphemes::{grapheme_width, RopeGraphemes};
151149
152150 let style = match spans.first() {
153− Some(span) => view.theme.get(view.theme.scopes()[span.0].as_str()),
151+ Some(span) => theme.get(theme.scopes()[span.0].as_str()),
154152 None => Style::default().fg(Color::Rgb(164, 160, 232)), // lavender
155153 };
156154
@@ -214,7 +212,7 @@ impl Renderer {
214212 }
215213 }
216214 }
217− let style: Style = view.theme.get("ui.linenr");
215+ let style: Style = theme.get("ui.linenr");
218216 let last_line = view.last_line();
219217 for (i, line) in (view.first_line..last_line).enumerate() {
220218 self.surface
@@ -222,7 +220,7 @@ impl Renderer {
222220 }
223221 }
224222
225− pub fn render_statusline(&mut self, view: &View) {
223+ pub fn render_statusline(&mut self, view: &View, theme: &Theme) {
226224 let mode = match view.state.mode() {
227225 Mode::Insert => "INS",
228226 Mode::Normal => "NOR",
@@ -231,7 +229,7 @@ impl Renderer {
231229 // statusline
232230 self.surface.set_style(
233231 Rect::new(0, self.size.1 - 2, self.size.0, 1),
234− view.theme.get("ui.statusline"),
232+ theme.get("ui.statusline"),
235233 );
236234 self.surface
237235 .set_string(1, self.size.1 - 2, mode, self.text_color);
@@ -354,8 +352,11 @@ impl Application {
354352 fn render(&mut self) {
355353 let viewport = Rect::new(OFFSET, 0, self.terminal.size.0, self.terminal.size.1 - 2); // - 2 for statusline and prompt
356354
355+ // SAFETY: we cheat around the view_mut() borrow because it doesn't allow us to also borrow
356+ // theme. Theme is immutable mutating view won't disrupt theme_ref.
357+ let theme_ref = unsafe { &*(&self.editor.theme as *const Theme) };
357358 if let Some(view) = self.editor.view_mut() {
358− self.terminal.render_view(view, viewport);
359+ self.terminal.render_view(view, viewport, theme_ref);
359360 if let Some(prompt) = &self.prompt {
360361 if prompt.should_close {
361362 self.prompt = None;
@@ -389,6 +390,7 @@ impl Application {
389390 self.terminal.resize(width, height);
390391
391392 // TODO: simplistic ensure cursor in view for now
393+ // TODO: loop over views
392394 if let Some(view) = self.editor.view_mut() {
393395 view.size = self.terminal.size;
394396 view.ensure_cursor_in_view()