@@ -14,9 +14,17 @@ use std::io::{self, stdout, Write};
14use std::path::PathBuf;
14use std::path::PathBuf;
15use std::time::Duration;
15use std::time::Duration;
17+use tui::backend::CrosstermBackend;
18+use tui::buffer::Buffer as Surface;
19+use tui::layout::Rect;
20+use tui::style::Style;
22+type Terminal = tui::Terminal<CrosstermBackend<std::io::Stdout>>;
17static EX: smol::Executor = smol::Executor::new();
24static EX: smol::Executor = smol::Executor::new();
19pub struct Editor {
26pub struct Editor {
20 state: Option<State>,
28 state: Option<State>,
21 first_line: u16,
29 first_line: u16,
22 size: (u16, u16),
30 size: (u16, u16),
@@ -24,7 +32,12 @@ pub struct Editor {
25impl Editor {
33impl Editor {
26 pub fn new(mut args: Args) -> Result<Self, Error> {
34 pub fn new(mut args: Args) -> Result<Self, Error> {
35+ let backend = CrosstermBackend::new(stdout());
37+ let mut terminal = Terminal::new(backend)?;
27 let mut editor = Editor {
39 let mut editor = Editor {
28 state: None,
41 state: None,
29 first_line: 0,
42 first_line: 0,
30 size: terminal::size().unwrap(),
43 size: terminal::size().unwrap(),
@@ -45,6 +58,9 @@ impl Editor {
45 fn render(&mut self) {
58 fn render(&mut self) {
46 match &self.state {
59 match &self.state {
47 Some(state) => {
60 Some(state) => {
61+ let area = Rect::new(0, 0, self.size.0, self.size.1);
62+ let mut surface = Surface::empty(area);
48 let lines = state
64 let lines = state
50 .lines_at(self.first_line as usize)
66 .lines_at(self.first_line as usize)
@@ -60,12 +76,33 @@ impl Editor {
60 cursor::MoveTo(0, n as u16),
76 cursor::MoveTo(0, n as u16),
61 Print((n + 1).to_string())
77 Print((n + 1).to_string())
80+ surface.set_string(2, n as u16, line, Style::default());
63− execute!(
81+ // execute!(
64− stdout,
82+ // stdout,
65− SetForegroundColor(Color::Reset),
83+ // SetForegroundColor(Color::Reset),
66− cursor::MoveTo(2, n as u16),
84+ // cursor::MoveTo(2, n as u16),
67− Print(line)
85+ // Print(line)
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(
100+ (x2 - x1 + 1) as u16,
101+ (y2 - y1 + 1) as u16,
103+ surface.set_style(area, select);
105+ // TODO: don't highlight next char in append mode
71 let mode = match state.mode {
108 let mode = match state.mode {
@@ -80,6 +117,13 @@ impl Editor {
80 Print(mode)
117 Print(mode)
120+ use tui::backend::Backend;
121+ // TODO: double buffer and diff here
122+ let empty = Surface::empty(area);
125+ .draw(empty.diff(&surface).into_iter());
83 // set cursor shape
127 // set cursor shape
84 match state.mode {
128 match state.mode {
85 Mode::Insert => write!(stdout, "\x1B[6 q"),
129 Mode::Insert => write!(stdout, "\x1B[6 q"),