From c97add7f5a181f459b2f349069507093be2bc738 Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Sat, 3 Feb 2024 00:27:00 +0100 Subject: [PATCH] rc tools git: blame-jump to handle buffer modifications since blame If I run git blame execute-keys 10o,j git blame-jump that'll jump to the wrong commit. Use a flag-lines option to tell if a line still has blame information cached. Closes #5084 --- rc/tools/git.kak | 60 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/rc/tools/git.kak b/rc/tools/git.kak index f3656cecb..d9a603e58 100644 --- a/rc/tools/git.kak +++ b/rc/tools/git.kak @@ -74,6 +74,7 @@ hook -group git-show-branch-highlight global WinSetOption filetype=git-show-bran } declare-option -hidden line-specs git_blame_flags +declare-option -hidden line-specs git_blame_index declare-option -hidden str git_blame declare-option -hidden str git_blob declare-option -hidden line-specs git_diff_flags @@ -180,6 +181,7 @@ define-command -params 1.. \ hide_blame() { printf %s " set-option buffer git_blame_flags $kak_timestamp + set-option buffer git_blame_index $kak_timestamp set-option buffer git_blame %{} remove-highlighter window/git-blame unmap window normal %{:git blame-jump} @@ -272,6 +274,7 @@ define-command -params 1.. \ cd_bufdir printf %s "evaluate-commands -client '$kak_client' %{ set-option buffer=$kak_bufname git_blame_flags '$kak_timestamp' + set-option buffer=$kak_bufname git_blame_index '$kak_timestamp' set-option buffer=$kak_bufname git_blame '' }" | kak -p ${kak_session} git blame --incremental "$@" <${contents_fifo} | perl -wne ' @@ -297,9 +300,11 @@ define-command -params 1.. \ } open CMD, "|-", "kak -p $ENV{kak_session}"; print CMD "set-option -add buffer=$ENV{kak_bufname} git_blame_flags $flags;"; + print CMD "set-option -add buffer=$ENV{kak_bufname} git_blame_index $index;"; print CMD "set-option -add buffer=$ENV{kak_bufname} git_blame " . quote $raw_blame; close(CMD); $flags = ""; + $index = ""; $raw_blame = ""; $last_sent = $now; } @@ -310,6 +315,9 @@ define-command -params 1.. \ $sha = $1; $line = $3; $count = $4; + for ( my $i = 0; $i < $count; $i++ ) { + $index .= " " . ($line+$i) . "|$.,$i"; + } } if (m/^author /) { $authors{$sha} = substr($_,7); @@ -483,11 +491,16 @@ define-command -params 1.. \ blame_jump() { echo >${kak_command_fifo} "echo -to-file ${kak_response_fifo} -- %opt{git_blame}" blame_info=$(cat < ${kak_response_fifo}) + blame_index= cursor_column=${kak_cursor_column} cursor_line=${kak_cursor_line} - if [ -z "$blame_info" ] && { - [ "${kak_opt_filetype}" = git-diff ] || [ "${kak_opt_filetype}" = git-log ] - }; then { + if [ -n "$blame_info" ]; then { + echo >${kak_command_fifo} " + update-option buffer git_blame_index + echo -to-file ${kak_response_fifo} -- %opt{git_blame_index} + " + blame_index=$(cat < ${kak_response_fifo}) + } elif [ "${kak_opt_filetype}" = git-diff ] || [ "${kak_opt_filetype}" = git-log ]; then { printf >${kak_command_fifo} %s ' evaluate-commands -draft %{ try %{ @@ -528,7 +541,7 @@ define-command -params 1.. \ cursor_line=$3 cursor_column=$4 blame_info=$(git blame --porcelain "$starting_commit" -L"$cursor_line,$cursor_line" -- "$file") - } elif [ -z "$blame_info" ]; then { + } else { set -- eval "$prepare_git_blame_args" blame_info=$(git blame --porcelain -L"$cursor_line,$cursor_line" "$@" <${contents_fifo}) @@ -536,7 +549,7 @@ define-command -params 1.. \ rm -r $(dirname $contents_fifo) fi } fi - eval "$(printf %s "$blame_info" | + eval "$(printf '%s\n---\n%s' "$blame_index" "$blame_info" | client=${kak_opt_docsclient:-$kak_client} \ cursor_line=$cursor_line cursor_column=$cursor_column \ perl -wne ' @@ -562,8 +575,28 @@ define-command -params 1.. \ return "$SQ$token$SQ"; } $target = $ENV{"cursor_line"}; + $state = "index"; } chomp; + if ($state eq "index") { + if ($_ eq "---") { + $state = "blame"; + next; + } + @blame_index = split; + next unless @blame_index; + shift @blame_index; + foreach (@blame_index) { + $_ =~ m{(\d+)\|(\d+),(\d+)} or die "bad blame index flag: $_"; + my $buffer_line = $1; + if ($buffer_line == $target) { + $target_in_blame = $2; + $target_offset = $3; + last; + } + } + defined $target_in_blame and next, or last; + } if (m/^([0-9a-f]+) ([0-9]+) ([0-9]+) ([0-9]+)/) { if ($done) { last; @@ -572,9 +605,16 @@ define-command -params 1.. \ $old_line = $2; $new_line = $3; $count = $4; - if ($new_line <= $target and $target < $new_line + $count) { - $old_line += $target - $new_line; - $done = 1; + if (defined $target_in_blame) { + if ($target_in_blame == $. - 2) { + $old_line += $target_offset; + $done = 1; + } + } else { + if ($new_line <= $target and $target < $new_line + $count) { + $old_line += $target - $new_line; + $done = 1; + } } } if (m/^filename /) { $old_filenames{$sha} = substr($_,9) } @@ -582,6 +622,10 @@ define-command -params 1.. \ if (m/^author-time ([0-9]*)/) { $dates{$sha} = strftime("%F", localtime $1) } if (m/^summary /) { $summaries{$sha} = substr($_,8) } END { + if (@blame_index and not defined $target_in_blame) { + print "echo fail git blame-jump: line has no blame information;"; + exit; + } if (not defined $sha) { print "echo fail git blame-jump: missing blame info"; exit;