|
|
@ -1251,6 +1251,65 @@ fn extend_next_long_word_end(cx: &mut Context) {
|
|
|
|
extend_word_impl(cx, movement::move_next_long_word_end)
|
|
|
|
extend_word_impl(cx, movement::move_next_long_word_end)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Separate branch to find_char designed only for <ret> char.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// This is necessary because the one document can have different line endings inside. And we
|
|
|
|
|
|
|
|
// cannot predict what character to find when <ret> is pressed. On the current line it can be `lf`
|
|
|
|
|
|
|
|
// but on the next line it can be `crlf`. That's why [`find_char_impl`] cannot be applied here.
|
|
|
|
|
|
|
|
fn find_char_line_ending(
|
|
|
|
|
|
|
|
cx: &mut Context,
|
|
|
|
|
|
|
|
count: usize,
|
|
|
|
|
|
|
|
direction: Direction,
|
|
|
|
|
|
|
|
inclusive: bool,
|
|
|
|
|
|
|
|
extend: bool,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
let (view, doc) = current!(cx.editor);
|
|
|
|
|
|
|
|
let text = doc.text().slice(..);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let selection = doc.selection(view.id).clone().transform(|range| {
|
|
|
|
|
|
|
|
let cursor = range.cursor(text);
|
|
|
|
|
|
|
|
let cursor_line = range.cursor_line(text);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Finding the line where we're going to find <ret>. Depends mostly on
|
|
|
|
|
|
|
|
// `count`, but also takes into account edge cases where we're already at the end
|
|
|
|
|
|
|
|
// of a line or the beginning of a line
|
|
|
|
|
|
|
|
let find_on_line = match direction {
|
|
|
|
|
|
|
|
Direction::Forward => {
|
|
|
|
|
|
|
|
let on_edge = line_end_char_index(&text, cursor_line) == cursor;
|
|
|
|
|
|
|
|
let line = cursor_line + count - 1 + (on_edge as usize);
|
|
|
|
|
|
|
|
if line >= text.len_lines() - 1 {
|
|
|
|
|
|
|
|
return range;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
line
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Direction::Backward => {
|
|
|
|
|
|
|
|
let on_edge = text.line_to_char(cursor_line) == cursor && !inclusive;
|
|
|
|
|
|
|
|
let line = cursor_line as isize - (count as isize - 1 + on_edge as isize);
|
|
|
|
|
|
|
|
if line <= 0 {
|
|
|
|
|
|
|
|
return range;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
line as usize
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let pos = match (direction, inclusive) {
|
|
|
|
|
|
|
|
(Direction::Forward, true) => line_end_char_index(&text, find_on_line),
|
|
|
|
|
|
|
|
(Direction::Forward, false) => line_end_char_index(&text, find_on_line) - 1,
|
|
|
|
|
|
|
|
(Direction::Backward, true) => line_end_char_index(&text, find_on_line - 1),
|
|
|
|
|
|
|
|
(Direction::Backward, false) => text.line_to_char(find_on_line),
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if extend {
|
|
|
|
|
|
|
|
range.put_cursor(text, pos, true)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
Range::point(range.cursor(text)).put_cursor(text, pos, true)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
doc.set_selection(view.id, selection);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn find_char(cx: &mut Context, direction: Direction, inclusive: bool, extend: bool) {
|
|
|
|
fn find_char(cx: &mut Context, direction: Direction, inclusive: bool, extend: bool) {
|
|
|
|
// TODO: count is reset to 1 before next key so we move it into the closure here.
|
|
|
|
// TODO: count is reset to 1 before next key so we move it into the closure here.
|
|
|
|
// Would be nice to carry over.
|
|
|
|
// Would be nice to carry over.
|
|
|
@ -1264,13 +1323,9 @@ fn find_char(cx: &mut Context, direction: Direction, inclusive: bool, extend: bo
|
|
|
|
KeyEvent {
|
|
|
|
KeyEvent {
|
|
|
|
code: KeyCode::Enter,
|
|
|
|
code: KeyCode::Enter,
|
|
|
|
..
|
|
|
|
..
|
|
|
|
} =>
|
|
|
|
} => {
|
|
|
|
// TODO: this isn't quite correct when CRLF is involved.
|
|
|
|
find_char_line_ending(cx, count, direction, inclusive, extend);
|
|
|
|
// This hack will work in most cases, since documents don't
|
|
|
|
return;
|
|
|
|
// usually mix line endings. But we should fix it eventually
|
|
|
|
|
|
|
|
// anyway.
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
doc!(cx.editor).line_ending.as_str().chars().next().unwrap()
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
KeyEvent {
|
|
|
|
KeyEvent {
|
|
|
|