summaryrefslogtreecommitdiff
path: root/rc/filetype/diff-parse.pl
diff options
context:
space:
mode:
authorJohannes Altmanninger <aclopte@gmail.com>2024-02-03 00:26:56 +0100
committerMaxime Coste <mawww@kakoune.org>2024-02-05 21:42:02 +1100
commit86d940c225d4d1e316efebf6d915feaa1aa49f63 (patch)
treeecba59b0d5f79b7618fcd698fa32cd64cb7ffa61 /rc/filetype/diff-parse.pl
parent36efbf4cbfe70c7fb8ca8ac6171cd5d8b134fdc0 (diff)
rc tools git: command for easy recursive blaming
Our ":git blame" annotates each line with the most recent commit. However often a line has been modified by several commits. Introduce ":git blame-jump" which shows the commit that added the line at cursor. Crucially, it works also in Git diff buffers, so it can be used recursively to find the full history of a line. To do the recursive blame from a diff, I need to navigate to the old (deleted) version of a line. Since old and new line are usually neighbors. Speed up the common scenario of finding the old version by making ":git blame-jump" jump to the new version. This means the initial diff view might not include the commit message etc. Compensate this by showing the commit's date+author+subject in the status line. Here are some test cases. - run blame-jump after "git blame" - create an uncommitted or unsaved line, run "git blame" and "blame-jump" on the uncommitted line - run blame-jump without running "git blame" - run blame-jump in "git show" - run blame-jump in "git diff HEAD" - run blame-jump in "git diff --cached" - run blame-jump in "git diff" (YMMV if there are cached changes, could fix that) Naming: there are some similar commands in the wild [1]; they are usually called "show-blamed" or similar, but they don't jump to the corresponding line. Also our list of git commands is getting a bit messy (especially the undocumented show-diff/hide-diff/next-hunk/prev-hunk; subject first naming seems better). [1]: https://github.com/robertmeta/kak/blob/f6e78ec4c0eeccd091e6275828234d98e6aa3a7f/kakrc#L423 Future work: to go back to the previously-blamed commit we need to have had the foresight to use "rename-buffer". Perhaps we want to add some kind of buffer stack (like Magit does for example).
Diffstat (limited to 'rc/filetype/diff-parse.pl')
-rwxr-xr-xrc/filetype/diff-parse.pl16
1 files changed, 16 insertions, 0 deletions
diff --git a/rc/filetype/diff-parse.pl b/rc/filetype/diff-parse.pl
index f7858eb7..203e9b19 100755
--- a/rc/filetype/diff-parse.pl
+++ b/rc/filetype/diff-parse.pl
@@ -39,11 +39,17 @@ while (defined $ARGV[0]) {
# Inputs
our $directory = $ENV{PWD};
our $strip;
+our $in_file;
+our $in_file_line;
our $version = "+";
eval $begin if defined $begin;
+$in_file = "$directory/$in_file" if defined $in_file;
+
# Outputs
+our $diff_line = 0;
+our $commit;
our $file;
our $file_line;
our $diff_line_text;
@@ -83,8 +89,13 @@ sub strip {
}
while (<STDIN>) {
+ $diff_line++;
s/^(> )*//g;
$diff_line_text = $_;
+ if (m{^commit (\w+)}) {
+ $commit = $1;
+ next;
+ }
if (m{^diff\b}) {
$state = "header";
$is_recursive_diff = 1;
@@ -116,6 +127,11 @@ while (<STDIN>) {
$other_file_line++ if defined $other_file_line;
}
}
+ if (defined $in_file and defined $file and $file eq $in_file) {
+ if (defined $in_file_line and defined $file_line and $file_line >= $in_file_line) {
+ last;
+ }
+ }
}
if (not defined $file) {
$file = ($fallback_file or $other_file);