@@ -14,9 +14,17 @@ use std::io::{self, stdout, Write};
1414use std::path::PathBuf;
1515use std::time::Duration;
1616
17+use tui::backend::CrosstermBackend;
18+use tui::buffer::Buffer as Surface;
19+use tui::layout::Rect;
20+use tui::style::Style;
21+
22+type Terminal = tui::Terminal<CrosstermBackend<std::io::Stdout>>;
23+
1724static EX: smol::Executor = smol::Executor::new();
1825
1926pub struct Editor {
27+ terminal: Terminal,
2028 state: Option<State>,
2129 first_line: u16,
2230 size: (u16, u16),
@@ -24,7 +32,12 @@ pub struct Editor {
2432
2533impl Editor {
2634 pub fn new(mut args: Args) -> Result<Self, Error> {
35+ let backend = CrosstermBackend::new(stdout());
36+
37+ let mut terminal = Terminal::new(backend)?;
38+
2739 let mut editor = Editor {
40+ terminal,
2841 state: None,
2942 first_line: 0,
3043 size: terminal::size().unwrap(),
@@ -45,6 +58,9 @@ impl Editor {
4558 fn render(&mut self) {
4659 match &self.state {
4760 Some(state) => {
61+ let area = Rect::new(0, 0, self.size.0, self.size.1);
62+ let mut surface = Surface::empty(area);
63+
4864 let lines = state
4965 .doc
5066 .lines_at(self.first_line as usize)
@@ -60,12 +76,33 @@ impl Editor {
6076 cursor::MoveTo(0, n as u16),
6177 Print((n + 1).to_string())
6278 );
63− execute!(
64− stdout,
65− SetForegroundColor(Color::Reset),
66− cursor::MoveTo(2, n as u16),
67− Print(line)
79+
80+ surface.set_string(2, n as u16, line, Style::default());
81+ // execute!(
82+ // stdout,
83+ // SetForegroundColor(Color::Reset),
84+ // cursor::MoveTo(2, n as u16),
85+ // Print(line)
86+ // );
87+ }
88+
89+ // iterate over selections and render them
90+ let select = Style::default().bg(tui::style::Color::LightBlue);
91+ let text = state.doc.slice(..);
92+ for range in state.selection.ranges() {
93+ // get terminal coords for x,y for each range pos
94+ // TODO: this won't work with multiline
95+ let (y1, x1) = coords_at_pos(&text, range.from());
96+ let (y2, x2) = coords_at_pos(&text, range.to());
97+ let area = Rect::new(
98+ (x1 + 2) as u16,
99+ y1 as u16,
100+ (x2 - x1 + 1) as u16,
101+ (y2 - y1 + 1) as u16,
68102 );
103+ surface.set_style(area, select);
104+
105+ // TODO: don't highlight next char in append mode
69106 }
70107
71108 let mode = match state.mode {
@@ -80,6 +117,13 @@ impl Editor {
80117 Print(mode)
81118 );
82119
120+ use tui::backend::Backend;
121+ // TODO: double buffer and diff here
122+ let empty = Surface::empty(area);
123+ self.terminal
124+ .backend_mut()
125+ .draw(empty.diff(&surface).into_iter());
126+
83127 // set cursor shape
84128 match state.mode {
85129 Mode::Insert => write!(stdout, "\x1B[6 q"),