summaryrefslogtreecommitdiff
path: root/rc/tools/git.kak
AgeCommit message (Collapse)Author
2025-05-11Revert "rc git: clarify reason for NormalIdle hook"Johannes Altmanninger
Commit eee362087 (Improve info box clearing behaviour, 2025-03-22) was merged shortly before commit 1c50bcd89 (rc git: clarify reason for NormalIdle hook, 2025-03-24). The first commit broke the second in the sense that "git blame-jump" no longer displays a message in the status line (with commit date/author/subject). I haven't had time to debug this yet. Revert the part of this cleanup commit that was broken.
2025-03-25rc git: fix blame/blame-jump/apply on files with eolformat=crlfJohannes Altmanninger
<a-|> produces \n line endings, which confuses Git when the tracked file uses \r\n line endings. Work around that.
2025-03-25rc git: clarify reason for NormalIdle hookJohannes Altmanninger
When blame and blame-jump invoke "git show" they set a BufCloseFifo hook to display a statusline message and center the viewport. As mentioned in the previous patch (which fixed a copy-paste error), the statusline message does not need a NormalIdle hook. Move it to prevent such errors.
2025-03-25rc git: display error from git blame immediatelyJohannes Altmanninger
When "git blame" fails, it prints an error message to the status line via a NormalIdle hook. But the hook is only necessary for "execute-keys vv". (as a workaround for https://github.com/mawww/kakoune/issues/5082). Since we run "git blame" in the background, it will not trigger a NormalIdle hook when finished. This means that the "failed to run git blame" message will only be shown after the next key press. This problem can be reproduced by first adding a sleep here: diff --git a/rc/tools/git.kak b/rc/tools/git.kak index 05e6ff144..bd899365f 100644 --- a/rc/tools/git.kak +++ b/rc/tools/git.kak @@ -301,4 +301,5 @@ define-command -params 1.. \ echo 'echo -markup {Information}Press <ret> to jump to blamed commit' ( + sleep .1 trap - INT QUIT if [ -z "${kak_opt_git_blob}" ]; then and then running ':git blame' in a file that is not Git-tracked. Reduce the scope of the hook to show this error message immediately.
2025-03-24rc git: fail blame-jump explicitly when there is no clientJohannes Altmanninger
My kak -e 'hook global WinCreate /.* %{ git blame-jump }; edit README.asciidoc' hangs until I cancel it with <c-c>. The error is error while waiting for shell: 1:1: 'evaluate-commands': 3:21: 'execute-keys': no such client: '-draft' git blame-jump cannot do anything useful without a client in context, so fail early and explicitly.
2025-03-24rc git: throw an error when diffutils is not installedJohannes Altmanninger
Some of our git wrappers use the diff utility; if it's not installed we'll hang because no one is opening the fifo for reading. For example, this happens when running chmod -x $(which diff) && kak -e "edit README.asciidoc; git apply" Fail earlier, I guess -- although it's probably fine as-is.
2025-03-24rc git: blame to not hide error when cd_bufdir failsJohannes Altmanninger
Running "git blame" in a scratch buffer echoes "Press <ret> to jump to blamed commit" even though the blaming clearly fails. The failure is silent because cd_bufdir exits the shell, so we don't even attempt to run "git blame". cd_bufdir prints a "fail" command stdout but that goes to /dev/null in this case. I don't really understand why 891a9f5fe (Merge remote-tracking branch 'lenormf/fix-git-tools', 2019-09-22) moved cd_bufdir inside this background subshell. I guess it didn't matter as much back then when we didn't have the "Press <ret> to jump" message. Also the existing error message printed by cd_bufdir for scratch buffers is confusing. Fail as early as possible, showing a suitable error. Note that "git blame" does work in filetype=git-diff and filetype=git-log buffers, so don't attempt cd_bufdir inside those.
2025-03-24rc git: fix blaming when in subdirectoryJohannes Altmanninger
When $PWD is different from $(git rev-parse --show-toplevel, recursive blaming is broken. For example (assuming k moves to a delted line): kak -e 'cd src; edit main.cc; git blame-jump; hook -once g NormalIdle .* %{ exec k; git blame-jump }' Fix this by 1. computing the correct path from diff-parse (we already require the git command be run in a git directory). 2. passing absolute paths to the recursive "git blame" invocations
2025-02-18rc git: Use wider characters for added/modified linesShawn Wallace
2025-02-18rc git: fix blame in diff of deleted/renamed filesJohannes Altmanninger
The code paths around "Missing commit line, assume it is an uncommitted change" in both blame and blame-jump code look suspiciously similar. It's possible that we can extract at least something, but there is a fundamental difference: blame-jump only jumps to another diff, while blame jumps from diff to blob, which may be a good reason for keeping them separate. More specifically, blame-jump passes « $version = "-" » because it's only interested in the parent commit/file/line, whereas blame wants to default to using the child commit/file/line (for added and context lines) and only uses the parent commit/file/line when run on deleted lines or on uncommitted changes (where HEAD is assumed to be parent commit even if there is no child). Unfortunately the blame path forgot to change to use the parent file for these; fix that and get rid of some code duplication.
2025-02-18rc git: remove dead codeJohannes Altmanninger
This branch is always taken since we check $diff_line_text above.
2025-02-18rc git: remove else after returnJohannes Altmanninger
2025-02-10Format blamed commit timestamps using the original time zoneJohannes Altmanninger
Surprisingly, these two commands show different commit times: git blame README.asciidoc kak -e 'git blame' README.asciidoc This is because git shows times as of the original time zone (of the author/committer). Our blame integration uses the current local time. - blame-jump displays the date in the status line of a git-show buffer This date may be inconsistent with the buffer's "Date:" header, so this seems surprising. Fix that. This fixes a test in some time zones. - Unlike "git blame", our ":git blame" does not display time zone info by default. So, the conversion to localtime might make sense. I don't really have an opinion on this. Change it too I guess, since the current behavior might not have been intended. Fixes #5285
2024-09-18rc git: don't require client in git show-diffJohannes Altmanninger
This fails because the new logic wrongly assumes the presence of a client: hook global WinCreate /.* 'git show-diff' The "diff" process hangs because we never write to ${kak_response_fifo}. After a "pkill diff", the *debug* buffer shows error while waiting for shell: 1:1: 'evaluate-commands': 3:13: 'execute-keys': no such client: '-draft' shell stderr: <<< The client argument is completely unnecessary since we always want to use the calling context's buffer anyway. Remove it. Note that we can probably further simplify this by using "write" instead of a shell process. I'll send that patch along a few other error handling improvements later. Closes #5235
2024-09-18rc git: fix show-diff and apply for BSD sedJohannes Altmanninger
2024-09-16Fix "git blame" inside "git blame-jump" diff buffersJohannes Altmanninger
I used to use a patch that removes cd_bufdir so I didn't notice this being broken for *git* buffers.
2024-09-16rc git: teach "git apply" to work on content, not just diffsJohannes Altmanninger
Staging/unstaging/reverting (parts of) the current buffer's file can be a common use case. Today "git apply" can do that based on a selection within a diff. When the selection is on uncommitted content, we can probably assume that the intent is to use the part of the selection that overlaps with the +-side of "git diff" (or "git diff --cached" for "git apply --cached"). Make "git apply" treat selections as content if the buffile is tracked by Git. This differentiator is not perfect but I don't know why anyone would want to use the existing "git apply" semantics on a tracked file. Maybe we should pick a different name. This feature couples well with "git show-diff", which shows all lines with unstaged changes (in future it should probably show staged changes as well). Whereas on diffs, "git apply" stages the entire hunk if the selection contains no newline, this does not happen when operating on content. I didn't yet try implementing that. I guess the hunks are not as explicit here. Closes #5225
2024-09-16diff-parse.pl: don't force error message into registerJohannes Altmanninger
A following patch wants to use this script without wrapping it in an "evaluate-commands -save-regs e %{ ... }", so simply print the raw error message and set the register to the caller. This interface is a bit weird because the error is printed quoted but for now that just makes things a bit more convenient.
2024-09-16rc git: show-diff to honor unsaved buffer modificationsJohannes Altmanninger
If a file has unsaved modifications, then the show-diff flags below such modifications will be wrong. Fix this by using the current buffer contents, just like the git blame integration does. This might make it a bit slower, I haven't tested that.
2024-09-16rc git: rationalize blame fifo usageJohannes Altmanninger
We call git blame a. asynchronously in ":git blame" b. synchronously in ":git blame-jump" In both cases we 1. create a fifo 2. buffer the file contents in shell memory 3. print to the fifo 4. run git blame and remove the fifo For the synchronous case the buffering and custom fifo is not necessary; use ${kak_response_fifo} instead. For the asynchronous case we do need a buffer that outlives the enclosing %sh{} block. Buffering in shell memory can be somewhat slow for large files. Let's use a temporary file instead.
2024-09-16rc git: simplify git diff invocationJohannes Altmanninger
If stdout is not a TTY, Git never calls a pager, so this is unnecessary.
2024-05-29Merge remote-tracking branch 'QiBaobin/git-completer'Maxime Coste
2024-05-12Fix another case where git tests were hangingMaxime Coste
2024-04-24add `add` to the git completerBob Qi
2024-04-12Make removing an unknown highlighter an errorMaxime Coste
Fail instead of silently doing nothing, this makes it easier to toggle highlighters using a try/catch
2024-03-31Reset SIGINT handler in background processesJohannes Altmanninger
In a noninteractive shell, asynchronous commands ignore SIGINT and SIGQUIT. We typically use such shells to feed fifo buffers which we do want to cancel them on Control-C. Make it so. Same for SIGQUIT; that one is not typically used but I expect that along the Kakoune server it kills any child processes that (haven't been daemonized). Note that for unknown reasons, Bash already doesn't ignore SIGINT in async processes that use "eval". Note that Dash has a bug that prevents this from working; proposed fix is at https://lore.kernel.org/dash/20240329153905.154792-2-aclopte@gmail.com/ (While at it balance out some parens, to help the m command)
2024-02-26rc git: hide blame and report error if git blame failsJohannes Altmanninger
Similar to the previous patch, when git blame fails it usually means that the blamed file is not tracked by Git. I don't know of other common failure scenarios. Since git blame runs in detached process, failure handling is a bit more involved. Let's forward stderr to the debug buffer and escalate the error. I'm not sure how to get the exit code from git blame in "git blame | perl" - we can't use $PIPESTATUS. As a workaround, interpret empty output as failure. In case of failure, also hide blame; this makes the UI more consistent I think.
2024-02-26rc git: report error if blame-jump failsJohannes Altmanninger
git blame typically fails when the buffile is not tracked by Git. Let's escalate the failure early instead of continuing witout blame data, only to eventually hit the generic "git blame-jump: missing blame info" error.
2024-02-26rc git: support uncommitted lines in git blame tooJohannes Altmanninger
I frequently run ":git diff" followed by ":git blame-jump" to find the commit that added the lines I deleted. I wasn't sure whether ":git blame" should allow this use case too. I think it should, I don't think this is too confusing.
2024-02-26rc git: fix off-by-one in git blame cursor targetJohannes Altmanninger
I personally mostly use "git blame-jump" so this "git blame" bug has flown under the radar. When we run git blame in a git-diff buffer, we want to move one column to the left since the lines in the target blob don't have the +- prefix. We already subtract one but we add it back accidentally when using "l" to go to this column. Fix it. In future we should try to preserve more of the selection(s), not just the main cursor.
2024-02-18rc tools git: fix initial position of blame of deleted lineJohannes Altmanninger
When running git blame in a "git show" buffer, we annotate the youngest version of the file that has the line referenced by the diff line at cursor. In case the cursor is on an added or context line, we simply show the version from the surrounding commit. When the cursor is on a deleted line, we show the parent commit, which still has the deleted line. However there is a bug: we use the line number in the new version of the file. Fix that.
2024-02-13rc git.kak: fix blame-jump for commits with special charactersJohannes Altmanninger
Commit 53d9b9b67 (Escaping tweak in git.kak, 2024-02-06) broke blame-jump when the commit subject contains a single quote. (Also on unbalanced "{" which is a rare edge case but we already have it in our Git history.) git.kak assumes that filenames don't contain ' or unbalanced {, but we can't really make that assumption about people's names or commit subjects. Unfortunately the escaping here is very messy. We need to pass arbitrary text to callbacks; maybe we should have closures that can capture private temporary registers.
2024-02-12rc tools git: quote $kak_buffile for add/rmJohannes Altmanninger
Our "git add" and "git rm" default to the current file. The shell interprets globs in the filename, which can lead to surprising results, for example if it's accidentally used on a scratch buffer like *git*.
2024-02-06Escaping tweak in git.kakMaxime Coste
2024-02-05rc tools git: blame-jump to handle buffer modifications since blameJohannes Altmanninger
If I run git blame execute-keys 10o<esc>,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
2024-02-05rc tools git: support blame in git-diff and git-log buffersJohannes Altmanninger
Today we can recursively search history with "git blame-jump". However that command has some drawbacks, mainly that it's blocking. Making it async without any progress indicator might be confusing. Better to run plain "git blame"[1] and press Enter. Also it might be nice to enable recursive searches using only "git blame" and `<ret>` (since that is bound to "git blame-jump" while blame annotations are displayed). Make "git blame" in git-diff/git-log buffers run "git show $commit:$file" for the commit and file at cursor, and decorate this blob view with blame annotations. The latter allows to use `<ret>` and repeat. Unfortunately this relies on a hidden option "git_blob" to keep the commit ID and filename. Maybe we can put this metadata somewhere else like the buffer name or contents, ideally in a way that survives serialization. I'd still keep "git blame-jump" because it seems faster for the common case of tracking down a single line. [1]: In my testing, "git blame --incremental" is not any slower than "git blame -L123,123" at finding that line.
2024-02-05rc tools git: while blame annotations are shown, map <ret> to "git blame-jump"Johannes Altmanninger
Running git blame signals intent to view the blamed commit. Let's make `<ret>` to go to that commit+line as long as blame info is shown. In diff buffers we already use `<ret>` for "diff-jump". Like blame annotations, the blame-jump mapping lives in window scope. This means it will not collide with "diff-jump" which is mapped in buffer scope. Add the mapping synchronously (unlike the rest of the git-blame code) to perhaps allow the user to override the mapping: git blame; map window normal <ret> ...
2024-02-05rc tools git: command for easy recursive blamingJohannes Altmanninger
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).
2024-02-05rc tools git: detect filetype=git-diff for untracked diff buffersJohannes Altmanninger
On untracked diff buffers, it might be useful to make the upcoming blame features work. This is experimental, I might drop it.
2024-02-05rc tools git: change git diff filetype from diff to git-diffJohannes Altmanninger
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
2024-02-05rc tools git: remove unused dependency on diff from status/show-branchJohannes Altmanninger
2024-02-05rc tools git: blame buffer contents, not on-disk fileJohannes Altmanninger
When a buffer has unsaved deleted/added lines, then any blame annotations below those lines may be off. Fix this by feeding the latest buffer contents to Git. Unfortunately there is no easy way to distinguish between "Unsaved" and "Saved but not committed yet" so let's keep using the umbrella term.
2024-01-26rc tools git: suggest -3/--3way argument to git applyJohannes Altmanninger
Sometimes a patch that fails to apply will apply cleanly after adding -3. Also sometimes we do want to apply with conflict markers. So this is another somewhat common option.
2024-01-23rc tools git: fix regression hiding blame in large filesJohannes Altmanninger
Sorry I did not test my earlier patch in production. It passes blame flags via the environment. On a 5000 line file this results in "execve failed: Argument list too long" errors. Use a different way of checking whether blame info is shown.
2024-01-21rc tools git: blame to hide blame if already shownJohannes Altmanninger
This simplifies the UI (no need to add multiple mappings) and might obsolete hide-blame.
2024-01-21rc tools git: remove redundant tryJohannes Altmanninger
These commands must never fail.
2024-01-07rc tools git: fix off-by-one regression in git blame SHA columnJohannes Altmanninger
Introduced in f27f6fa2d (rc git: fix "git blame" on macOS with perl rewrite, 2023-11-12); awk uses 1-based indices but perl uses offsets.
2023-12-02ranked match: prefer input order over alphabetical order for user-specified ↵Johannes Altmanninger
completions When using either of set-option g completers option=my_option prompt -shell-script-candidates ... While the search text is empty, the completions will be sorted alphabetically. This is bad because it means the most important entries are not listed first, making them harder to select or even spot. Let's apply input order before resorting to sorting alphabetically. In theory there is a more elegant solution: sort candidates (except if they're user input) before passing them to RankedMatch, and then always use stable sort. However that doesn't work because we use a heap which doesn't support stable sort. Closes #1709, #4813
2023-11-12rc git: fix "git blame" on macOS with perl rewriteJohannes Altmanninger
macOS awk doesn't have strftime().
2023-11-05Merge remote-tracking branch 'stacyharper/git-log-ret'Maxime Coste