@@ -1,5 +1,7 @@
11use helix_core::{
2− comment, coords_at_pos, find_first_non_whitespace_char, find_root, graphemes, indent,
2+ comment, coords_at_pos, find_first_non_whitespace_char, find_root, graphemes,
3+ history::UndoKind,
4+ indent,
35 indent::IndentStyle,
46 line_ending::{get_line_ending_of_str, line_end_char_index, str_is_line_ending},
57 match_brackets,
@@ -284,6 +286,8 @@ impl Command {
284286 delete_word_backward, "Delete previous word",
285287 undo, "Undo change",
286288 redo, "Redo change",
289+ earlier, "Move backward in history",
290+ later, "Move forward in history",
287291 yank, "Yank selection",
288292 yank_joined_to_clipboard, "Join and yank selections to clipboard",
289293 yank_main_selection_to_clipboard, "Yank main selection to clipboard",
@@ -1877,10 +1881,7 @@ mod cmd {
18771881 args: &[&str],
18781882 _event: PromptEvent,
18791883 ) -> anyhow::Result<()> {
1880− let uk = args
1881− .join(" ")
1882− .parse::<helix_core::history::UndoKind>()
1883− .map_err(|s| anyhow!(s))?;
1884+ let uk = args.join(" ").parse::<UndoKind>().map_err(|s| anyhow!(s))?;
18841885
18851886 let (view, doc) = current!(cx.editor);
18861887 let success = doc.earlier(view.id, uk);
@@ -1896,10 +1897,7 @@ mod cmd {
18961897 args: &[&str],
18971898 _event: PromptEvent,
18981899 ) -> anyhow::Result<()> {
1899− let uk = args
1900− .join(" ")
1901− .parse::<helix_core::history::UndoKind>()
1902− .map_err(|s| anyhow!(s))?;
1900+ let uk = args.join(" ").parse::<UndoKind>().map_err(|s| anyhow!(s))?;
19031901 let (view, doc) = current!(cx.editor);
19041902 let success = doc.later(view.id, uk);
19051903 if !success {
@@ -3963,20 +3961,48 @@ pub mod insert {
39633961// storing it?
39643962
39653963fn undo(cx: &mut Context) {
3964+ let count = cx.count();
39663965 let (view, doc) = current!(cx.editor);
3967− let view_id = view.id;
3968− let success = doc.undo(view_id);
3969− if !success {
3970− cx.editor.set_status("Already at oldest change".to_owned());
3966+ for _ in 0..count {
3967+ if !doc.undo(view.id) {
3968+ cx.editor.set_status("Already at oldest change".to_owned());
3969+ break;
3970+ }
39713971 }
39723972}
39733973
39743974fn redo(cx: &mut Context) {
3975+ let count = cx.count();
3976+ let (view, doc) = current!(cx.editor);
3977+ for _ in 0..count {
3978+ if !doc.redo(view.id) {
3979+ cx.editor.set_status("Already at newest change".to_owned());
3980+ break;
3981+ }
3982+ }
3983+}
3984+
3985+fn earlier(cx: &mut Context) {
3986+ let count = cx.count();
3987+ let (view, doc) = current!(cx.editor);
3988+ for _ in 0..count {
3989+ // rather than doing in batch we do this so get error halfway
3990+ if !doc.earlier(view.id, UndoKind::Steps(1)) {
3991+ cx.editor.set_status("Already at oldest change".to_owned());
3992+ break;
3993+ }
3994+ }
3995+}
3996+
3997+fn later(cx: &mut Context) {
3998+ let count = cx.count();
39753999 let (view, doc) = current!(cx.editor);
3976− let view_id = view.id;
3977− let success = doc.redo(view_id);
3978− if !success {
3979− cx.editor.set_status("Already at newest change".to_owned());
4000+ for _ in 0..count {
4001+ // rather than doing in batch we do this so get error halfway
4002+ if !doc.later(view.id, UndoKind::Steps(1)) {
4003+ cx.editor.set_status("Already at newest change".to_owned());
4004+ break;
4005+ }
39804006 }
39814007}
39824008