From 9ad40bc40b57f88d2c81a5dc55373bd6e31a6c21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Mon, 7 Sep 2020 18:10:08 +0900 Subject: [PATCH] Experiment with TUI so we can render selections. --- Cargo.lock | 20 +++++++++++++++ helix-term/Cargo.toml | 3 +-- helix-term/src/editor.rs | 54 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 70 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 244fedeb..da549c98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -212,6 +212,12 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" +[[package]] +name = "cassowary" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" + [[package]] name = "cc" version = "1.0.59" @@ -420,6 +426,7 @@ dependencies = [ "helix-core", "num_cpus", "smol", + "tui", ] [[package]] @@ -738,6 +745,19 @@ dependencies = [ "utf-8", ] +[[package]] +name = "tui" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a977b0bb2e2033a6fef950f218f13622c3c34e59754b704ce3492dedab1dfe95" +dependencies = [ + "bitflags", + "cassowary", + "crossterm", + "unicode-segmentation", + "unicode-width", +] + [[package]] name = "unicode-segmentation" version = "1.6.0" diff --git a/helix-term/Cargo.toml b/helix-term/Cargo.toml index 32e72825..b5f7484e 100644 --- a/helix-term/Cargo.toml +++ b/helix-term/Cargo.toml @@ -22,6 +22,5 @@ crossterm = { version = "0.17.7", features = ["event-stream"] } smol = "0.4" futures = { version = "0.3.5", default-features = false, features = ["std", "async-await"] } num_cpus = "1.13.0" +tui = { version = "0.10.0", default-features = false, features = ["crossterm"] } # futures-timer = "3.0.2" - -# tui = { version = "0.9.5", default-features = false } diff --git a/helix-term/src/editor.rs b/helix-term/src/editor.rs index 6c0d5b49..a6de3e0b 100644 --- a/helix-term/src/editor.rs +++ b/helix-term/src/editor.rs @@ -14,9 +14,17 @@ use std::io::{self, stdout, Write}; use std::path::PathBuf; use std::time::Duration; +use tui::backend::CrosstermBackend; +use tui::buffer::Buffer as Surface; +use tui::layout::Rect; +use tui::style::Style; + +type Terminal = tui::Terminal>; + static EX: smol::Executor = smol::Executor::new(); pub struct Editor { + terminal: Terminal, state: Option, first_line: u16, size: (u16, u16), @@ -24,7 +32,12 @@ pub struct Editor { impl Editor { pub fn new(mut args: Args) -> Result { + let backend = CrosstermBackend::new(stdout()); + + let mut terminal = Terminal::new(backend)?; + let mut editor = Editor { + terminal, state: None, first_line: 0, size: terminal::size().unwrap(), @@ -45,6 +58,9 @@ impl Editor { fn render(&mut self) { match &self.state { Some(state) => { + let area = Rect::new(0, 0, self.size.0, self.size.1); + let mut surface = Surface::empty(area); + let lines = state .doc .lines_at(self.first_line as usize) @@ -60,12 +76,33 @@ impl Editor { cursor::MoveTo(0, n as u16), Print((n + 1).to_string()) ); - execute!( - stdout, - SetForegroundColor(Color::Reset), - cursor::MoveTo(2, n as u16), - Print(line) + + surface.set_string(2, n as u16, line, Style::default()); + // execute!( + // stdout, + // SetForegroundColor(Color::Reset), + // cursor::MoveTo(2, n as u16), + // Print(line) + // ); + } + + // iterate over selections and render them + let select = Style::default().bg(tui::style::Color::LightBlue); + let text = state.doc.slice(..); + for range in state.selection.ranges() { + // get terminal coords for x,y for each range pos + // TODO: this won't work with multiline + let (y1, x1) = coords_at_pos(&text, range.from()); + let (y2, x2) = coords_at_pos(&text, range.to()); + let area = Rect::new( + (x1 + 2) as u16, + y1 as u16, + (x2 - x1 + 1) as u16, + (y2 - y1 + 1) as u16, ); + surface.set_style(area, select); + + // TODO: don't highlight next char in append mode } let mode = match state.mode { @@ -80,6 +117,13 @@ impl Editor { Print(mode) ); + use tui::backend::Backend; + // TODO: double buffer and diff here + let empty = Surface::empty(area); + self.terminal + .backend_mut() + .draw(empty.diff(&surface).into_iter()); + // set cursor shape match state.mode { Mode::Insert => write!(stdout, "\x1B[6 q"),