on master help sign in
Command needs access to view information for certain changes.
48330ddBlaž Hrastnik
helix-core/src/lib.rs+1−2
@@ -1,5 +1,4 @@
1#![allow(unused)]
1#![allow(unused)]
2−pub mod commands;
3pub mod graphemes;
2pub mod graphemes;
4mod position;
3mod position;
5mod selection;
4mod selection;
@@ -11,7 +10,7 @@ pub use ropey::{Rope, RopeSlice};
11pub use tendril::StrTendril as Tendril;
10pub use tendril::StrTendril as Tendril;
12
11
13pub use position::Position;
12pub use position::Position;
14−pub use selection::Range as SelectionRange;
13+pub use selection::Range;
15pub use selection::Selection;
14pub use selection::Selection;
16pub use syntax::Syntax;
15pub use syntax::Syntax;
17
16
helix-core/src/state.rs+8−7
@@ -1,5 +1,5 @@
1use crate::graphemes::{nth_next_grapheme_boundary, nth_prev_grapheme_boundary, RopeGraphemes};
1use crate::graphemes::{nth_next_grapheme_boundary, nth_prev_grapheme_boundary, RopeGraphemes};
2−use crate::{Position, Rope, RopeSlice, Selection, SelectionRange, Syntax};
2+use crate::{Position, Range, Rope, RopeSlice, Selection, Syntax};
3use anyhow::Error;
3use anyhow::Error;
4
4
5use std::path::PathBuf;
5use std::path::PathBuf;
@@ -12,11 +12,12 @@ pub enum Mode {
12
12
13/// A state represents the current editor state of a single buffer.
13/// A state represents the current editor state of a single buffer.
14pub struct State {
14pub struct State {
15+ // TODO: fields should be private but we need to refactor commands.rs first
15 /// Path to file on disk.
16 /// Path to file on disk.
16− pub(crate) path: Option<PathBuf>,
17+ pub path: Option<PathBuf>,
17− pub(crate) doc: Rope,
18+ pub doc: Rope,
18− pub(crate) selection: Selection,
19+ pub selection: Selection,
19− pub(crate) mode: Mode,
20+ pub mode: Mode,
20
21
21 //
22 //
22 pub syntax: Option<Syntax>,
23 pub syntax: Option<Syntax>,
@@ -189,7 +190,7 @@ impl State {
189 // } else {
190 // } else {
190 let pos = self.move_pos(range.head, dir, granularity, count);
191 let pos = self.move_pos(range.head, dir, granularity, count);
191 // };
192 // };
192− SelectionRange::new(pos, pos)
193+ Range::new(pos, pos)
193 })
194 })
194 }
195 }
195
196
@@ -201,7 +202,7 @@ impl State {
201 ) -> Selection {
202 ) -> Selection {
202 self.selection.transform(|range| {
203 self.selection.transform(|range| {
203 let pos = self.move_pos(range.head, dir, granularity, count);
204 let pos = self.move_pos(range.head, dir, granularity, count);
204− SelectionRange::new(range.anchor, pos)
205+ Range::new(range.anchor, pos)
205 })
206 })
206 }
207 }
207}
208}
helix-core/src/transaction.rs+2−2
@@ -1,4 +1,4 @@
1−use crate::{Rope, Selection, SelectionRange, State, Tendril};
1+use crate::{Range, Rope, Selection, State, Tendril};
2
2
3/// (from, to, replacement)
3/// (from, to, replacement)
4pub type Change = (usize, usize, Option<Tendril>);
4pub type Change = (usize, usize, Option<Tendril>);
@@ -387,7 +387,7 @@ impl Transaction {
387 /// Generate a transaction with a change per selection range.
387 /// Generate a transaction with a change per selection range.
388 pub fn change_by_selection<F>(state: &State, f: F) -> Self
388 pub fn change_by_selection<F>(state: &State, f: F) -> Self
389 where
389 where
390− F: Fn(&SelectionRange) -> Change,
390+ F: Fn(&Range) -> Change,
391 {
391 {
392 Self::change(state, state.selection.ranges().iter().map(f))
392 Self::change(state, state.selection.ranges().iter().map(f))
393 }
393 }
helix-core/src/commands.rs → helix-term/src/commands.rsrenamed+66−55
@@ -1,32 +1,42 @@
1+use helix_core::{
1−use crate::graphemes;
2+ graphemes,
2−use crate::selection::{Range, Selection};
3−use crate::state::{Direction, Granularity, Mode, State};
3+ state::{Direction, Granularity, Mode, State},
4−use crate::transaction::{ChangeSet, Transaction};
4+ ChangeSet, Range, Selection, Tendril, Transaction,
5+};
6+
5−use crate::Tendril;
7+use crate::editor::View;
6
8
7/// A command is a function that takes the current state and a count, and does a side-effect on the
9/// A command is a function that takes the current state and a count, and does a side-effect on the
8/// state (usually by creating and applying a transaction).
10/// state (usually by creating and applying a transaction).
9−pub type Command = fn(state: &mut State, count: usize);
11+pub type Command = fn(view: &mut View, count: usize);
10
12
11−pub fn move_char_left(state: &mut State, count: usize) {
13+pub fn move_char_left(view: &mut View, count: usize) {
12 // TODO: use a transaction
14 // TODO: use a transaction
15+ let selection = view
16+ .state
13− let selection = state.move_selection(Direction::Backward, Granularity::Character, count);
17+ .move_selection(Direction::Backward, Granularity::Character, count);
14− state.selection = selection;
18+ view.state.selection = selection;
15}
19}
16
20
17−pub fn move_char_right(state: &mut State, count: usize) {
21+pub fn move_char_right(view: &mut View, count: usize) {
18 // TODO: use a transaction
22 // TODO: use a transaction
23+ view.state.selection =
24+ view.state
19− state.selection = state.move_selection(Direction::Forward, Granularity::Character, count);
25+ .move_selection(Direction::Forward, Granularity::Character, count);
20}
26}
21
27
22−pub fn move_line_up(state: &mut State, count: usize) {
28+pub fn move_line_up(view: &mut View, count: usize) {
23 // TODO: use a transaction
29 // TODO: use a transaction
30+ view.state.selection = view
31+ .state
24− state.selection = state.move_selection(Direction::Backward, Granularity::Line, count);
32+ .move_selection(Direction::Backward, Granularity::Line, count);
25}
33}
26
34
27−pub fn move_line_down(state: &mut State, count: usize) {
35+pub fn move_line_down(view: &mut View, count: usize) {
28 // TODO: use a transaction
36 // TODO: use a transaction
37+ view.state.selection = view
38+ .state
29− state.selection = state.move_selection(Direction::Forward, Granularity::Line, count);
39+ .move_selection(Direction::Forward, Granularity::Line, count);
30}
40}
31
41
32// avoid select by default by having a visual mode switch that makes movements into selects
42// avoid select by default by having a visual mode switch that makes movements into selects
@@ -37,21 +47,22 @@ pub fn move_line_down(state: &mut State, count: usize) {
37// lastly, if it was append mode we shift cursor by 1?
47// lastly, if it was append mode we shift cursor by 1?
38
48
39// inserts at the start of each selection
49// inserts at the start of each selection
40−pub fn insert_mode(state: &mut State, _count: usize) {
50+pub fn insert_mode(view: &mut View, _count: usize) {
41− state.mode = Mode::Insert;
51+ view.state.mode = Mode::Insert;
42
52
43− state.selection = state
53+ view.state.selection = view
54+ .state
44 .selection
55 .selection
45 .transform(|range| Range::new(range.to(), range.from()))
56 .transform(|range| Range::new(range.to(), range.from()))
46}
57}
47
58
48// inserts at the end of each selection
59// inserts at the end of each selection
49−pub fn append_mode(state: &mut State, _count: usize) {
60+pub fn append_mode(view: &mut View, _count: usize) {
50− state.mode = Mode::Insert;
61+ view.state.mode = Mode::Insert;
51
62
52 // TODO: as transaction
63 // TODO: as transaction
53− let text = &state.doc.slice(..);
64+ let text = &view.state.doc.slice(..);
54− state.selection = state.selection.transform(|range| {
65+ view.state.selection = view.state.selection.transform(|range| {
55 // TODO: to() + next char
66 // TODO: to() + next char
56 Range::new(
67 Range::new(
57 range.from(),
68 range.from(),
@@ -78,63 +89,63 @@ fn selection_lines(state: &State) -> Vec<usize> {
78}
89}
79
90
80// I inserts at the start of each line with a selection
91// I inserts at the start of each line with a selection
81−pub fn prepend_to_line(state: &mut State, _count: usize) {
92+pub fn prepend_to_line(view: &mut View, _count: usize) {
82− state.mode = Mode::Insert;
93+ view.state.mode = Mode::Insert;
83
94
84− let lines = selection_lines(state);
95+ let lines = selection_lines(&view.state);
85
96
86 let positions = lines
97 let positions = lines
87 .into_iter()
98 .into_iter()
88 .map(|index| {
99 .map(|index| {
89 // adjust all positions to the start of the line.
100 // adjust all positions to the start of the line.
90− state.doc.line_to_char(index)
101+ view.state.doc.line_to_char(index)
91 })
102 })
92 .map(|pos| Range::new(pos, pos));
103 .map(|pos| Range::new(pos, pos));
93
104
94 let selection = Selection::new(positions.collect(), 0);
105 let selection = Selection::new(positions.collect(), 0);
95
106
96− let transaction = Transaction::new(state).with_selection(selection);
107+ let transaction = Transaction::new(&mut view.state).with_selection(selection);
97
108
98− transaction.apply(state);
109+ transaction.apply(&mut view.state);
99 // TODO: need to store into history if successful
110 // TODO: need to store into history if successful
100}
111}
101
112
102// A inserts at the end of each line with a selection
113// A inserts at the end of each line with a selection
103−pub fn append_to_line(state: &mut State, _count: usize) {
114+pub fn append_to_line(view: &mut View, _count: usize) {
104− state.mode = Mode::Insert;
115+ view.state.mode = Mode::Insert;
105
116
106− let lines = selection_lines(state);
117+ let lines = selection_lines(&view.state);
107
118
108 let positions = lines
119 let positions = lines
109 .into_iter()
120 .into_iter()
110 .map(|index| {
121 .map(|index| {
111 // adjust all positions to the end of the line.
122 // adjust all positions to the end of the line.
112− let line = state.doc.line(index);
123+ let line = view.state.doc.line(index);
113− let line_start = state.doc.line_to_char(index);
124+ let line_start = view.state.doc.line_to_char(index);
114 line_start + line.len_chars() - 1
125 line_start + line.len_chars() - 1
115 })
126 })
116 .map(|pos| Range::new(pos, pos));
127 .map(|pos| Range::new(pos, pos));
117
128
118 let selection = Selection::new(positions.collect(), 0);
129 let selection = Selection::new(positions.collect(), 0);
119
130
120− let transaction = Transaction::new(state).with_selection(selection);
131+ let transaction = Transaction::new(&mut view.state).with_selection(selection);
121
132
122− transaction.apply(state);
133+ transaction.apply(&mut view.state);
123 // TODO: need to store into history if successful
134 // TODO: need to store into history if successful
124}
135}
125
136
126// o inserts a new line after each line with a selection
137// o inserts a new line after each line with a selection
127−pub fn open_below(state: &mut State, _count: usize) {
138+pub fn open_below(view: &mut View, _count: usize) {
128− state.mode = Mode::Insert;
139+ view.state.mode = Mode::Insert;
129
140
130− let lines = selection_lines(state);
141+ let lines = selection_lines(&view.state);
131
142
132 let positions: Vec<_> = lines
143 let positions: Vec<_> = lines
133 .into_iter()
144 .into_iter()
134 .map(|index| {
145 .map(|index| {
135 // adjust all positions to the end of the line.
146 // adjust all positions to the end of the line.
136− let line = state.doc.line(index);
147+ let line = view.state.doc.line(index);
137− let line_start = state.doc.line_to_char(index);
148+ let line_start = view.state.doc.line_to_char(index);
138 line_start + line.len_chars()
149 line_start + line.len_chars()
139 })
150 })
140 .collect();
151 .collect();
@@ -155,51 +166,51 @@ pub fn open_below(state: &mut State, _count: usize) {
155 0,
166 0,
156 );
167 );
157
168
158− let transaction = Transaction::change(state, changes).with_selection(selection);
169+ let transaction = Transaction::change(&view.state, changes).with_selection(selection);
159
170
160− transaction.apply(state);
171+ transaction.apply(&mut view.state);
161 // TODO: need to store into history if successful
172 // TODO: need to store into history if successful
162}
173}
163
174
164// O inserts a new line before each line with a selection
175// O inserts a new line before each line with a selection
165
176
166−pub fn normal_mode(state: &mut State, _count: usize) {
177+pub fn normal_mode(view: &mut View, _count: usize) {
167 // TODO: if leaving append mode, move cursor back by 1
178 // TODO: if leaving append mode, move cursor back by 1
168− state.mode = Mode::Normal;
179+ view.state.mode = Mode::Normal;
169}
180}
170
181
171// TODO: insert means add text just before cursor, on exit we should be on the last letter.
182// TODO: insert means add text just before cursor, on exit we should be on the last letter.
172−pub fn insert_char(state: &mut State, c: char) {
183+pub fn insert_char(view: &mut View, c: char) {
173 let c = Tendril::from_char(c);
184 let c = Tendril::from_char(c);
174− let transaction = Transaction::insert(&state, c);
185+ let transaction = Transaction::insert(&view.state, c);
175
186
176− transaction.apply(state);
187+ transaction.apply(&mut view.state);
177 // TODO: need to store into history if successful
188 // TODO: need to store into history if successful
178}
189}
179
190
180// TODO: handle indent-aware delete
191// TODO: handle indent-aware delete
181−pub fn delete_char_backward(state: &mut State, count: usize) {
192+pub fn delete_char_backward(view: &mut View, count: usize) {
182− let text = &state.doc.slice(..);
193+ let text = &view.state.doc.slice(..);
183− let transaction = Transaction::change_by_selection(state, |range| {
194+ let transaction = Transaction::change_by_selection(&view.state, |range| {
184 (
195 (
185 graphemes::nth_prev_grapheme_boundary(text, range.head, count),
196 graphemes::nth_prev_grapheme_boundary(text, range.head, count),
186 range.head,
197 range.head,
187 None,
198 None,
188 )
199 )
189 });
200 });
190− transaction.apply(state);
201+ transaction.apply(&mut view.state);
191 // TODO: need to store into history if successful
202 // TODO: need to store into history if successful
192}
203}
193
204
194−pub fn delete_char_forward(state: &mut State, count: usize) {
205+pub fn delete_char_forward(view: &mut View, count: usize) {
195− let text = &state.doc.slice(..);
206+ let text = &view.state.doc.slice(..);
196− let transaction = Transaction::change_by_selection(state, |range| {
207+ let transaction = Transaction::change_by_selection(&view.state, |range| {
197 (
208 (
198 graphemes::nth_next_grapheme_boundary(text, range.head, count),
209 graphemes::nth_next_grapheme_boundary(text, range.head, count),
199 range.head,
210 range.head,
200 None,
211 None,
201 )
212 )
202 });
213 });
203− transaction.apply(state);
214+ transaction.apply(&mut view.state);
204 // TODO: need to store into history if successful
215 // TODO: need to store into history if successful
205}
216}
helix-term/src/editor.rs+52−40
@@ -1,4 +1,4 @@
1−use crate::{keymap, theme::Theme, Args};
1+use crate::{commands, keymap, theme::Theme, Args};
2use helix_core::{
2use helix_core::{
3 state::coords_at_pos,
3 state::coords_at_pos,
4 state::Mode,
4 state::Mode,
@@ -31,10 +31,15 @@ type Terminal = tui::Terminal<CrosstermBackend<std::io::Stdout>>;
31
31
32static EX: smol::Executor = smol::Executor::new();
32static EX: smol::Executor = smol::Executor::new();
33
33
34+pub struct View {
35+ pub state: State,
36+ pub first_line: u16,
37+ pub size: (u16, u16),
38+}
39+
34pub struct Editor {
40pub struct Editor {
35 terminal: Terminal,
41 terminal: Terminal,
36− state: Option<State>,
42+ view: Option<View>,
37− first_line: u16,
38 size: (u16, u16),
43 size: (u16, u16),
39 surface: Surface,
44 surface: Surface,
40 cache: Surface,
45 cache: Surface,
@@ -52,8 +57,7 @@ impl Editor {
52
57
53 let mut editor = Editor {
58 let mut editor = Editor {
54 terminal,
59 terminal,
55− state: None,
60+ view: None,
56− first_line: 0,
57 size,
61 size,
58 surface: Surface::empty(area),
62 surface: Surface::empty(area),
59 cache: Surface::empty(area),
63 cache: Surface::empty(area),
@@ -75,7 +79,14 @@ impl Editor {
75 .as_mut()
79 .as_mut()
76 .unwrap()
80 .unwrap()
77 .configure(self.theme.scopes());
81 .configure(self.theme.scopes());
78− self.state = Some(state);
82+
83+ let view = View {
84+ state,
85+ first_line: 0,
86+ size: self.size,
87+ };
88+
89+ self.view = Some(view);
79 Ok(())
90 Ok(())
80 }
91 }
81
92
@@ -83,8 +94,8 @@ impl Editor {
83 use tui::backend::Backend;
94 use tui::backend::Backend;
84 use tui::style::Color;
95 use tui::style::Color;
85 // TODO: ideally not mut but highlights require it because of cursor cache
96 // TODO: ideally not mut but highlights require it because of cursor cache
86− match &mut self.state {
97+ match &mut self.view {
87− Some(state) => {
98+ Some(view) => {
88 let area = Rect::new(0, 0, self.size.0, self.size.1);
99 let area = Rect::new(0, 0, self.size.0, self.size.1);
89 let mut stdout = stdout();
100 let mut stdout = stdout();
90 self.surface.reset(); // reset is faster than allocating new empty surface
101 self.surface.reset(); // reset is faster than allocating new empty surface
@@ -97,18 +108,18 @@ impl Editor {
97 let viewport = Rect::new(offset, 0, self.size.0, self.size.1 - 1); // - 1 for statusline
108 let viewport = Rect::new(offset, 0, self.size.0, self.size.1 - 1); // - 1 for statusline
98
109
99 // TODO: inefficient, should feed chunks.iter() to tree_sitter.parse_with(|offset, pos|)
110 // TODO: inefficient, should feed chunks.iter() to tree_sitter.parse_with(|offset, pos|)
100− let source_code = state.doc().to_string();
111+ let source_code = view.state.doc().to_string();
101
112
102 let last_line = std::cmp::min(
113 let last_line = std::cmp::min(
103− (self.first_line + viewport.height - 1) as usize,
114+ (view.first_line + viewport.height - 1) as usize,
104− state.doc().len_lines() - 1,
115+ view.state.doc().len_lines() - 1,
105 );
116 );
106
117
107 let range = {
118 let range = {
108 // calculate viewport byte ranges
119 // calculate viewport byte ranges
109− let start = state.doc().line_to_byte(self.first_line.into());
120+ let start = view.state.doc().line_to_byte(view.first_line.into());
110− let end = state.doc().line_to_byte(last_line)
121+ let end = view.state.doc().line_to_byte(last_line)
111− + state.doc().line(last_line).len_bytes();
122+ + view.state.doc().line(last_line).len_bytes();
112
123
113 start..end
124 start..end
114 };
125 };
@@ -117,7 +128,8 @@ impl Editor {
117
128
118 // TODO: cache highlight results
129 // TODO: cache highlight results
119 // TODO: only recalculate when state.doc is actually modified
130 // TODO: only recalculate when state.doc is actually modified
120− let highlights: Vec<_> = state
131+ let highlights: Vec<_> = view
132+ .state
121 .syntax
133 .syntax
122 .as_mut()
134 .as_mut()
123 .unwrap()
135 .unwrap()
@@ -141,10 +153,10 @@ impl Editor {
141 HighlightEvent::Source { start, end } => {
153 HighlightEvent::Source { start, end } => {
142 // TODO: filter out spans out of viewport for now..
154 // TODO: filter out spans out of viewport for now..
143
155
144− let start = state.doc().byte_to_char(start);
156+ let start = view.state.doc().byte_to_char(start);
145− let end = state.doc().byte_to_char(end);
157+ let end = view.state.doc().byte_to_char(end);
146
158
147− let text = state.doc().slice(start..end);
159+ let text = view.state.doc().slice(start..end);
148
160
149 use helix_core::graphemes::{grapheme_width, RopeGraphemes};
161 use helix_core::graphemes::{grapheme_width, RopeGraphemes};
150
162
@@ -191,7 +203,7 @@ impl Editor {
191
203
192 let mut line = 0;
204 let mut line = 0;
193 let style = self.theme.get("ui.linenr");
205 let style = self.theme.get("ui.linenr");
194− for i in self.first_line..(last_line as u16) {
206+ for i in view.first_line..(last_line as u16) {
195 self.surface
207 self.surface
196 .set_stringn(0, line, format!("{:>5}", i + 1), 5, style); // lavender
208 .set_stringn(0, line, format!("{:>5}", i + 1), 5, style); // lavender
197 line += 1;
209 line += 1;
@@ -223,7 +235,7 @@ impl Editor {
223 // }
235 // }
224
236
225 // statusline
237 // statusline
226− let mode = match state.mode() {
238+ let mode = match view.state.mode() {
227 Mode::Insert => "INS",
239 Mode::Insert => "INS",
228 Mode::Normal => "NOR",
240 Mode::Normal => "NOR",
229 };
241 };
@@ -235,7 +247,7 @@ impl Editor {
235 let text_color = Style::default().fg(Color::Rgb(219, 191, 239)); // lilac
247 let text_color = Style::default().fg(Color::Rgb(219, 191, 239)); // lilac
236 self.surface
248 self.surface
237 .set_string(1, self.size.1 - 1, mode, text_color);
249 .set_string(1, self.size.1 - 1, mode, text_color);
238− if let Some(path) = state.path() {
250+ if let Some(path) = view.state.path() {
239 self.surface
251 self.surface
240 .set_string(6, self.size.1 - 1, path.to_string_lossy(), text_color);
252 .set_string(6, self.size.1 - 1, path.to_string_lossy(), text_color);
241 }
253 }
@@ -247,19 +259,19 @@ impl Editor {
247 std::mem::swap(&mut self.surface, &mut self.cache);
259 std::mem::swap(&mut self.surface, &mut self.cache);
248
260
249 // set cursor shape
261 // set cursor shape
250− match state.mode() {
262+ match view.state.mode() {
251 Mode::Insert => write!(stdout, "\x1B[6 q"),
263 Mode::Insert => write!(stdout, "\x1B[6 q"),
252 Mode::Normal => write!(stdout, "\x1B[2 q"),
264 Mode::Normal => write!(stdout, "\x1B[2 q"),
253 };
265 };
254
266
255 // render the cursor
267 // render the cursor
256− let pos = state.selection().cursor();
268+ let pos = view.state.selection().cursor();
257− let coords = coords_at_pos(&state.doc().slice(..), pos);
269+ let coords = coords_at_pos(&view.state.doc().slice(..), pos);
258 execute!(
270 execute!(
259 stdout,
271 stdout,
260 cursor::MoveTo(
272 cursor::MoveTo(
261 coords.col as u16 + viewport.x,
273 coords.col as u16 + viewport.x,
262− coords.row as u16 - self.first_line + viewport.y,
274+ coords.row as u16 - view.first_line + viewport.y,
263 )
275 )
264 );
276 );
265 }
277 }
@@ -295,29 +307,29 @@ impl Editor {
295 break;
307 break;
296 }
308 }
297 Some(Ok(Event::Key(event))) => {
309 Some(Ok(Event::Key(event))) => {
298− if let Some(state) = &mut self.state {
310+ if let Some(view) = &mut self.view {
299− match state.mode() {
311+ match view.state.mode() {
300 Mode::Insert => {
312 Mode::Insert => {
301 match event {
313 match event {
302 KeyEvent {
314 KeyEvent {
303 code: KeyCode::Esc, ..
315 code: KeyCode::Esc, ..
304− } => helix_core::commands::normal_mode(state, 1),
316+ } => commands::normal_mode(view, 1),
305 KeyEvent {
317 KeyEvent {
306 code: KeyCode::Backspace,
318 code: KeyCode::Backspace,
307 ..
319 ..
308− } => helix_core::commands::delete_char_backward(state, 1),
320+ } => commands::delete_char_backward(view, 1),
309 KeyEvent {
321 KeyEvent {
310 code: KeyCode::Delete,
322 code: KeyCode::Delete,
311 ..
323 ..
312− } => helix_core::commands::delete_char_forward(state, 1),
324+ } => commands::delete_char_forward(view, 1),
313 KeyEvent {
325 KeyEvent {
314 code: KeyCode::Char(c),
326 code: KeyCode::Char(c),
315 ..
327 ..
316− } => helix_core::commands::insert_char(state, c),
328+ } => commands::insert_char(view, c),
317 KeyEvent {
329 KeyEvent {
318 code: KeyCode::Enter,
330 code: KeyCode::Enter,
319 ..
331 ..
320− } => helix_core::commands::insert_char(state, '\n'),
332+ } => commands::insert_char(view, '\n'),
321 _ => (), // skip
333 _ => (), // skip
322 }
334 }
323 // TODO: simplistic ensure cursor in view for now
335 // TODO: simplistic ensure cursor in view for now
@@ -329,7 +341,7 @@ impl Editor {
329 // TODO: handle modes and sequences (`gg`)
341 // TODO: handle modes and sequences (`gg`)
330 if let Some(command) = keymap.get(&event) {
342 if let Some(command) = keymap.get(&event) {
331 // TODO: handle count other than 1
343 // TODO: handle count other than 1
332− command(state, 1);
344+ command(view, 1);
333
345
334 // TODO: simplistic ensure cursor in view for now
346 // TODO: simplistic ensure cursor in view for now
335 self.ensure_cursor_in_view();
347 self.ensure_cursor_in_view();
@@ -350,10 +362,10 @@ impl Editor {
350 }
362 }
351
363
352 fn ensure_cursor_in_view(&mut self) {
364 fn ensure_cursor_in_view(&mut self) {
353− if let Some(state) = &mut self.state {
365+ if let Some(view) = &mut self.view {
354− let cursor = state.selection().cursor();
366+ let cursor = view.state.selection().cursor();
355− let line = state.doc().char_to_line(cursor) as u16;
367+ let line = view.state.doc().char_to_line(cursor) as u16;
356− let document_end = self.first_line + self.size.1.saturating_sub(1) - 1;
368+ let document_end = view.first_line + self.size.1.saturating_sub(1) - 1;
357
369
358 let padding = 5u16;
370 let padding = 5u16;
359
371
@@ -361,10 +373,10 @@ impl Editor {
361
373
362 if line > document_end.saturating_sub(padding) {
374 if line > document_end.saturating_sub(padding) {
363 // scroll down
375 // scroll down
364− self.first_line += line - (document_end.saturating_sub(padding));
376+ view.first_line += line - (document_end.saturating_sub(padding));
365− } else if line < self.first_line + padding {
377+ } else if line < view.first_line + padding {
366 // scroll up
378 // scroll up
367− self.first_line = line.saturating_sub(padding);
379+ view.first_line = line.saturating_sub(padding);
368 }
380 }
369 }
381 }
370 }
382 }
helix-term/src/keymap.rs+1−1
@@ -1,9 +1,9 @@
1+use crate::commands::{self, Command};
1use crossterm::{
2use crossterm::{
2 event::{KeyCode, KeyEvent as Key, KeyModifiers as Modifiers},
3 event::{KeyCode, KeyEvent as Key, KeyModifiers as Modifiers},
3 execute,
4 execute,
4 style::Print,
5 style::Print,
5};
6};
6−use helix_core::commands::{self, Command};
7use std::collections::HashMap;
7use std::collections::HashMap;
8
8
9// Kakoune-inspired:
9// Kakoune-inspired:
helix-term/src/main.rs+2
@@ -1,6 +1,8 @@
1#![allow(unused)]
1#![allow(unused)]
2#[macro_use]
2#[macro_use]
3mod macros;
3mod macros;
4+
5+mod commands;
4mod editor;
6mod editor;
5mod keymap;
7mod keymap;
6mod theme;
8mod theme;