diff options
Diffstat (limited to 'autoload/tools/patch.kak')
-rw-r--r-- | autoload/tools/patch.kak | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/autoload/tools/patch.kak b/autoload/tools/patch.kak new file mode 100644 index 0000000..a481ff4 --- /dev/null +++ b/autoload/tools/patch.kak @@ -0,0 +1,63 @@ +define-command patch -params .. -docstring %{ + patch [<arguments>]: apply selections in diff to a file + + Given some selections within a unified diff, apply the changed lines in + each selection by piping them to "patch <arguments> 1>&2" + (or "<arguments> 1>&2" if <arguments> starts with a non-option argument). + If successful, the in-buffer diff will be updated to reflect the applied + changes. + For selections that contain no newline, the entire enclosing diff hunk + is applied (unless the cursor is inside a diff header, in which case + the entire diff is applied). + To revert changes, <arguments> must contain "--reverse" or "-R". +} %{ + evaluate-commands -draft -itersel -save-regs aes|^ %{ + try %{ + execute-keys <a-k>\n<ret> + } catch %{ + # The selection contains no newline. + execute-keys -save-regs '' Z + execute-keys <a-l><semicolon><a-?>^diff<ret> + try %{ + execute-keys <a-k>^@@<ret> + # If the cursor is in a diff hunk, stage the entire hunk. + execute-keys z + execute-keys /.*?(?:(?=\n@@)|(?=\ndiff)|(?=\n\n)|\z)<ret>x<semicolon><a-?>^@@<ret> + } catch %{ + # If the cursor is in a diff header, stage the entire diff. + execute-keys <a-semicolon>?.*?(?:(?=\ndiff)|(?=\n\n)|\z)<ret> + } + } + # We want to apply only the selected lines. Remember them. + execute-keys <a-:> + set-register s %val{selection_desc} + # Select forward until the end of the last hunk. + execute-keys H?.*?(?:(?=\n@@)|(?=\ndiff)|(?=\n\n)|\z)<ret>x + # Select backward to the beginning of the first hunk's diff header. + execute-keys <a-semicolon><a-L><a-?>^diff<ret> + # Move cursor to the beginning so we know the diff's offset within the buffer. + execute-keys <a-:><a-semicolon> + set-register a %arg{@} + set-register e nop + set-register | %{ + # The selected range to apply. + IFS=' .,' read min_line _ max_line _ <<-EOF + $kak_reg_s + EOF + min_line=$((min_line - kak_cursor_line + 1)) + max_line=$((max_line - kak_cursor_line + 1)) + + # Since registers are never empty, we get an empty arg even if + # there were no args. This does no harm because we pass it to + # a shell where it expands to nothing. + eval set -- "$kak_quoted_reg_a" + + perl "${kak_runtime}"/rc/tools/patch-range.pl $min_line $max_line "$@" || + echo >$kak_command_fifo "set-register e fail 'patch: failed to apply selections, see *debug* buffer'" + } + execute-keys |<ret> + %reg{e} + } +} + +provide-module patch %ยงยง |