@@ -255,7 +255,8 @@ impl Command {
255 space_mode,
255 space_mode,
256 view_mode,
256 view_mode,
257 left_bracket_mode,
257 left_bracket_mode,
258− right_bracket_mode
258+ right_bracket_mode,
@@ -1906,6 +1907,7 @@ fn goto_mode(cx: &mut Context) {
1906 match (doc.mode, ch) {
1907 match (doc.mode, ch) {
1907 (_, 'g') => move_file_start(cx),
1908 (_, 'g') => move_file_start(cx),
1908 (_, 'e') => move_file_end(cx),
1909 (_, 'e') => move_file_end(cx),
1910+ (_, 'm') => match_brackets(cx),
1909 (_, 'a') => switch_to_last_accessed_file(cx),
1911 (_, 'a') => switch_to_last_accessed_file(cx),
1910 (Mode::Normal, 'h') => move_line_start(cx),
1912 (Mode::Normal, 'h') => move_line_start(cx),
1911 (Mode::Normal, 'l') => move_line_end(cx),
1913 (Mode::Normal, 'l') => move_line_end(cx),
@@ -3311,6 +3313,122 @@ fn right_bracket_mode(cx: &mut Context) {
3316+fn surround(cx: &mut Context) {
3317+ let count = cx.count;
3318+ cx.on_next_key(move |cx, event| {
3320+ code: KeyCode::Char(ch),
3324+ // FIXME: count gets reset because of cx.on_next_key()
3327+ 'a' => surround_add(cx),
3328+ 'r' => surround_replace(cx),
3330+ surround_delete(cx);
3331+ let (view, doc) = current!(cx.editor);
3339+use helix_core::surround;
3341+fn surround_add(cx: &mut Context) {
3342+ cx.on_next_key(move |cx, event| {
3344+ code: KeyCode::Char(ch),
3348+ let (view, doc) = current!(cx.editor);
3349+ let text = doc.text().slice(..);
3350+ let selection = doc.selection(view.id);
3351+ let (open, close) = surround::get_pair(ch);
3353+ let mut changes = Vec::new();
3354+ for (i, range) in selection.iter().enumerate() {
3355+ let (from, to) = (range.from(), range.to() + 1);
3356+ changes.push((from, from, Some(Tendril::from_char(open))));
3357+ changes.push((to, to, Some(Tendril::from_char(close))));
3360+ let transaction = Transaction::change(doc.text(), changes.into_iter());
3361+ doc.apply(&transaction, view.id);
3362+ doc.append_changes_to_history(view.id);
3367+fn surround_replace(cx: &mut Context) {
3368+ let count = cx.count();
3369+ cx.on_next_key(move |cx, event| {
3371+ code: KeyCode::Char(from),
3375+ cx.on_next_key(move |cx, event| {
3377+ code: KeyCode::Char(to),
3381+ let (view, doc) = current!(cx.editor);
3382+ let text = doc.text().slice(..);
3383+ let selection = doc.selection(view.id);
3385+ let change_pos = match surround::get_surround_pos(text, selection, from, count)
3391+ let (open, close) = surround::get_pair(to);
3392+ let transaction = Transaction::change(
3394+ change_pos.iter().enumerate().map(|(i, &pos)| {
3395+ let ch = if i % 2 == 0 { open } else { close };
3396+ (pos, pos + 1, Some(Tendril::from_char(ch)))
3399+ doc.apply(&transaction, view.id);
3400+ doc.append_changes_to_history(view.id);
3407+fn surround_delete(cx: &mut Context) {
3408+ let count = cx.count();
3409+ cx.on_next_key(move |cx, event| {
3411+ code: KeyCode::Char(ch),
3415+ let (view, doc) = current!(cx.editor);
3416+ let text = doc.text().slice(..);
3417+ let selection = doc.selection(view.id);
3419+ let change_pos = match surround::get_surround_pos(text, selection, ch, count) {
3425+ Transaction::change(doc.text(), change_pos.into_iter().map(|p| (p, p + 1, None)));
3426+ doc.apply(&transaction, view.id);
3427+ doc.append_changes_to_history(view.id);
3314impl fmt::Display for Command {
3432impl fmt::Display for Command {
3315 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3433 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3316 let Command(name, _) = self;
3434 let Command(name, _) = self;