Implement the f/t/F/T find/till family of commands.
This commit is contained in:
parent
62c991230f
commit
4acf301022
2
TODO.md
2
TODO.md
@ -25,7 +25,7 @@
|
|||||||
- [ ] CI binary builds
|
- [ ] CI binary builds
|
||||||
|
|
||||||
- [ ] regex search / select next
|
- [ ] regex search / select next
|
||||||
- [ ] f / t mappings
|
- [x] f / t mappings
|
||||||
- [ ] open_above (O) command
|
- [ ] open_above (O) command
|
||||||
- [ ] = for auto indent line/selection
|
- [ ] = for auto indent line/selection
|
||||||
- [x] q should only close the view, if all are closed, close the editor
|
- [x] q should only close the view, if all are closed, close the editor
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
use crate::RopeSlice;
|
use crate::RopeSlice;
|
||||||
|
|
||||||
pub fn find_nth_next(text: RopeSlice, ch: char, mut pos: usize, n: usize) -> Option<usize> {
|
pub fn find_nth_next(
|
||||||
|
text: RopeSlice,
|
||||||
|
ch: char,
|
||||||
|
mut pos: usize,
|
||||||
|
n: usize,
|
||||||
|
inclusive: bool,
|
||||||
|
) -> Option<usize> {
|
||||||
// start searching right after pos
|
// start searching right after pos
|
||||||
let mut chars = text.chars_at(pos + 1);
|
let mut chars = text.chars_at(pos + 1);
|
||||||
|
|
||||||
@ -16,10 +22,20 @@ pub fn find_nth_next(text: RopeSlice, ch: char, mut pos: usize, n: usize) -> Opt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !inclusive {
|
||||||
|
pos -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
Some(pos)
|
Some(pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_nth_prev(text: RopeSlice, ch: char, mut pos: usize, n: usize) -> Option<usize> {
|
pub fn find_nth_prev(
|
||||||
|
text: RopeSlice,
|
||||||
|
ch: char,
|
||||||
|
mut pos: usize,
|
||||||
|
n: usize,
|
||||||
|
inclusive: bool,
|
||||||
|
) -> Option<usize> {
|
||||||
// start searching right before pos
|
// start searching right before pos
|
||||||
let mut chars = text.chars_at(pos.saturating_sub(1));
|
let mut chars = text.chars_at(pos.saturating_sub(1));
|
||||||
|
|
||||||
@ -35,5 +51,9 @@ pub fn find_nth_prev(text: RopeSlice, ch: char, mut pos: usize, n: usize) -> Opt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !inclusive {
|
||||||
|
pos -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
Some(pos)
|
Some(pos)
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
regex::{self, Regex},
|
regex::{self, Regex},
|
||||||
register, search, selection,
|
register, search, selection,
|
||||||
state::{coords_at_pos, pos_at_coords, Direction, Granularity, State},
|
state::{coords_at_pos, pos_at_coords, Direction, Granularity, State},
|
||||||
Change, ChangeSet, Position, Range, Selection, Tendril, Transaction,
|
Change, ChangeSet, Position, Range, RopeSlice, Selection, Tendril, Transaction,
|
||||||
};
|
};
|
||||||
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
@ -236,7 +236,13 @@ pub fn extend_next_word_end(cx: &mut Context) {
|
|||||||
doc.set_selection(selection);
|
doc.set_selection(selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_next_char(cx: &mut Context) {
|
#[inline]
|
||||||
|
fn _find_char<F>(cx: &mut Context, search_fn: F, inclusive: bool, extend: bool)
|
||||||
|
where
|
||||||
|
// TODO: make an options struct for and abstract this Fn into a searcher type
|
||||||
|
// use the definition for w/b/e too
|
||||||
|
F: Fn(RopeSlice, char, usize, usize, bool) -> Option<usize>,
|
||||||
|
{
|
||||||
// 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.
|
||||||
let count = cx.count;
|
let count = cx.count;
|
||||||
@ -252,9 +258,13 @@ pub fn find_next_char(cx: &mut Context) {
|
|||||||
let text = doc.text().slice(..);
|
let text = doc.text().slice(..);
|
||||||
|
|
||||||
let selection = doc.selection().transform(|mut range| {
|
let selection = doc.selection().transform(|mut range| {
|
||||||
if let Some(pos) = search::find_nth_next(text, ch, range.head, count) {
|
if let Some(pos) = search::find_nth_next(text, ch, range.head, count, inclusive) {
|
||||||
|
if extend {
|
||||||
|
Range::new(range.anchor, pos)
|
||||||
|
} else {
|
||||||
|
// select
|
||||||
Range::new(range.head, pos)
|
Range::new(range.head, pos)
|
||||||
// or (range.anchor, pos) for extend
|
}
|
||||||
// or (pos, pos) to move to found val
|
// or (pos, pos) to move to found val
|
||||||
} else {
|
} else {
|
||||||
range
|
range
|
||||||
@ -266,6 +276,78 @@ pub fn find_next_char(cx: &mut Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn find_till_char(cx: &mut Context) {
|
||||||
|
_find_char(
|
||||||
|
cx,
|
||||||
|
search::find_nth_next,
|
||||||
|
false, /* inclusive */
|
||||||
|
false, /* extend */
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_next_char(cx: &mut Context) {
|
||||||
|
_find_char(
|
||||||
|
cx,
|
||||||
|
search::find_nth_next,
|
||||||
|
true, /* inclusive */
|
||||||
|
false, /* extend */
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extend_till_char(cx: &mut Context) {
|
||||||
|
_find_char(
|
||||||
|
cx,
|
||||||
|
search::find_nth_next,
|
||||||
|
false, /* inclusive */
|
||||||
|
true, /* extend */
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extend_next_char(cx: &mut Context) {
|
||||||
|
_find_char(
|
||||||
|
cx,
|
||||||
|
search::find_nth_next,
|
||||||
|
true, /* inclusive */
|
||||||
|
true, /* extend */
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn till_prev_char(cx: &mut Context) {
|
||||||
|
_find_char(
|
||||||
|
cx,
|
||||||
|
search::find_nth_prev,
|
||||||
|
false, /* inclusive */
|
||||||
|
false, /* extend */
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_prev_char(cx: &mut Context) {
|
||||||
|
_find_char(
|
||||||
|
cx,
|
||||||
|
search::find_nth_prev,
|
||||||
|
true, /* inclusive */
|
||||||
|
false, /* extend */
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extend_till_prev_char(cx: &mut Context) {
|
||||||
|
_find_char(
|
||||||
|
cx,
|
||||||
|
search::find_nth_prev,
|
||||||
|
false, /* inclusive */
|
||||||
|
true, /* extend */
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extend_prev_char(cx: &mut Context) {
|
||||||
|
_find_char(
|
||||||
|
cx,
|
||||||
|
search::find_nth_prev,
|
||||||
|
true, /* inclusive */
|
||||||
|
true, /* extend */
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn scroll(view: &mut View, offset: usize, direction: Direction) {
|
fn scroll(view: &mut View, offset: usize, direction: Direction) {
|
||||||
use Direction::*;
|
use Direction::*;
|
||||||
let text = view.doc.text().slice(..);
|
let text = view.doc.text().slice(..);
|
||||||
|
@ -137,10 +137,10 @@ pub fn default() -> Keymaps {
|
|||||||
key!('k') => commands::move_line_up,
|
key!('k') => commands::move_line_up,
|
||||||
key!('l') => commands::move_char_right,
|
key!('l') => commands::move_char_right,
|
||||||
|
|
||||||
// key!('t') => commands::till_next_char,
|
key!('t') => commands::find_till_char,
|
||||||
key!('f') => commands::find_next_char,
|
key!('f') => commands::find_next_char,
|
||||||
// key!('T') => commands::till_prev_char,
|
shift!('T') => commands::till_prev_char,
|
||||||
// key!('f') => commands::find_prev_char,
|
shift!('F') => commands::find_prev_char,
|
||||||
// and matching set for select mode (extend)
|
// and matching set for select mode (extend)
|
||||||
|
|
||||||
key!('0') => commands::move_line_start,
|
key!('0') => commands::move_line_start,
|
||||||
@ -261,6 +261,11 @@ pub fn default() -> Keymaps {
|
|||||||
key!('b') => commands::extend_prev_word_start,
|
key!('b') => commands::extend_prev_word_start,
|
||||||
key!('e') => commands::extend_next_word_end,
|
key!('e') => commands::extend_next_word_end,
|
||||||
|
|
||||||
|
key!('t') => commands::extend_till_char,
|
||||||
|
key!('f') => commands::extend_next_char,
|
||||||
|
shift!('T') => commands::extend_till_prev_char,
|
||||||
|
shift!('F') => commands::extend_prev_char,
|
||||||
|
|
||||||
Key {
|
Key {
|
||||||
code: KeyCode::Esc,
|
code: KeyCode::Esc,
|
||||||
modifiers: Modifiers::NONE
|
modifiers: Modifiers::NONE
|
||||||
|
Loading…
Reference in New Issue
Block a user