@@ -5,7 +5,7 @@ use helix_core::{
5 regex::{self, Regex},
5 regex::{self, Regex},
6 register, search, selection,
6 register, search, selection,
7 state::{coords_at_pos, pos_at_coords, Direction, Granularity, State},
7 state::{coords_at_pos, pos_at_coords, Direction, Granularity, State},
8− Change, ChangeSet, Position, Range, Selection, Tendril, Transaction,
8+ Change, ChangeSet, Position, Range, RopeSlice, Selection, Tendril, Transaction,
11use once_cell::sync::Lazy;
11use once_cell::sync::Lazy;
@@ -236,7 +236,13 @@ pub fn extend_next_word_end(cx: &mut Context) {
236 doc.set_selection(selection);
236 doc.set_selection(selection);
239−pub fn find_next_char(cx: &mut Context) {
239+#[inline]
240+fn _find_char<F>(cx: &mut Context, search_fn: F, inclusive: bool, extend: bool)
242+ // TODO: make an options struct for and abstract this Fn into a searcher type
243+ // use the definition for w/b/e too
244+ F: Fn(RopeSlice, char, usize, usize, bool) -> Option<usize>,
240 // TODO: count is reset to 1 before next key so we move it into the closure here.
246 // TODO: count is reset to 1 before next key so we move it into the closure here.
241 // Would be nice to carry over.
247 // Would be nice to carry over.
242 let count = cx.count;
248 let count = cx.count;
@@ -252,9 +258,13 @@ pub fn find_next_char(cx: &mut Context) {
252 let text = doc.text().slice(..);
258 let text = doc.text().slice(..);
254 let selection = doc.selection().transform(|mut range| {
260 let selection = doc.selection().transform(|mut range| {
255− if let Some(pos) = search::find_nth_next(text, ch, range.head, count) {
261+ if let Some(pos) = search::find_nth_next(text, ch, range.head, count, inclusive) {
256− Range::new(range.head, pos)
262+ if extend {
257− // or (range.anchor, pos) for extend
263+ Range::new(range.anchor, pos)
266+ Range::new(range.head, pos)
258 // or (pos, pos) to move to found val
268 // or (pos, pos) to move to found val
@@ -266,6 +276,78 @@ pub fn find_next_char(cx: &mut Context) {
279+pub fn find_till_char(cx: &mut Context) {
282+ search::find_nth_next,
283+ false, /* inclusive */
288+pub fn find_next_char(cx: &mut Context) {
291+ search::find_nth_next,
292+ true, /* inclusive */
297+pub fn extend_till_char(cx: &mut Context) {
300+ search::find_nth_next,
301+ false, /* inclusive */
306+pub fn extend_next_char(cx: &mut Context) {
309+ search::find_nth_next,
310+ true, /* inclusive */
315+pub fn till_prev_char(cx: &mut Context) {
318+ search::find_nth_prev,
319+ false, /* inclusive */
324+pub fn find_prev_char(cx: &mut Context) {
327+ search::find_nth_prev,
328+ true, /* inclusive */
333+pub fn extend_till_prev_char(cx: &mut Context) {
336+ search::find_nth_prev,
337+ false, /* inclusive */
342+pub fn extend_prev_char(cx: &mut Context) {
345+ search::find_nth_prev,
346+ true, /* inclusive */
269fn scroll(view: &mut View, offset: usize, direction: Direction) {
351fn scroll(view: &mut View, offset: usize, direction: Direction) {
270 use Direction::*;
352 use Direction::*;
271 let text = view.doc.text().slice(..);
353 let text = view.doc.text().slice(..);