@@ -42,16 +42,15 @@ type Terminal = tui::Terminal<CrosstermBackend<std::io::Stdout>>;
42const BASE_WIDTH: u16 = 30;
42const BASE_WIDTH: u16 = 30;
44pub struct Application<'a> {
44pub struct Application<'a> {
45− prompt: Option<Prompt>,
47 compositor: Compositor,
45 compositor: Compositor,
48 renderer: Renderer,
47 renderer: Renderer,
50 executor: &'a smol::Executor<'a>,
49 executor: &'a smol::Executor<'a>,
51 language_server: helix_lsp::Client,
50 language_server: helix_lsp::Client,
54−pub(crate) struct Renderer {
53+pub struct Renderer {
55 size: (u16, u16),
54 size: (u16, u16),
56 terminal: Terminal,
55 terminal: Terminal,
57 surface: Surface,
56 surface: Surface,
@@ -263,6 +262,11 @@ impl Renderer {
263 self.surface
262 self.surface
264 .set_string(1, self.size.1 - 2, mode, self.text_color);
263 .set_string(1, self.size.1 - 2, mode, self.text_color);
265+ if let Some(path) = view.doc.path() {
267+ .set_string(6, self.size.1 - 2, path.to_string_lossy(), self.text_color);
266 self.surface.set_string(
270 self.surface.set_string(
267 self.size.0 - 10,
271 self.size.0 - 10,
268 self.size.1 - 2,
272 self.size.1 - 2,
@@ -271,7 +275,7 @@ impl Renderer {
274− pub fn render_prompt(&mut self, view: &View, prompt: &Prompt, theme: &Theme) {
278+ pub fn render_prompt(&mut self, prompt: &Prompt, theme: &Theme) {
275 // completion
279 // completion
276 if !prompt.completion.is_empty() {
280 if !prompt.completion.is_empty() {
277 // TODO: find out better way of clearing individual lines of the screen
281 // TODO: find out better way of clearing individual lines of the screen
@@ -343,15 +347,6 @@ impl Renderer {
343 let pos = if let Some(prompt) = prompt {
347 let pos = if let Some(prompt) = prompt {
344 Position::new(self.size.0 as usize, 2 + prompt.cursor)
348 Position::new(self.size.0 as usize, 2 + prompt.cursor)
346− if let Some(path) = view.doc.path() {
347− self.surface.set_string(
350− path.to_string_lossy(),
355 let cursor = view.doc.state.selection().cursor();
350 let cursor = view.doc.state.selection().cursor();
357 let mut pos = view
352 let mut pos = view
@@ -367,146 +362,77 @@ impl Renderer {
369struct EditorView {
364struct EditorView {
371− prompt: Option<Prompt>, // TODO: this is None for now, make a layer
372 keymap: Keymaps,
365 keymap: Keymaps,
375impl EditorView {
368impl EditorView {
376− fn new(editor: Editor) -> Self {
369+ fn new() -> Self {
380 keymap: keymap::default(),
371 keymap: keymap::default(),
376+use crate::compositor::Context;
385impl Component for EditorView {
378impl Component for EditorView {
386− fn handle_event(&mut self, event: Event, executor: &smol::Executor) -> EventResult {
379+ fn handle_event(&mut self, event: Event, cx: &mut Context) -> EventResult {
387 match event {
380 match event {
388 Event::Resize(width, height) => {
381 Event::Resize(width, height) => {
389 // TODO: simplistic ensure cursor in view for now
382 // TODO: simplistic ensure cursor in view for now
390 // TODO: loop over views
383 // TODO: loop over views
391− if let Some(view) = self.editor.view_mut() {
384+ if let Some(view) = cx.editor.view_mut() {
392 view.size = (width, height);
385 view.size = (width, height);
393 view.ensure_cursor_in_view()
386 view.ensure_cursor_in_view()
395 EventResult::Consumed(None)
388 EventResult::Consumed(None)
397 Event::Key(event) => {
390 Event::Key(event) => {
398− if let Some(view) = self.editor.view_mut() {
391+ if let Some(view) = cx.editor.view_mut() {
399 let keys = vec![event];
392 let keys = vec![event];
400 // TODO: sequences (`gg`)
393 // TODO: sequences (`gg`)
394+ let mode = view.doc.mode();
401 // TODO: handle count other than 1
395 // TODO: handle count other than 1
396+ let mut cx = commands::Context {
398+ executor: cx.executor,
402− match view.doc.mode() {
403+ match mode {
403 Mode::Insert => {
404 Mode::Insert => {
404 if let Some(command) = self.keymap[&Mode::Insert].get(&keys) {
405 if let Some(command) = self.keymap[&Mode::Insert].get(&keys) {
405− let mut cx = commands::Context {
411 command(&mut cx);
406 command(&mut cx);
412 } else if let KeyEvent {
407 } else if let KeyEvent {
413 code: KeyCode::Char(c),
408 code: KeyCode::Char(c),
415 } = event
410 } = event
417− let mut cx = commands::Context {
422 commands::insert::insert_char(&mut cx, c);
412 commands::insert::insert_char(&mut cx, c);
424− view.ensure_cursor_in_view();
426 Mode::Normal => {
415 Mode::Normal => {
428− code: KeyCode::Char(':'),
430− }] = keys.as_slice()
432− let prompt = Prompt::new(
435− // TODO: i need this duplicate list right now to avoid borrow checker issues
436− let command_list = vec![
438− String::from("aaa"),
439− String::from("bbb"),
440− String::from("ccc"),
441− String::from("ddd"),
442− String::from("eee"),
443− String::from("averylongcommandaverylongcommandaverylongcommandaverylongcommandaverylongcommand"),
445− String::from("aaa"),
446− String::from("bbb"),
447− String::from("ccc"),
448− String::from("ddd"),
449− String::from("eee"),
451− String::from("aaa"),
452− String::from("bbb"),
453− String::from("ccc"),
454− String::from("ddd"),
455− String::from("eee"),
457− String::from("aaa"),
458− String::from("bbb"),
459− String::from("ccc"),
460− String::from("ddd"),
461− String::from("eee"),
463− String::from("aaa"),
464− String::from("bbb"),
465− String::from("ccc"),
466− String::from("ddd"),
467− String::from("eee"),
471− .filter(|command| command.contains(_input))
474− |editor: &mut Editor, input: &str| match input {
475− "q" => editor.should_close = true,
480− self.prompt = Some(prompt);
482− // HAXX: special casing for command mode
483− } else if let Some(command) = self.keymap[&Mode::Normal].get(&keys) {
416+ if let Some(command) = self.keymap[&Mode::Normal].get(&keys) {
484− let mut cx = commands::Context {
489 command(&mut cx);
417 command(&mut cx);
491 // TODO: simplistic ensure cursor in view for now
419 // TODO: simplistic ensure cursor in view for now
492− view.ensure_cursor_in_view();
495 mode => {
422 mode => {
496 if let Some(command) = self.keymap[&mode].get(&keys) {
423 if let Some(command) = self.keymap[&mode].get(&keys) {
497− let mut cx = commands::Context {
502 command(&mut cx);
424 command(&mut cx);
504 // TODO: simplistic ensure cursor in view for now
426 // TODO: simplistic ensure cursor in view for now
505− view.ensure_cursor_in_view();
431+ let callback = cx.callback.take();
433+ view.ensure_cursor_in_view();
509− EventResult::Consumed(None)
435+ EventResult::Consumed(callback)
511 EventResult::Ignored
437 EventResult::Ignored
@@ -514,19 +440,19 @@ impl Component for EditorView {
514 Event::Mouse(_) => EventResult::Ignored,
440 Event::Mouse(_) => EventResult::Ignored,
517− fn render(&mut self, renderer: &mut Renderer) {
443+ fn render(&mut self, renderer: &mut Renderer, cx: &mut Context) {
518 const OFFSET: u16 = 7; // 1 diagnostic + 5 linenr + 1 gutter
444 const OFFSET: u16 = 7; // 1 diagnostic + 5 linenr + 1 gutter
519 let viewport = Rect::new(OFFSET, 0, renderer.size.0, renderer.size.1 - 2); // - 2 for statusline and prompt
445 let viewport = Rect::new(OFFSET, 0, renderer.size.0, renderer.size.1 - 2); // - 2 for statusline and prompt
521 // SAFETY: we cheat around the view_mut() borrow because it doesn't allow us to also borrow
447 // SAFETY: we cheat around the view_mut() borrow because it doesn't allow us to also borrow
522 // theme. Theme is immutable mutating view won't disrupt theme_ref.
448 // theme. Theme is immutable mutating view won't disrupt theme_ref.
523− let theme_ref = unsafe { &*(&self.editor.theme as *const Theme) };
449+ let theme_ref = unsafe { &*(&cx.editor.theme as *const Theme) };
524− if let Some(view) = self.editor.view_mut() {
450+ if let Some(view) = cx.editor.view_mut() {
525 renderer.render_view(view, viewport, theme_ref);
451 renderer.render_view(view, viewport, theme_ref);
528 // TODO: drop unwrap
454 // TODO: drop unwrap
529− renderer.render_cursor(self.editor.view().unwrap(), self.prompt.as_ref(), viewport);
455+ renderer.render_cursor(cx.editor.view().unwrap(), None, viewport);
@@ -540,11 +466,12 @@ impl<'a> Application<'a> {
542 let mut compositor = Compositor::new();
468 let mut compositor = Compositor::new();
543− compositor.push(Box::new(EditorView::new(editor)));
469+ compositor.push(Box::new(EditorView::new()));
545 let language_server = helix_lsp::Client::start(&executor, "rust-analyzer", &[]);
471 let language_server = helix_lsp::Client::start(&executor, "rust-analyzer", &[]);
547 let mut app = Self {
473 let mut app = Self {
548 renderer,
475 renderer,
549 // TODO; move to state
476 // TODO; move to state
550 compositor,
477 compositor,
@@ -558,7 +485,11 @@ impl<'a> Application<'a> {
559 fn render(&mut self) {
486 fn render(&mut self) {
560 self.renderer.surface.reset(); // reset is faster than allocating new empty surface
487 self.renderer.surface.reset(); // reset is faster than allocating new empty surface
488+ let mut cx = crate::compositor::Context {
489+ editor: &mut self.editor,
490+ executor: &self.executor,
561− self.compositor.render(&mut self.renderer); // viewport,
492+ self.compositor.render(&mut self.renderer, &mut cx); // viewport,
562 self.renderer.draw_and_swap();
493 self.renderer.draw_and_swap();
@@ -569,17 +500,16 @@ impl<'a> Application<'a> {
569 self.language_server.initialize().await.unwrap();
500 self.language_server.initialize().await.unwrap();
570 // TODO: temp
501 // TODO: temp
571 // self.language_server
502 // self.language_server
572− // .text_document_did_open(&self.editor.view().unwrap().doc)
503+ // .text_document_did_open(&cx.editor.view().unwrap().doc)
573 // .await
504 // .await
574 // .unwrap();
505 // .unwrap();
576 self.render();
507 self.render();
580− // if self.editor.should_close {
510+ if self.editor.should_close {
581− // break;
511+ break;
584 use futures_util::{select, FutureExt};
514 use futures_util::{select, FutureExt};
585 select! {
515 select! {
@@ -594,26 +524,26 @@ impl<'a> Application<'a> {
596 pub fn handle_terminal_events(&mut self, event: Option<Result<Event, crossterm::ErrorKind>>) {
526 pub fn handle_terminal_events(&mut self, event: Option<Result<Event, crossterm::ErrorKind>>) {
527+ let mut cx = crate::compositor::Context {
528+ editor: &mut self.editor,
529+ executor: &self.executor,
597 // Handle key events
531 // Handle key events
598− match event {
532+ let should_redraw = match event {
599 Some(Ok(Event::Resize(width, height))) => {
533 Some(Ok(Event::Resize(width, height))) => {
600 self.renderer.resize(width, height);
534 self.renderer.resize(width, height);
602− // TODO: use the response
603 self.compositor
536 self.compositor
604− .handle_event(Event::Resize(width, height), self.executor);
537+ .handle_event(Event::Resize(width, height), &mut cx)
608− Some(Ok(event)) => {
609− // TODO: use the response
610− self.compositor.handle_event(event, self.executor);
539+ Some(Ok(event)) => self.compositor.handle_event(event, &mut cx),
614 Some(Err(x)) => panic!(x),
540 Some(Err(x)) => panic!(x),
615 None => panic!(),
541 None => panic!(),
619 pub async fn handle_language_server_message(&mut self, call: Option<helix_lsp::Call>) {
549 pub async fn handle_language_server_message(&mut self, call: Option<helix_lsp::Call>) {