@@ -14,44 +14,54 @@ use crate::{
14 view::{View, PADDING},
14 view::{View, PADDING},
17+pub struct Context<'a, 'b> {
19+ pub view: &'a mut View,
20+ pub executor: &'a smol::Executor<'b>,
17/// A command is a function that takes the current state and a count, and does a side-effect on the
23/// A command is a function that takes the current state and a count, and does a side-effect on the
18/// state (usually by creating and applying a transaction).
24/// state (usually by creating and applying a transaction).
19−pub type Command = fn(view: &mut View, count: usize);
25+pub type Command = fn(cx: &mut Context);
21−pub fn move_char_left(view: &mut View, count: usize) {
27+pub fn move_char_left(cx: &mut Context) {
22 let selection =
28 let selection =
25− .move_selection(Direction::Backward, Granularity::Character, count);
32+ .move_selection(Direction::Backward, Granularity::Character, cx.count);
26− view.doc.set_selection(selection);
33+ cx.view.doc.set_selection(selection);
29−pub fn move_char_right(view: &mut View, count: usize) {
36+pub fn move_char_right(cx: &mut Context) {
30 let selection =
37 let selection =
33− .move_selection(Direction::Forward, Granularity::Character, count);
41+ .move_selection(Direction::Forward, Granularity::Character, cx.count);
34− view.doc.set_selection(selection);
42+ cx.view.doc.set_selection(selection);
37−pub fn move_line_up(view: &mut View, count: usize) {
45+pub fn move_line_up(cx: &mut Context) {
38− let selection = view
46+ let selection =
41− .move_selection(Direction::Backward, Granularity::Line, count);
50+ .move_selection(Direction::Backward, Granularity::Line, cx.count);
42− view.doc.set_selection(selection);
51+ cx.view.doc.set_selection(selection);
45−pub fn move_line_down(view: &mut View, count: usize) {
54+pub fn move_line_down(cx: &mut Context) {
46− let selection = view
55+ let selection =
49− .move_selection(Direction::Forward, Granularity::Line, count);
59+ .move_selection(Direction::Forward, Granularity::Line, cx.count);
50− view.doc.set_selection(selection);
60+ cx.view.doc.set_selection(selection);
53−pub fn move_line_end(view: &mut View, _count: usize) {
63+pub fn move_line_end(cx: &mut Context) {
54− let lines = selection_lines(&view.doc.state);
64+ let lines = selection_lines(&cx.view.doc.state);
56 let positions = lines
66 let positions = lines
57 .into_iter()
67 .into_iter()
@@ -60,78 +70,78 @@ pub fn move_line_end(view: &mut View, _count: usize) {
61 // Line end is pos at the start of next line - 1
71 // Line end is pos at the start of next line - 1
62 // subtract another 1 because the line ends with \n
72 // subtract another 1 because the line ends with \n
63− view.doc.text().line_to_char(index + 1).saturating_sub(2)
73+ cx.view.doc.text().line_to_char(index + 1).saturating_sub(2)
65 .map(|pos| Range::new(pos, pos));
75 .map(|pos| Range::new(pos, pos));
67 let selection = Selection::new(positions.collect(), 0);
77 let selection = Selection::new(positions.collect(), 0);
69− view.doc.set_selection(selection);
79+ cx.view.doc.set_selection(selection);
72−pub fn move_line_start(view: &mut View, _count: usize) {
82+pub fn move_line_start(cx: &mut Context) {
73− let lines = selection_lines(&view.doc.state);
83+ let lines = selection_lines(&cx.view.doc.state);
75 let positions = lines
85 let positions = lines
76 .into_iter()
86 .into_iter()
77 .map(|index| {
87 .map(|index| {
78 // adjust all positions to the start of the line.
88 // adjust all positions to the start of the line.
79− view.doc.text().line_to_char(index)
89+ cx.view.doc.text().line_to_char(index)
81 .map(|pos| Range::new(pos, pos));
91 .map(|pos| Range::new(pos, pos));
83 let selection = Selection::new(positions.collect(), 0);
93 let selection = Selection::new(positions.collect(), 0);
85− view.doc.set_selection(selection);
95+ cx.view.doc.set_selection(selection);
88−pub fn move_next_word_start(view: &mut View, count: usize) {
98+pub fn move_next_word_start(cx: &mut Context) {
89− let pos = view.doc.state.move_pos(
99+ let pos = cx.view.doc.state.move_pos(
90− view.doc.selection().cursor(),
100+ cx.view.doc.selection().cursor(),
91 Direction::Forward,
101 Direction::Forward,
92 Granularity::Word,
102 Granularity::Word,
96− view.doc.set_selection(Selection::point(pos));
106+ cx.view.doc.set_selection(Selection::point(pos));
99−pub fn move_prev_word_start(view: &mut View, count: usize) {
109+pub fn move_prev_word_start(cx: &mut Context) {
100− let pos = view.doc.state.move_pos(
110+ let pos = cx.view.doc.state.move_pos(
101− view.doc.selection().cursor(),
111+ cx.view.doc.selection().cursor(),
102 Direction::Backward,
112 Direction::Backward,
103 Granularity::Word,
113 Granularity::Word,
104− count,
114+ cx.count,
107− view.doc.set_selection(Selection::point(pos));
117+ cx.view.doc.set_selection(Selection::point(pos));
110−pub fn move_next_word_end(view: &mut View, count: usize) {
120+pub fn move_next_word_end(cx: &mut Context) {
111 let pos = State::move_next_word_end(
121 let pos = State::move_next_word_end(
112− &view.doc.text().slice(..),
122+ &cx.view.doc.text().slice(..),
113− view.doc.selection().cursor(),
123+ cx.view.doc.selection().cursor(),
114− count,
124+ cx.count,
117− view.doc.set_selection(Selection::point(pos));
127+ cx.view.doc.set_selection(Selection::point(pos));
120−pub fn move_file_start(view: &mut View, _count: usize) {
130+pub fn move_file_start(cx: &mut Context) {
121− view.doc.set_selection(Selection::point(0));
131+ cx.view.doc.set_selection(Selection::point(0));
123− view.doc.mode = Mode::Normal;
133+ cx.view.doc.mode = Mode::Normal;
126−pub fn move_file_end(view: &mut View, _count: usize) {
136+pub fn move_file_end(cx: &mut Context) {
127− let text = &view.doc.text();
137+ let text = &cx.view.doc.text();
128 let last_line = text.line_to_char(text.len_lines().saturating_sub(2));
138 let last_line = text.line_to_char(text.len_lines().saturating_sub(2));
129− view.doc.set_selection(Selection::point(last_line));
139+ cx.view.doc.set_selection(Selection::point(last_line));
131− view.doc.mode = Mode::Normal;
141+ cx.view.doc.mode = Mode::Normal;
134−pub fn check_cursor_in_view(view: &mut View) -> bool {
144+pub fn check_cursor_in_view(view: &View) -> bool {
135 let cursor = view.doc.selection().cursor();
145 let cursor = view.doc.selection().cursor();
136 let line = view.doc.text().char_to_line(cursor);
146 let line = view.doc.text().char_to_line(cursor);
137 let document_end = view.first_line + view.size.1.saturating_sub(1) as usize;
147 let document_end = view.first_line + view.size.1.saturating_sub(1) as usize;
@@ -142,172 +152,182 @@ pub fn check_cursor_in_view(view: &mut View) -> bool {
145−pub fn page_up(view: &mut View, _count: usize) {
155+pub fn page_up(cx: &mut Context) {
146− if view.first_line < PADDING {
156+ if cx.view.first_line < PADDING {
150− view.first_line = view.first_line.saturating_sub(view.size.1 as usize);
160+ cx.view.first_line = cx.view.first_line.saturating_sub(cx.view.size.1 as usize);
152− if !check_cursor_in_view(view) {
162+ if !check_cursor_in_view(cx.view) {
153− let text = view.doc.text();
163+ let text = cx.view.doc.text();
154− let pos = text.line_to_char(view.last_line().saturating_sub(PADDING));
164+ let pos = text.line_to_char(cx.view.last_line().saturating_sub(PADDING));
155− view.doc.set_selection(Selection::point(pos));
165+ cx.view.doc.set_selection(Selection::point(pos));
159−pub fn page_down(view: &mut View, _count: usize) {
169+pub fn page_down(cx: &mut Context) {
160− view.first_line += view.size.1 as usize + PADDING;
170+ cx.view.first_line += cx.view.size.1 as usize + PADDING;
162− if view.first_line < view.doc.text().len_lines() {
172+ if cx.view.first_line < cx.view.doc.text().len_lines() {
163− let text = view.doc.text();
173+ let text = cx.view.doc.text();
164− let pos = text.line_to_char(view.first_line as usize);
174+ let pos = text.line_to_char(cx.view.first_line as usize);
165− view.doc.set_selection(Selection::point(pos));
175+ cx.view.doc.set_selection(Selection::point(pos));
169−pub fn half_page_up(view: &mut View, _count: usize) {
179+pub fn half_page_up(cx: &mut Context) {
170− if view.first_line < PADDING {
180+ if cx.view.first_line < PADDING {
184+ cx.view.first_line = cx
174− view.first_line = view.first_line.saturating_sub(view.size.1 as usize / 2);
187+ .saturating_sub(cx.view.size.1 as usize / 2);
176− if !check_cursor_in_view(view) {
189+ if !check_cursor_in_view(cx.view) {
177− let text = &view.doc.text();
190+ let text = &cx.view.doc.text();
178− let pos = text.line_to_char(view.last_line() - PADDING);
191+ let pos = text.line_to_char(cx.view.last_line() - PADDING);
179− view.doc.set_selection(Selection::point(pos));
192+ cx.view.doc.set_selection(Selection::point(pos));
183−pub fn half_page_down(view: &mut View, _count: usize) {
196+pub fn half_page_down(cx: &mut Context) {
184− let lines = view.doc.text().len_lines();
197+ let lines = cx.view.doc.text().len_lines();
185− if view.first_line < lines.saturating_sub(view.size.1 as usize) {
198+ if cx.view.first_line < lines.saturating_sub(cx.view.size.1 as usize) {
186− view.first_line += view.size.1 as usize / 2;
199+ cx.view.first_line += cx.view.size.1 as usize / 2;
188− if !check_cursor_in_view(view) {
201+ if !check_cursor_in_view(cx.view) {
189− let text = view.doc.text();
202+ let text = cx.view.doc.text();
190− let pos = text.line_to_char(view.first_line as usize);
203+ let pos = text.line_to_char(cx.view.first_line as usize);
191− view.doc.set_selection(Selection::point(pos));
204+ cx.view.doc.set_selection(Selection::point(pos));
194// avoid select by default by having a visual mode switch that makes movements into selects
207// avoid select by default by having a visual mode switch that makes movements into selects
196−pub fn extend_char_left(view: &mut View, count: usize) {
209+pub fn extend_char_left(cx: &mut Context) {
197 let selection =
210 let selection =
198− view.doc
211+ cx.view
200− .extend_selection(Direction::Backward, Granularity::Character, count);
214+ .extend_selection(Direction::Backward, Granularity::Character, cx.count);
201− view.doc.set_selection(selection);
215+ cx.view.doc.set_selection(selection);
204−pub fn extend_char_right(view: &mut View, count: usize) {
218+pub fn extend_char_right(cx: &mut Context) {
205 let selection =
219 let selection =
206− view.doc
220+ cx.view
208− .extend_selection(Direction::Forward, Granularity::Character, count);
223+ .extend_selection(Direction::Forward, Granularity::Character, cx.count);
209− view.doc.set_selection(selection);
224+ cx.view.doc.set_selection(selection);
212−pub fn extend_line_up(view: &mut View, count: usize) {
227+pub fn extend_line_up(cx: &mut Context) {
213− let selection = view
228+ let selection =
216− .extend_selection(Direction::Backward, Granularity::Line, count);
232+ .extend_selection(Direction::Backward, Granularity::Line, cx.count);
217− view.doc.set_selection(selection);
233+ cx.view.doc.set_selection(selection);
220−pub fn extend_line_down(view: &mut View, count: usize) {
236+pub fn extend_line_down(cx: &mut Context) {
221− let selection = view
237+ let selection =
224− .extend_selection(Direction::Forward, Granularity::Line, count);
241+ .extend_selection(Direction::Forward, Granularity::Line, cx.count);
225− view.doc.set_selection(selection);
242+ cx.view.doc.set_selection(selection);
228−pub fn split_selection_on_newline(view: &mut View, _count: usize) {
245+pub fn split_selection_on_newline(cx: &mut Context) {
229− let text = &view.doc.text().slice(..);
246+ let text = &cx.view.doc.text().slice(..);
230 // only compile the regex once
247 // only compile the regex once
231 #[allow(clippy::trivial_regex)]
248 #[allow(clippy::trivial_regex)]
232 static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\n").unwrap());
249 static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\n").unwrap());
233− let selection = selection::split_on_matches(text, view.doc.selection(), ®EX);
250+ let selection = selection::split_on_matches(text, cx.view.doc.selection(), ®EX);
234− view.doc.set_selection(selection);
251+ cx.view.doc.set_selection(selection);
237−pub fn select_line(view: &mut View, _count: usize) {
254+pub fn select_line(cx: &mut Context) {
238 // TODO: count
255 // TODO: count
239− let pos = view.doc.selection().primary();
256+ let pos = cx.view.doc.selection().primary();
240− let text = view.doc.text();
257+ let text = cx.view.doc.text();
241 let line = text.char_to_line(pos.head);
258 let line = text.char_to_line(pos.head);
242 let start = text.line_to_char(line);
259 let start = text.line_to_char(line);
243 let end = text.line_to_char(line + 1).saturating_sub(1);
260 let end = text.line_to_char(line + 1).saturating_sub(1);
245− view.doc.set_selection(Selection::single(start, end));
262+ cx.view.doc.set_selection(Selection::single(start, end));
248−pub fn delete_selection(view: &mut View, _count: usize) {
265+pub fn delete_selection(cx: &mut Context) {
249− let transaction = Transaction::change_by_selection(&view.doc.state, |range| {
266+ let transaction = Transaction::change_by_selection(&cx.view.doc.state, |range| {
250 (range.from(), range.to() + 1, None)
267 (range.from(), range.to() + 1, None)
252− view.doc.apply(&transaction);
269+ cx.view.doc.apply(&transaction);
254− append_changes_to_history(view);
271+ append_changes_to_history(cx);
257−pub fn change_selection(view: &mut View, count: usize) {
274+pub fn change_selection(cx: &mut Context) {
258− delete_selection(view, count);
275+ delete_selection(cx);
259− insert_mode(view, count);
276+ insert_mode(cx);
262−pub fn collapse_selection(view: &mut View, _count: usize) {
279+pub fn collapse_selection(cx: &mut Context) {
263− let selection = view
280+ let selection = cx
265 .selection()
283 .selection()
266 .transform(|range| Range::new(range.head, range.head));
284 .transform(|range| Range::new(range.head, range.head));
268− view.doc.set_selection(selection);
286+ cx.view.doc.set_selection(selection);
271−pub fn flip_selections(view: &mut View, _count: usize) {
289+pub fn flip_selections(cx: &mut Context) {
272− let selection = view
290+ let selection = cx
274 .selection()
293 .selection()
275 .transform(|range| Range::new(range.head, range.anchor));
294 .transform(|range| Range::new(range.head, range.anchor));
277− view.doc.set_selection(selection);
296+ cx.view.doc.set_selection(selection);
280−fn enter_insert_mode(view: &mut View) {
299+fn enter_insert_mode(cx: &mut Context) {
281− view.doc.mode = Mode::Insert;
300+ cx.view.doc.mode = Mode::Insert;
283− append_changes_to_history(view);
302+ append_changes_to_history(cx);
285// inserts at the start of each selection
304// inserts at the start of each selection
286−pub fn insert_mode(view: &mut View, _count: usize) {
305+pub fn insert_mode(cx: &mut Context) {
287− enter_insert_mode(view);
306+ enter_insert_mode(cx);
289− let selection = view
308+ let selection = cx
291 .selection()
311 .selection()
292 .transform(|range| Range::new(range.to(), range.from()));
312 .transform(|range| Range::new(range.to(), range.from()));
293− view.doc.set_selection(selection);
313+ cx.view.doc.set_selection(selection);
296// inserts at the end of each selection
316// inserts at the end of each selection
297−pub fn append_mode(view: &mut View, _count: usize) {
317+pub fn append_mode(cx: &mut Context) {
298− enter_insert_mode(view);
318+ enter_insert_mode(cx);
299− view.doc.restore_cursor = true;
319+ cx.view.doc.restore_cursor = true;
301 // TODO: as transaction
321 // TODO: as transaction
302− let text = &view.doc.text().slice(..);
322+ let text = &cx.view.doc.text().slice(..);
303− let selection = view.doc.selection().transform(|range| {
323+ let selection = cx.view.doc.selection().transform(|range| {
304 // TODO: to() + next char
324 // TODO: to() + next char
305 Range::new(
325 Range::new(
306 range.from(),
326 range.from(),
307 graphemes::next_grapheme_boundary(text, range.to()),
327 graphemes::next_grapheme_boundary(text, range.to()),
310− view.doc.set_selection(selection);
330+ cx.view.doc.set_selection(selection);
313// TODO: I, A, o and O can share a lot of the primitives.
333// TODO: I, A, o and O can share a lot of the primitives.
@@ -332,30 +352,30 @@ fn selection_lines(state: &State) -> Vec<usize> {
334// I inserts at the start of each line with a selection
354// I inserts at the start of each line with a selection
335−pub fn prepend_to_line(view: &mut View, count: usize) {
355+pub fn prepend_to_line(cx: &mut Context) {
336− enter_insert_mode(view);
356+ enter_insert_mode(cx);
338− move_line_start(view, count);
358+ move_line_start(cx);
341// A inserts at the end of each line with a selection
361// A inserts at the end of each line with a selection
342−pub fn append_to_line(view: &mut View, count: usize) {
362+pub fn append_to_line(cx: &mut Context) {
343− enter_insert_mode(view);
363+ enter_insert_mode(cx);
345− move_line_end(view, count);
365+ move_line_end(cx);
348// o inserts a new line after each line with a selection
368// o inserts a new line after each line with a selection
349−pub fn open_below(view: &mut View, _count: usize) {
369+pub fn open_below(cx: &mut Context) {
350− enter_insert_mode(view);
370+ enter_insert_mode(cx);
352− let lines = selection_lines(&view.doc.state);
372+ let lines = selection_lines(&cx.view.doc.state);
354 let positions: Vec<_> = lines
374 let positions: Vec<_> = lines
355 .into_iter()
375 .into_iter()
356 .map(|index| {
376 .map(|index| {
357 // adjust all positions to the end of the line/start of the next one.
377 // adjust all positions to the end of the line/start of the next one.
358− view.doc.text().line_to_char(index + 1)
378+ cx.view.doc.text().line_to_char(index + 1)
360 .collect();
380 .collect();
@@ -376,82 +396,85 @@ pub fn open_below(view: &mut View, _count: usize) {
379− let transaction = Transaction::change(&view.doc.state, changes).with_selection(selection);
399+ let transaction = Transaction::change(&cx.view.doc.state, changes).with_selection(selection);
381− view.doc.apply(&transaction);
401+ cx.view.doc.apply(&transaction);
384// O inserts a new line before each line with a selection
404// O inserts a new line before each line with a selection
386−fn append_changes_to_history(view: &mut View) {
406+fn append_changes_to_history(cx: &mut Context) {
387− if view.doc.changes.is_empty() {
407+ if cx.view.doc.changes.is_empty() {
391− let new_changeset = ChangeSet::new(view.doc.text());
411+ let new_changeset = ChangeSet::new(cx.view.doc.text());
392− let changes = std::mem::replace(&mut view.doc.changes, new_changeset);
412+ let changes = std::mem::replace(&mut cx.view.doc.changes, new_changeset);
393 // Instead of doing this messy merge we could always commit, and based on transaction
413 // Instead of doing this messy merge we could always commit, and based on transaction
394 // annotations either add a new layer or compose into the previous one.
414 // annotations either add a new layer or compose into the previous one.
395− let transaction = Transaction::from(changes).with_selection(view.doc.selection().clone());
415+ let transaction = Transaction::from(changes).with_selection(cx.view.doc.selection().clone());
397 // increment document version
417 // increment document version
398 // TODO: needs to happen on undo/redo too
418 // TODO: needs to happen on undo/redo too
399− view.doc.version += 1;
419+ cx.view.doc.version += 1;
401 // TODO: trigger lsp/documentDidChange with changes
421 // TODO: trigger lsp/documentDidChange with changes
403 // HAXX: we need to reconstruct the state as it was before the changes..
423 // HAXX: we need to reconstruct the state as it was before the changes..
404− let old_state = std::mem::replace(&mut view.doc.old_state, view.doc.state.clone());
424+ let old_state = std::mem::replace(&mut cx.view.doc.old_state, cx.view.doc.state.clone());
405 // TODO: take transaction by value?
425 // TODO: take transaction by value?
406− view.doc.history.commit_revision(&transaction, &old_state);
429+ .commit_revision(&transaction, &old_state);
408 // TODO: notify LSP of changes
431 // TODO: notify LSP of changes
411−pub fn normal_mode(view: &mut View, _count: usize) {
434+pub fn normal_mode(cx: &mut Context) {
412− view.doc.mode = Mode::Normal;
435+ cx.view.doc.mode = Mode::Normal;
414− append_changes_to_history(view);
437+ append_changes_to_history(cx);
416 // if leaving append mode, move cursor back by 1
439 // if leaving append mode, move cursor back by 1
417− if view.doc.restore_cursor {
440+ if cx.view.doc.restore_cursor {
418− let text = &view.doc.text().slice(..);
441+ let text = &cx.view.doc.text().slice(..);
419− let selection = view.doc.selection().transform(|range| {
442+ let selection = cx.view.doc.selection().transform(|range| {
420 Range::new(
443 Range::new(
421 range.from(),
444 range.from(),
422 graphemes::prev_grapheme_boundary(text, range.to()),
445 graphemes::prev_grapheme_boundary(text, range.to()),
425− view.doc.set_selection(selection);
448+ cx.view.doc.set_selection(selection);
427− view.doc.restore_cursor = false;
450+ cx.view.doc.restore_cursor = false;
431−pub fn goto_mode(view: &mut View, _count: usize) {
454+pub fn goto_mode(cx: &mut Context) {
432− view.doc.mode = Mode::Goto;
455+ cx.view.doc.mode = Mode::Goto;
435// NOTE: Transactions in this module get appended to history when we switch back to normal mode.
458// NOTE: Transactions in this module get appended to history when we switch back to normal mode.
436pub mod insert {
459pub mod insert {
437 use super::*;
460 use super::*;
438 // TODO: insert means add text just before cursor, on exit we should be on the last letter.
461 // TODO: insert means add text just before cursor, on exit we should be on the last letter.
439− pub fn insert_char(view: &mut View, c: char) {
462+ pub fn insert_char(cx: &mut Context, c: char) {
440 let c = Tendril::from_char(c);
463 let c = Tendril::from_char(c);
441− let transaction = Transaction::insert(&view.doc.state, c);
464+ let transaction = Transaction::insert(&cx.view.doc.state, c);
443− view.doc.apply(&transaction);
466+ cx.view.doc.apply(&transaction);
446− pub fn insert_tab(view: &mut View, _count: usize) {
469+ pub fn insert_tab(cx: &mut Context) {
447− insert_char(view, '\t');
470+ insert_char(cx, '\t');
450− pub fn insert_newline(view: &mut View, _count: usize) {
473+ pub fn insert_newline(cx: &mut Context) {
451− let transaction = Transaction::change_by_selection(&view.doc.state, |range| {
474+ let transaction = Transaction::change_by_selection(&cx.view.doc.state, |range| {
452 let indent_level = helix_core::indent::suggested_indent_for_pos(
475 let indent_level = helix_core::indent::suggested_indent_for_pos(
453− view.doc.syntax.as_ref(),
476+ cx.view.doc.syntax.as_ref(),
454− &view.doc.state,
477+ &cx.view.doc.state,
455 range.head,
478 range.head,
457 let indent = " ".repeat(TAB_WIDTH).repeat(indent_level);
480 let indent = " ".repeat(TAB_WIDTH).repeat(indent_level);
@@ -460,32 +483,32 @@ pub mod insert {
460 text.push_str(&indent);
483 text.push_str(&indent);
461 (range.head, range.head, Some(text.into()))
484 (range.head, range.head, Some(text.into()))
463− view.doc.apply(&transaction);
486+ cx.view.doc.apply(&transaction);
466 // TODO: handle indent-aware delete
489 // TODO: handle indent-aware delete
467− pub fn delete_char_backward(view: &mut View, count: usize) {
490+ pub fn delete_char_backward(cx: &mut Context) {
468− let text = &view.doc.text().slice(..);
491+ let text = &cx.view.doc.text().slice(..);
469− let transaction = Transaction::change_by_selection(&view.doc.state, |range| {
492+ let transaction = Transaction::change_by_selection(&cx.view.doc.state, |range| {
471− graphemes::nth_prev_grapheme_boundary(text, range.head, count),
494+ graphemes::nth_prev_grapheme_boundary(text, range.head, cx.count),
472 range.head,
495 range.head,
476− view.doc.apply(&transaction);
499+ cx.view.doc.apply(&transaction);
479− pub fn delete_char_forward(view: &mut View, count: usize) {
502+ pub fn delete_char_forward(cx: &mut Context) {
480− let text = &view.doc.text().slice(..);
503+ let text = &cx.view.doc.text().slice(..);
481− let transaction = Transaction::change_by_selection(&view.doc.state, |range| {
504+ let transaction = Transaction::change_by_selection(&cx.view.doc.state, |range| {
483 range.head,
506 range.head,
484− graphemes::nth_next_grapheme_boundary(text, range.head, count),
507+ graphemes::nth_next_grapheme_boundary(text, range.head, cx.count),
488− view.doc.apply(&transaction);
511+ cx.view.doc.apply(&transaction);
@@ -495,31 +518,32 @@ pub fn insert_char_prompt(prompt: &mut Prompt, c: char) {
496// Undo / Redo
519// Undo / Redo
498−pub fn undo(view: &mut View, _count: usize) {
521+pub fn undo(cx: &mut Context) {
499− if let Some(revert) = view.doc.history.undo() {
522+ if let Some(revert) = cx.view.doc.history.undo() {
500− view.doc.version += 1;
523+ cx.view.doc.version += 1;
501− view.doc.apply(&revert);
524+ cx.view.doc.apply(&revert);
504 // TODO: each command could simply return a Option<transaction>, then the higher level handles storing it?
527 // TODO: each command could simply return a Option<transaction>, then the higher level handles storing it?
507−pub fn redo(view: &mut View, _count: usize) {
530+pub fn redo(cx: &mut Context) {
508− if let Some(transaction) = view.doc.history.redo() {
531+ if let Some(transaction) = cx.view.doc.history.redo() {
509− view.doc.version += 1;
532+ cx.view.doc.version += 1;
510− view.doc.apply(&transaction);
533+ cx.view.doc.apply(&transaction);
514// Yank / Paste
537// Yank / Paste
516−pub fn yank(view: &mut View, _count: usize) {
539+pub fn yank(cx: &mut Context) {
517 // TODO: should selections be made end inclusive?
540 // TODO: should selections be made end inclusive?
518− let values = view
541+ let values = cx
521 .selection()
545 .selection()
522− .fragments(&view.doc.text().slice(..))
546+ .fragments(&cx.view.doc.text().slice(..))
523 .map(|cow| cow.into_owned())
547 .map(|cow| cow.into_owned())
524 .collect();
548 .collect();
@@ -528,7 +552,7 @@ pub fn yank(view: &mut View, _count: usize) {
528 register::set(reg, values);
552 register::set(reg, values);
531−pub fn paste(view: &mut View, _count: usize) {
555+pub fn paste(cx: &mut Context) {
532 // TODO: allow specifying reg
556 // TODO: allow specifying reg
533 let reg = '"';
557 let reg = '"';
534 if let Some(values) = register::get(reg) {
558 if let Some(values) = register::get(reg) {
@@ -560,19 +584,19 @@ pub fn paste(view: &mut View, _count: usize) {
560 let transaction = if linewise {
584 let transaction = if linewise {
561 // paste on the next line
585 // paste on the next line
562 // TODO: can simply take a range + modifier and compute the right pos without ifs
586 // TODO: can simply take a range + modifier and compute the right pos without ifs
563− let text = view.doc.text();
587+ let text = cx.view.doc.text();
564− Transaction::change_by_selection(&view.doc.state, |range| {
588+ Transaction::change_by_selection(&cx.view.doc.state, |range| {
565 let line_end = text.line_to_char(text.char_to_line(range.head) + 1);
589 let line_end = text.line_to_char(text.char_to_line(range.head) + 1);
566 (line_end, line_end, Some(values.next().unwrap()))
590 (line_end, line_end, Some(values.next().unwrap()))
569− Transaction::change_by_selection(&view.doc.state, |range| {
593+ Transaction::change_by_selection(&cx.view.doc.state, |range| {
570 (range.head + 1, range.head + 1, Some(values.next().unwrap()))
594 (range.head + 1, range.head + 1, Some(values.next().unwrap()))
574− view.doc.apply(&transaction);
598+ cx.view.doc.apply(&transaction);
575− append_changes_to_history(view);
599+ append_changes_to_history(cx);
@@ -593,29 +617,29 @@ fn get_lines(view: &View) -> Vec<usize> {
596−pub fn indent(view: &mut View, _count: usize) {
620+pub fn indent(cx: &mut Context) {
597− let lines = get_lines(view);
621+ let lines = get_lines(cx.view);
599 // Indent by one level
623 // Indent by one level
600 let indent = Tendril::from(" ".repeat(TAB_WIDTH));
624 let indent = Tendril::from(" ".repeat(TAB_WIDTH));
602 let transaction = Transaction::change(
626 let transaction = Transaction::change(
603− &view.doc.state,
627+ &cx.view.doc.state,
604 lines.into_iter().map(|line| {
628 lines.into_iter().map(|line| {
605− let pos = view.doc.text().line_to_char(line);
629+ let pos = cx.view.doc.text().line_to_char(line);
606 (pos, pos, Some(indent.clone()))
630 (pos, pos, Some(indent.clone()))
609− view.doc.apply(&transaction);
633+ cx.view.doc.apply(&transaction);
610− append_changes_to_history(view);
634+ append_changes_to_history(cx);
613−pub fn unindent(view: &mut View, _count: usize) {
637+pub fn unindent(cx: &mut Context) {
614− let lines = get_lines(view);
638+ let lines = get_lines(cx.view);
615 let mut changes = Vec::with_capacity(lines.len());
639 let mut changes = Vec::with_capacity(lines.len());
617 for line_idx in lines {
641 for line_idx in lines {
618− let line = view.doc.text().line(line_idx);
642+ let line = cx.view.doc.text().line(line_idx);
619 let mut width = 0;
643 let mut width = 0;
621 for ch in line.chars() {
645 for ch in line.chars() {
@@ -631,18 +655,18 @@ pub fn unindent(view: &mut View, _count: usize) {
633 if width > 0 {
657 if width > 0 {
634− let start = view.doc.text().line_to_char(line_idx);
658+ let start = cx.view.doc.text().line_to_char(line_idx);
635 changes.push((start, start + width, None))
659 changes.push((start, start + width, None))
639− let transaction = Transaction::change(&view.doc.state, changes.into_iter());
663+ let transaction = Transaction::change(&cx.view.doc.state, changes.into_iter());
641− view.doc.apply(&transaction);
665+ cx.view.doc.apply(&transaction);
642− append_changes_to_history(view);
666+ append_changes_to_history(cx);
645−pub fn indent_selection(_view: &mut View, _count: usize) {
669+pub fn indent_selection(_cx: &mut Context) {
646 // loop over each line and recompute proper indentation
670 // loop over each line and recompute proper indentation
647 unimplemented!()
671 unimplemented!()