@@ -3,7 +3,7 @@ use helix_core::{
3 indent::TAB_WIDTH,
3 indent::TAB_WIDTH,
5 regex::{self, Regex},
5 regex::{self, Regex},
6− register, 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, Selection, Tendril, Transaction,
@@ -19,12 +19,15 @@ use helix_view::{
19 Document, Editor,
19 Document, Editor,
22+use crossterm::event::{KeyCode, KeyEvent};
22pub struct Context<'a> {
24pub struct Context<'a> {
23 pub count: usize,
25 pub count: usize,
24 pub editor: &'a mut Editor,
26 pub editor: &'a mut Editor,
25 pub executor: &'static smol::Executor<'static>,
27 pub executor: &'static smol::Executor<'static>,
27 pub callback: Option<crate::compositor::Callback>,
29 pub callback: Option<crate::compositor::Callback>,
30+ pub on_next_key_callback: Option<Box<dyn FnOnce(&mut Context, KeyEvent)>>,
30impl<'a> Context<'a> {
33impl<'a> Context<'a> {
@@ -49,6 +52,14 @@ impl<'a> Context<'a> {
59+ on_next_key_callback: impl FnOnce(&mut Context, KeyEvent) + 'static,
61+ self.on_next_key_callback = Some(Box::new(on_next_key_callback));
54/// A command is a function that takes the current state and a count, and does a side-effect on the
65/// A command is a function that takes the current state and a count, and does a side-effect on the
@@ -225,6 +236,36 @@ pub fn extend_next_word_end(cx: &mut Context) {
225 doc.set_selection(selection);
236 doc.set_selection(selection);
239+pub fn find_next_char(cx: &mut Context) {
240+ // TODO: count is reset to 1 before next key so we move it into the closure here.
241+ // Would be nice to carry over.
242+ let count = cx.count;
244+ // need to wait for next key
245+ cx.on_next_key(move |cx, event| {
247+ code: KeyCode::Char(ch),
252+ let text = doc.text().slice(..);
254+ let selection = doc.selection().transform(|mut range| {
255+ if let Some(pos) = search::find_nth_next(text, ch, range.head, count) {
256+ Range::new(range.head, pos)
257+ // or (range.anchor, pos) for extend
258+ // or (pos, pos) to move to found val
264+ doc.set_selection(selection);
228fn scroll(view: &mut View, offset: usize, direction: Direction) {
269fn scroll(view: &mut View, offset: usize, direction: Direction) {
229 use Direction::*;
270 use Direction::*;
230 let text = view.doc.text().slice(..);
271 let text = view.doc.text().slice(..);