diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 5ac83d7b7..8bde88a2e 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -325,140 +325,111 @@ impl PartialEq for Command { fn move_char_left(cx: &mut Context) { let count = cx.count(); let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id).clone().transform(|range| { - movement::move_horizontally( - doc.text().slice(..), - range, - Direction::Backward, - count, - Movement::Move, - ) - }), - ); + let text = doc.text().slice(..); + + let selection = doc.selection(view.id).clone().transform(|range| { + movement::move_horizontally(text, range, Direction::Backward, count, Movement::Move) + }); + doc.set_selection(view.id, selection); } fn move_char_right(cx: &mut Context) { let count = cx.count(); let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id).clone().transform(|range| { - movement::move_horizontally( - doc.text().slice(..), - range, - Direction::Forward, - count, - Movement::Move, - ) - }), - ); + let text = doc.text().slice(..); + + let selection = doc.selection(view.id).clone().transform(|range| { + movement::move_horizontally(text, range, Direction::Forward, count, Movement::Move) + }); + doc.set_selection(view.id, selection); } fn move_line_up(cx: &mut Context) { let count = cx.count(); let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id).clone().transform(|range| { - movement::move_vertically( - doc.text().slice(..), - range, - Direction::Backward, - count, - Movement::Move, - ) - }), - ); + let text = doc.text().slice(..); + + let selection = doc.selection(view.id).clone().transform(|range| { + movement::move_vertically(text, range, Direction::Backward, count, Movement::Move) + }); + doc.set_selection(view.id, selection); } fn move_line_down(cx: &mut Context) { let count = cx.count(); let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id).clone().transform(|range| { - movement::move_vertically( - doc.text().slice(..), - range, - Direction::Forward, - count, - Movement::Move, - ) - }), - ); + let text = doc.text().slice(..); + + let selection = doc.selection(view.id).clone().transform(|range| { + movement::move_vertically(text, range, Direction::Forward, count, Movement::Move) + }); + doc.set_selection(view.id, selection); } fn goto_line_end(cx: &mut Context) { let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id).clone().transform(|range| { - let text = doc.text().slice(..); - let line = range.head_line(text); + let text = doc.text().slice(..); - let mut pos = line_end_char_index(&text, line); - if doc.mode != Mode::Select { - pos = graphemes::prev_grapheme_boundary(text, pos); - } + let selection = doc.selection(view.id).clone().transform(|range| { + let line = range.head_line(text); - pos = range.head.max(pos).max(text.line_to_char(line)); + let mut pos = line_end_char_index(&text, line); + if doc.mode != Mode::Select { + pos = graphemes::prev_grapheme_boundary(text, pos); + } - range.put(text, pos, doc.mode == Mode::Select) - }), - ); + pos = range.head.max(pos).max(text.line_to_char(line)); + + range.put(text, pos, doc.mode == Mode::Select) + }); + doc.set_selection(view.id, selection); } fn goto_line_end_newline(cx: &mut Context) { let (view, doc) = current!(cx.editor); + let text = doc.text().slice(..); - doc.set_selection( - view.id, - doc.selection(view.id).clone().transform(|range| { - let text = doc.text().slice(..); - let line = range.head_line(text); + let selection = doc.selection(view.id).clone().transform(|range| { + let line = range.head_line(text); - let mut pos = text.line_to_char((line + 1).min(text.len_lines())); - if doc.mode != Mode::Select { - pos = graphemes::prev_grapheme_boundary(text, pos); - } - range.put(text, pos, doc.mode == Mode::Select) - }), - ); + let mut pos = text.line_to_char((line + 1).min(text.len_lines())); + if doc.mode != Mode::Select { + pos = graphemes::prev_grapheme_boundary(text, pos); + } + range.put(text, pos, doc.mode == Mode::Select) + }); + doc.set_selection(view.id, selection); } fn goto_line_start(cx: &mut Context) { let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id).clone().transform(|range| { - let text = doc.text().slice(..); - let line = range.head_line(text); + let text = doc.text().slice(..); - // adjust to start of the line - let pos = text.line_to_char(line); - range.put(text, pos, doc.mode == Mode::Select) - }), - ); + let selection = doc.selection(view.id).clone().transform(|range| { + let line = range.head_line(text); + + // adjust to start of the line + let pos = text.line_to_char(line); + range.put(text, pos, doc.mode == Mode::Select) + }); + doc.set_selection(view.id, selection); } fn goto_first_nonwhitespace(cx: &mut Context) { let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id).clone().transform(|range| { - let text = doc.text().slice(..); - let line = range.head_line(text); + let text = doc.text().slice(..); - if let Some(pos) = find_first_non_whitespace_char(text.line(line)) { - let pos = pos + text.line_to_char(line); - range.put(text, pos, doc.mode == Mode::Select) - } else { - range - } - }), - ); + let selection = doc.selection(view.id).clone().transform(|range| { + let line = range.head_line(text); + + if let Some(pos) = find_first_non_whitespace_char(text.line(line)) { + let pos = pos + text.line_to_char(line); + range.put(text, pos, doc.mode == Mode::Select) + } else { + range + } + }); + doc.set_selection(view.id, selection); } fn goto_window(cx: &mut Context, align: Align) { @@ -499,80 +470,79 @@ fn goto_window_bottom(cx: &mut Context) { fn move_next_word_start(cx: &mut Context) { let count = cx.count(); let (view, doc) = current!(cx.editor); + let text = doc.text().slice(..); - doc.set_selection( - view.id, - doc.selection(view.id) - .clone() - .min_width_1(doc.text().slice(..)) - .transform(|range| movement::move_next_word_start(doc.text().slice(..), range, count)), - ); + let selection = doc + .selection(view.id) + .clone() + .min_width_1(text) + .transform(|range| movement::move_next_word_start(text, range, count)); + doc.set_selection(view.id, selection); } fn move_prev_word_start(cx: &mut Context) { let count = cx.count(); let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id) - .clone() - .min_width_1(doc.text().slice(..)) - .transform(|range| movement::move_prev_word_start(doc.text().slice(..), range, count)), - ); + let text = doc.text().slice(..); + + let selection = doc + .selection(view.id) + .clone() + .min_width_1(text) + .transform(|range| movement::move_prev_word_start(text, range, count)); + doc.set_selection(view.id, selection); } fn move_next_word_end(cx: &mut Context) { let count = cx.count(); let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id) - .clone() - .min_width_1(doc.text().slice(..)) - .transform(|range| movement::move_next_word_end(doc.text().slice(..), range, count)), - ); + let text = doc.text().slice(..); + + let selection = doc + .selection(view.id) + .clone() + .min_width_1(text) + .transform(|range| movement::move_next_word_end(text, range, count)); + doc.set_selection(view.id, selection); } fn move_next_long_word_start(cx: &mut Context) { let count = cx.count(); let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id) - .clone() - .min_width_1(doc.text().slice(..)) - .transform(|range| { - movement::move_next_long_word_start(doc.text().slice(..), range, count) - }), - ); + let text = doc.text().slice(..); + + let selection = doc + .selection(view.id) + .clone() + .min_width_1(text) + .transform(|range| movement::move_next_long_word_start(text, range, count)); + doc.set_selection(view.id, selection); } fn move_prev_long_word_start(cx: &mut Context) { let count = cx.count(); let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id) - .clone() - .min_width_1(doc.text().slice(..)) - .transform(|range| { - movement::move_prev_long_word_start(doc.text().slice(..), range, count) - }), - ); + let text = doc.text().slice(..); + + let selection = doc + .selection(view.id) + .clone() + .min_width_1(text) + .transform(|range| movement::move_prev_long_word_start(text, range, count)); + doc.set_selection(view.id, selection); } fn move_next_long_word_end(cx: &mut Context) { let count = cx.count(); let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id) - .clone() - .min_width_1(doc.text().slice(..)) - .transform(|range| { - movement::move_next_long_word_end(doc.text().slice(..), range, count) - }), - ); + let text = doc.text().slice(..); + + let selection = doc + .selection(view.id) + .clone() + .min_width_1(text) + .transform(|range| movement::move_next_long_word_end(text, range, count)); + doc.set_selection(view.id, selection); } fn goto_file_start(cx: &mut Context) { @@ -590,52 +560,52 @@ fn goto_file_end(cx: &mut Context) { fn extend_next_word_start(cx: &mut Context) { let count = cx.count(); let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id) - .clone() - .min_width_1(doc.text().slice(..)) - .transform(|range| { - let text = doc.text().slice(..); - let word = movement::move_next_word_start(text, range, count); - let pos = word.head; - range.put(text, pos, true) - }), - ); + let text = doc.text().slice(..); + + let selection = doc + .selection(view.id) + .clone() + .min_width_1(text) + .transform(|range| { + let word = movement::move_next_word_start(text, range, count); + let pos = word.head; + range.put(text, pos, true) + }); + doc.set_selection(view.id, selection); } fn extend_prev_word_start(cx: &mut Context) { let count = cx.count(); let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id) - .clone() - .min_width_1(doc.text().slice(..)) - .transform(|range| { - let text = doc.text().slice(..); - let word = movement::move_prev_word_start(text, range, count); - let pos = word.head; - range.put(text, pos, true) - }), - ); + let text = doc.text().slice(..); + + let selection = doc + .selection(view.id) + .clone() + .min_width_1(text) + .transform(|range| { + let word = movement::move_prev_word_start(text, range, count); + let pos = word.head; + range.put(text, pos, true) + }); + doc.set_selection(view.id, selection); } fn extend_next_word_end(cx: &mut Context) { let count = cx.count(); let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id) - .clone() - .min_width_1(doc.text().slice(..)) - .transform(|range| { - let text = doc.text().slice(..); - let word = movement::move_next_word_end(text, range, count); - let pos = word.head; - range.put(text, pos, true) - }), - ); + let text = doc.text().slice(..); + + let selection = doc + .selection(view.id) + .clone() + .min_width_1(text) + .transform(|range| { + let word = movement::move_next_word_end(text, range, count); + let pos = word.head; + range.put(text, pos, true) + }); + doc.set_selection(view.id, selection); } #[inline] @@ -678,15 +648,13 @@ where }; let (view, doc) = current!(cx.editor); + let text = doc.text().slice(..); - doc.set_selection( - view.id, - doc.selection(view.id).clone().transform(|range| { - let text = doc.text().slice(..); - search_fn(text, ch, range.head, count, inclusive) - .map_or(range, |pos| range.put(text, pos, extend)) - }), - ); + let selection = doc.selection(view.id).clone().transform(|range| { + search_fn(text, ch, range.head, count, inclusive) + .map_or(range, |pos| range.put(text, pos, extend)) + }); + doc.set_selection(view.id, selection); }) } @@ -939,69 +907,45 @@ fn half_page_down(cx: &mut Context) { fn extend_char_left(cx: &mut Context) { let count = cx.count(); let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id).clone().transform(|range| { - movement::move_horizontally( - doc.text().slice(..), - range, - Direction::Backward, - count, - Movement::Extend, - ) - }), - ); + let text = doc.text().slice(..); + + let selection = doc.selection(view.id).clone().transform(|range| { + movement::move_horizontally(text, range, Direction::Backward, count, Movement::Extend) + }); + doc.set_selection(view.id, selection); } fn extend_char_right(cx: &mut Context) { let count = cx.count(); let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id).clone().transform(|range| { - movement::move_horizontally( - doc.text().slice(..), - range, - Direction::Forward, - count, - Movement::Extend, - ) - }), - ); + let text = doc.text().slice(..); + + let selection = doc.selection(view.id).clone().transform(|range| { + movement::move_horizontally(text, range, Direction::Forward, count, Movement::Extend) + }); + doc.set_selection(view.id, selection); } fn extend_line_up(cx: &mut Context) { let count = cx.count(); let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id).clone().transform(|range| { - movement::move_vertically( - doc.text().slice(..), - range, - Direction::Backward, - count, - Movement::Extend, - ) - }), - ); + let text = doc.text().slice(..); + + let selection = doc.selection(view.id).clone().transform(|range| { + movement::move_vertically(text, range, Direction::Backward, count, Movement::Extend) + }); + doc.set_selection(view.id, selection); } fn extend_line_down(cx: &mut Context) { let count = cx.count(); let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id).clone().transform(|range| { - movement::move_vertically( - doc.text().slice(..), - range, - Direction::Forward, - count, - Movement::Extend, - ) - }), - ); + let text = doc.text().slice(..); + + let selection = doc.selection(view.id).clone().transform(|range| { + movement::move_vertically(text, range, Direction::Forward, count, Movement::Extend) + }); + doc.set_selection(view.id, selection); } fn select_all(cx: &mut Context) { @@ -1222,30 +1166,28 @@ fn change_selection(cx: &mut Context) { fn collapse_selection(cx: &mut Context) { let (view, doc) = current!(cx.editor); + let text = doc.text().slice(..); - doc.set_selection( - view.id, - doc.selection(view.id).clone().transform(|range| { - let pos = if range.head > range.anchor { - // For 1-width cursor semantics. - graphemes::prev_grapheme_boundary(doc.text().slice(..), range.head) - } else { - range.head - }; - Range::new(pos, pos) - }), - ); + let selection = doc.selection(view.id).clone().transform(|range| { + let pos = if range.head > range.anchor { + // For 1-width cursor semantics. + graphemes::prev_grapheme_boundary(text, range.head) + } else { + range.head + }; + Range::new(pos, pos) + }); + doc.set_selection(view.id, selection); } fn flip_selections(cx: &mut Context) { let (view, doc) = current!(cx.editor); - doc.set_selection( - view.id, - doc.selection(view.id) - .clone() - .transform(|range| Range::new(range.head, range.anchor)), - ); + let selection = doc + .selection(view.id) + .clone() + .transform(|range| Range::new(range.head, range.anchor)); + doc.set_selection(view.id, selection); } fn enter_insert_mode(doc: &mut Document) { @@ -1257,12 +1199,11 @@ fn insert_mode(cx: &mut Context) { let (view, doc) = current!(cx.editor); enter_insert_mode(doc); - doc.set_selection( - view.id, - doc.selection(view.id) - .clone() - .transform(|range| Range::new(range.to(), range.from())), - ); + let selection = doc + .selection(view.id) + .clone() + .transform(|range| Range::new(range.to(), range.from())); + doc.set_selection(view.id, selection); } // inserts at the end of each selection @@ -1286,15 +1227,13 @@ fn append_mode(cx: &mut Context) { doc.apply(&transaction, view.id); } - doc.set_selection( - view.id, - selection.clone().transform(|range| { - Range::new( - range.from(), - graphemes::next_grapheme_boundary(doc.text().slice(..), range.to()), - ) - }), - ); + let selection = selection.transform(|range| { + Range::new( + range.from(), + graphemes::next_grapheme_boundary(doc.text().slice(..), range.to()), + ) + }); + doc.set_selection(view.id, selection); } mod cmd { @@ -2200,15 +2139,13 @@ fn append_to_line(cx: &mut Context) { let (view, doc) = current!(cx.editor); enter_insert_mode(doc); - doc.set_selection( - view.id, - doc.selection(view.id).clone().transform(|range| { - let text = doc.text().slice(..); - let line = range.head_line(text); - let pos = line_end_char_index(&text, line); - Range::new(pos, pos) - }), - ); + let selection = doc.selection(view.id).clone().transform(|range| { + let text = doc.text().slice(..); + let line = range.head_line(text); + let pos = line_end_char_index(&text, line); + Range::new(pos, pos) + }); + doc.set_selection(view.id, selection); } /// Sometimes when applying formatting changes we want to mark the buffer as unmodified, for @@ -2338,15 +2275,14 @@ fn normal_mode(cx: &mut Context) { // if leaving append mode, move cursor back by 1 if doc.restore_cursor { - doc.set_selection( - view.id, - doc.selection(view.id).clone().transform(|range| { - Range::new( - range.from(), - graphemes::prev_grapheme_boundary(doc.text().slice(..), range.to()), - ) - }), - ); + let text = doc.text().slice(..); + let selection = doc.selection(view.id).clone().transform(|range| { + Range::new( + range.from(), + graphemes::prev_grapheme_boundary(text, range.to()), + ) + }); + doc.set_selection(view.id, selection); doc.restore_cursor = false; } @@ -2370,22 +2306,21 @@ fn goto_last_accessed_file(cx: &mut Context) { fn select_mode(cx: &mut Context) { let (view, doc) = current!(cx.editor); + let text = doc.text().slice(..); // Make sure all selections are at least 1-wide. // (With the exception of being in an empty document, of course.) - doc.set_selection( - view.id, - doc.selection(view.id).clone().transform(|range| { - if range.is_empty() && range.head == doc.text().len_chars() { - Range::new( - graphemes::prev_grapheme_boundary(doc.text().slice(..), range.anchor), - range.head, - ) - } else { - range.min_width_1(doc.text().slice(..)) - } - }), - ); + let selection = doc.selection(view.id).clone().transform(|range| { + if range.is_empty() && range.head == text.len_chars() { + Range::new( + graphemes::prev_grapheme_boundary(text, range.anchor), + range.head, + ) + } else { + range.min_width_1(text) + } + }); + doc.set_selection(view.id, selection); doc_mut!(cx.editor).mode = Mode::Select; } @@ -2964,13 +2899,13 @@ pub mod insert { pub fn delete_word_backward(cx: &mut Context) { let count = cx.count(); let (view, doc) = current!(cx.editor); + let text = doc.text().slice(..); - doc.set_selection( - view.id, - doc.selection(view.id).clone().transform(|range| { - movement::move_prev_word_start(doc.text().slice(..), range, count) - }), - ); + let selection = doc + .selection(view.id) + .clone() + .transform(|range| movement::move_prev_word_start(text, range, count)); + doc.set_selection(view.id, selection); delete_selection(cx) } } @@ -3721,21 +3656,19 @@ fn select_textobject(cx: &mut Context, objtype: textobject::TextObject) { } = event { let (view, doc) = current!(cx.editor); + let text = doc.text().slice(..); - doc.set_selection( - view.id, - doc.selection(view.id).clone().transform(|range| { - let text = doc.text().slice(..); - match ch { - 'w' => textobject::textobject_word(text, range, objtype, count), - // TODO: cancel new ranges if inconsistent surround matches across lines - ch if !ch.is_ascii_alphanumeric() => { - textobject::textobject_surround(text, range, objtype, ch, count) - } - _ => range, + let selection = doc.selection(view.id).clone().transform(|range| { + match ch { + 'w' => textobject::textobject_word(text, range, objtype, count), + // TODO: cancel new ranges if inconsistent surround matches across lines + ch if !ch.is_ascii_alphanumeric() => { + textobject::textobject_surround(text, range, objtype, ch, count) } - }), - ); + _ => range, + } + }); + doc.set_selection(view.id, selection); } }) }