diff options
author | Pascal Kuthe | 2023-03-08 01:49:14 +0000 |
---|---|---|
committer | GitHub | 2023-03-08 01:49:14 +0000 |
commit | 48b6aa9a699df0680a6d31e9611ebd1ca9909de4 (patch) | |
tree | 11459e49578000678f494857cfbe1f60bfe2ba20 /helix-term/src/commands | |
parent | 8c2e447b16e4d11db411b18f2fbe3ac2bc031d89 (diff) |
Add command for resetting diff hunks (#5736)
Diffstat (limited to 'helix-term/src/commands')
-rw-r--r-- | helix-term/src/commands/typed.rs | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs index 0ddca6df..77c14321 100644 --- a/helix-term/src/commands/typed.rs +++ b/helix-term/src/commands/typed.rs @@ -2033,6 +2033,64 @@ fn run_shell_command( Ok(()) } +fn reset_diff_change( + cx: &mut compositor::Context, + args: &[Cow<str>], + event: PromptEvent, +) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + ensure!(args.is_empty(), ":reset-diff-change takes no arguments"); + + let editor = &mut cx.editor; + let scrolloff = editor.config().scrolloff; + + let (view, doc) = current!(editor); + // TODO refactor to use let..else once MSRV is raised to 1.65 + let handle = match doc.diff_handle() { + Some(handle) => handle, + None => bail!("Diff is not available in the current buffer"), + }; + + let diff = handle.load(); + let doc_text = doc.text().slice(..); + let line = doc.selection(view.id).primary().cursor_line(doc_text); + + // TODO refactor to use let..else once MSRV is raised to 1.65 + let hunk_idx = match diff.hunk_at(line as u32, true) { + Some(hunk_idx) => hunk_idx, + None => bail!("There is no change at the cursor"), + }; + let hunk = diff.nth_hunk(hunk_idx); + let diff_base = diff.diff_base(); + let before_start = diff_base.line_to_char(hunk.before.start as usize); + let before_end = diff_base.line_to_char(hunk.before.end as usize); + let text: Tendril = diff + .diff_base() + .slice(before_start..before_end) + .chunks() + .collect(); + let anchor = doc_text.line_to_char(hunk.after.start as usize); + let transaction = Transaction::change( + doc.text(), + [( + anchor, + doc_text.line_to_char(hunk.after.end as usize), + (!text.is_empty()).then_some(text), + )] + .into_iter(), + ); + drop(diff); // make borrow check happy + doc.apply(&transaction, view.id); + // select inserted text + let text_len = before_end - before_start; + doc.set_selection(view.id, Selection::single(anchor, anchor + text_len)); + doc.append_changes_to_history(view); + view.ensure_cursor_in_view(doc, scrolloff); + Ok(()) +} + pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[ TypableCommand { name: "quit", @@ -2569,6 +2627,13 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[ fun: run_shell_command, completer: Some(completers::filename), }, + TypableCommand { + name: "reset-diff-change", + aliases: &["diffget", "diffg"], + doc: "Reset the diff change at the cursor position.", + fun: reset_diff_change, + completer: None, + }, ]; pub static TYPABLE_COMMAND_MAP: Lazy<HashMap<&'static str, &'static TypableCommand>> = |