Implement the f/t/F/T find/till family of commands.

This commit is contained in:
Blaž Hrastnik 2021-03-11 16:14:52 +09:00
parent 62c991230f
commit 4acf301022
4 changed files with 118 additions and 11 deletions

View File

@ -25,7 +25,7 @@
- [ ] CI binary builds
- [ ] regex search / select next
- [ ] f / t mappings
- [x] f / t mappings
- [ ] open_above (O) command
- [ ] = for auto indent line/selection
- [x] q should only close the view, if all are closed, close the editor

View File

@ -1,6 +1,12 @@
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
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)
}
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
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)
}

View File

@ -5,7 +5,7 @@ use helix_core::{
regex::{self, Regex},
register, search, selection,
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;
@ -236,7 +236,13 @@ pub fn extend_next_word_end(cx: &mut Context) {
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.
// Would be nice to carry over.
let count = cx.count;
@ -252,9 +258,13 @@ pub fn find_next_char(cx: &mut Context) {
let text = doc.text().slice(..);
let selection = doc.selection().transform(|mut range| {
if let Some(pos) = search::find_nth_next(text, ch, range.head, count) {
Range::new(range.head, pos)
// or (range.anchor, pos) for extend
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)
}
// or (pos, pos) to move to found val
} else {
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) {
use Direction::*;
let text = view.doc.text().slice(..);

View File

@ -137,10 +137,10 @@ pub fn default() -> Keymaps {
key!('k') => commands::move_line_up,
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!('T') => commands::till_prev_char,
// key!('f') => commands::find_prev_char,
shift!('T') => commands::till_prev_char,
shift!('F') => commands::find_prev_char,
// and matching set for select mode (extend)
key!('0') => commands::move_line_start,
@ -261,6 +261,11 @@ pub fn default() -> Keymaps {
key!('b') => commands::extend_prev_word_start,
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 {
code: KeyCode::Esc,
modifiers: Modifiers::NONE