rc tools git: change git diff filetype from diff to git-diff

Diff buffers created by ":git diff" differ from other filetype=diff
buffers in that they use "git rev-parse --show-toplevel" as root
directory for diff-jump. This makes sense because paths printed by
"git diff" are relative to that directory.

Today we handle the above difference by making ":git" override the
diff-jump mapping.  This doesn't work for buffers that were read from
a file.  Fix this by introducing a separate filetype, "git-diff",
which allows to move the mapping in the usual place.

This breaks existing filetype=diff hooks[1] which need to be adapted
to match git-diff (also git-log).

Another motivation for the separate filetype is that a following
patch wants to enable Git blame commands in git-diff buffers but
not in plain diff buffers -- those should keep being blamed like any
other file if tracked by Git.
Perhaps git-* buffers are for Git metadata, not files that are tracked
by Git.

The added hooks awkwardly include their hook parameter to work around
hook ordering issues when switching between filetypes. See also [2].

We could also use filetype=git-log instead of git-diff.
Our highlighting for "git log --graph" would have rare false positives.

Closes #5049

[1]: https://github.com/search?utf8=%E2%9C%93&q=filetype%3Ddiff+language%3Akakounescript+-repo%3Amawww%2Fkakoune+-is%3Afork&type=code
[2]: https://lists.sr.ht/~mawww/kakoune/%3C20240201091907.973508-1-aclopte@gmail.com%3E
This commit is contained in:
Johannes Altmanninger 2024-02-03 00:26:53 +01:00 committed by Maxime Coste
parent 7a5bf7f649
commit d6b75ac0bb

View File

@ -14,16 +14,28 @@ declare-option -docstring "git diff top deleted character" \
str git_diff_top_char "‾" str git_diff_top_char "‾"
hook -group git-log-highlight global WinSetOption filetype=git-log %{ hook -group git-log-highlight global WinSetOption filetype=git-log %{
require-module diff
add-highlighter window/git-log group add-highlighter window/git-log group
add-highlighter window/git-log/ regex '^([*|\\ /_.-])*' 0:keyword add-highlighter window/git-log/ regex '^([*|\\ /_.-])*' 0:keyword
add-highlighter window/git-log/ regex '^( ?[*|\\ /_.-])*\h{,3}(commit )?(\b[0-9a-f]{4,40}\b)' 2:keyword 3:comment add-highlighter window/git-log/ regex '^( ?[*|\\ /_.-])*\h{,3}(commit )?(\b[0-9a-f]{4,40}\b)' 2:keyword 3:comment
add-highlighter window/git-log/ regex '^( ?[*|\\ /_.-])*\h{,3}([a-zA-Z_-]+:) (.*?)$' 2:variable 3:value add-highlighter window/git-log/ regex '^( ?[*|\\ /_.-])*\h{,3}([a-zA-Z_-]+:) (.*?)$' 2:variable 3:value
add-highlighter window/git-log/ ref diff # highlight potential diffs from the -p option
hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/git-log } hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/git-log }
} }
hook -group git-diff-highlight global WinSetOption filetype=(git-diff|git-log) %{
require-module diff
add-highlighter %exp{window/%val{hook_param_capture_1}-ref-diff} ref diff
hook -once -always window WinSetOption filetype=.* %exp{
remove-highlighter window/%val{hook_param_capture_1}-ref-diff
}
}
hook global WinSetOption filetype=(?:git-diff|git-log) %{
map buffer normal <ret> %exp{:git-diff-goto-source # %val{hook_param}<ret>} -docstring 'Jump to source from git diff'
hook -once -always window WinSetOption filetype=.* %exp{
unmap buffer normal <ret> %%{:git-diff-goto-source # %val{hook_param}<ret>}
}
}
hook -group git-status-highlight global WinSetOption filetype=git-status %{ hook -group git-status-highlight global WinSetOption filetype=git-status %{
add-highlighter window/git-status group add-highlighter window/git-status group
add-highlighter window/git-status/ regex '^## ' 0:comment add-highlighter window/git-status/ regex '^## ' 0:comment
@ -121,13 +133,12 @@ define-command -params 1.. \
show_git_cmd_output() { show_git_cmd_output() {
local filetype local filetype
local map_diff_goto_source
case "$1" in case "$1" in
diff) map_diff_goto_source=true; filetype=diff ;; diff) filetype=git-diff ;;
show) map_diff_goto_source=true; filetype=git-log ;; show) filetype=git-log ;;
show-branch) filetype=git-show-branch ;; show-branch) filetype=git-show-branch ;;
log) map_diff_goto_source=true; filetype=git-log ;; log) filetype=git-log ;;
status) filetype=git-status ;; status) filetype=git-status ;;
*) return 1 ;; *) return 1 ;;
esac esac
@ -135,17 +146,10 @@ define-command -params 1.. \
mkfifo ${output} mkfifo ${output}
( git "$@" > ${output} 2>&1 & ) > /dev/null 2>&1 < /dev/null ( git "$@" > ${output} 2>&1 & ) > /dev/null 2>&1 < /dev/null
# We need to unmap in case an existing buffer changes type,
# for example if the user runs "git show" and "git status".
map_diff_goto_source=$([ -n "${map_diff_goto_source}" ] \
&& printf %s "map buffer normal <ret> :git-diff-goto-source<ret> -docstring 'Jump to source from git diff'" \
|| printf %s "unmap buffer normal <ret> :git-diff-goto-source<ret>")
printf %s "evaluate-commands -try-client '$kak_opt_docsclient' %{ printf %s "evaluate-commands -try-client '$kak_opt_docsclient' %{
edit! -fifo ${output} *git* edit! -fifo ${output} *git*
set-option buffer filetype '${filetype}' set-option buffer filetype '${filetype}'
hook -always -once buffer BufCloseFifo .* %{ nop %sh{ rm -r $(dirname ${output}) } } hook -always -once buffer BufCloseFifo .* %{ nop %sh{ rm -r $(dirname ${output}) } }
${map_diff_goto_source}
}" }"
} }