@@ -9,36 +9,11 @@ use crossterm::{
99 terminal::{self, disable_raw_mode, enable_raw_mode},
1010};
1111use futures::{future::FutureExt, select, StreamExt};
12−use helix_core::{state::coords_at_pos, Buffer, State};
12+use helix_core::{state::coords_at_pos, state::Mode, Buffer, State};
1313use std::io::{self, stdout, Write};
1414use std::path::PathBuf;
1515use std::time::Duration;
1616
17−pub struct BufferComponent<'a> {
18− x: u16,
19− y: u16,
20− contents: Vec<&'a str>,
21−}
22−
23−impl BufferComponent<'_> {
24− pub fn render(&self) {
25− for (n, line) in self.contents.iter().enumerate() {
26− execute!(
27− stdout(),
28− SetForegroundColor(Color::DarkCyan),
29− cursor::MoveTo(self.x, self.y + n as u16),
30− Print((n + 1).to_string())
31− );
32− execute!(
33− stdout(),
34− SetForegroundColor(Color::Reset),
35− cursor::MoveTo(self.x + 2, self.y + n as u16),
36− Print(line)
37− );
38− }
39− }
40−}
41−
4217static EX: smol::Executor = smol::Executor::new();
4318
4419pub struct Editor {
@@ -70,21 +45,56 @@ impl Editor {
7045 }
7146
7247 fn render(&mut self) {
73− // TODO:
74−
7548 match &self.state {
76− Some(s) => {
77− let view = BufferComponent {
78− x: 0,
79− y: self.first_line,
80− contents: s
81− .file()
82− .lines_at(self.first_line as usize)
83− .take(self.size.1 as usize)
84− .map(|x| x.as_str().unwrap())
85− .collect::<Vec<&str>>(),
49+ Some(state) => {
50+ let lines = state
51+ .contents()
52+ .lines_at(self.first_line as usize)
53+ .take(self.size.1 as usize)
54+ .map(|x| x.as_str().unwrap());
55+
56+ let mut stdout = stdout();
57+
58+ for (n, line) in lines.enumerate() {
59+ execute!(
60+ stdout,
61+ SetForegroundColor(Color::DarkCyan),
62+ cursor::MoveTo(0, n as u16),
63+ Print((n + 1).to_string())
64+ );
65+ execute!(
66+ stdout,
67+ SetForegroundColor(Color::Reset),
68+ cursor::MoveTo(2, n as u16),
69+ Print(line)
70+ );
71+ }
72+
73+ let mode = match state.mode {
74+ Mode::Insert => "INS",
75+ Mode::Normal => "NOR",
76+ };
77+
78+ execute!(
79+ stdout,
80+ SetForegroundColor(Color::Reset),
81+ cursor::MoveTo(0, self.size.1),
82+ Print(mode)
83+ );
84+
85+ // set cursor shape
86+ match state.mode {
87+ Mode::Insert => write!(stdout, "\x1B[6 q"),
88+ Mode::Normal => write!(stdout, "\x1B[2 q"),
8689 };
87− view.render();
90+
91+ // render the cursor
92+ let pos = state.selection.primary().head;
93+ let coords = coords_at_pos(&state.doc.contents.slice(..), pos);
94+ execute!(
95+ stdout,
96+ cursor::MoveTo((coords.1 + 2) as u16, coords.0 as u16)
97+ );
8898 }
8999 None => (),
90100 }
@@ -108,22 +118,30 @@ impl Editor {
108118 break;
109119 }
110120 Some(Ok(Event::Key(event))) => {
111− // TODO: handle modes and sequences (`gg`)
112− if let Some(command) = keymap.get(&event) {
113− if let Some(state) = &mut self.state {
114− // TODO: handle count other than 1
115− command(state, 1);
116− self.render();
117− // render the cursor
118− let pos = self.state.as_ref().unwrap().selection.primary().head;
119− let coords = coords_at_pos(
120− &self.state.as_ref().unwrap().doc.contents.slice(..),
121− pos,
122− );
123− execute!(
124− stdout(),
125− cursor::MoveTo((coords.1 + 2) as u16, coords.0 as u16)
126− );
121+ if let Some(state) = &mut self.state {
122+ match state.mode {
123+ Mode::Insert => {
124+ match event {
125+ KeyEvent {
126+ code: KeyCode::Esc, ..
127+ } => helix_core::commands::normal_mode(state, 1),
128+ KeyEvent {
129+ code: KeyCode::Char(c),
130+ ..
131+ } => helix_core::commands::insert(state, c),
132+ _ => (), // skip
133+ }
134+ self.render();
135+ }
136+ Mode::Normal => {
137+ // TODO: handle modes and sequences (`gg`)
138+ if let Some(command) = keymap.get(&event) {
139+ // TODO: handle count other than 1
140+ command(state, 1);
141+
142+ self.render();
143+ }
144+ }
127145 }
128146 }
129147 }
@@ -145,6 +163,9 @@ impl Editor {
145163
146164 self.print_events().await;
147165
166+ // reset cursor shape
167+ write!(stdout, "\x1B[2 q");
168+
148169 execute!(stdout, terminal::LeaveAlternateScreen)?;
149170
150171 disable_raw_mode()?;