Passing large diff buffers via the environment can quickly result in
the error "execve failed: Argument list too long". Use a pipe like
in format.kak
When running | (or <a-|>), Kakoune does not use %arg{@} to populate
"$@" (missing feature?). Work around this by moving %arg{@} to a
temporary register. Apparently $kak_quoted_reg_a will never be an
empty list, so work around that too.
When diff parsing fails, we take care to run "fail" in the calling
client, unlike :format (probably a bug in format.kak).
(This patch is best viewed while ignoring whitespace changes (diff -w))
Mapping in the filetype hook matches others like grep.kak and man.kak.
Since we map in buffer scope, git diff buffers will override diff-jump
with git-diff-goto-source.
This means that the diff-jump binding applies here:
diff -u "$1" "$2" | kak -e 'set buffer filetype diff'
Reported in: https://github.com/mawww/kakoune/issues/153#issuecomment-1030643854
I dedicate any and all copyright interest in this software to the
public domain. I make this dedication for the benefit of the public at
large and to the detriment of my heirs and successors. I intend this
dedication to be an overt act of relinquishment in perpetuity of all
present and future rights to this software under copyright law.
Given a completer option with two applicable completions
text|select-cmd1|menu-text1
text|select-cmd2|menu-text2
Kakoune will only show one of them, because they will insert the
same text.
Some language servers send completions like this, for example if
two different importable modules provide the same name. This can be
reproduced using intelephense in this PHP file (cursor is %())
<?php
namespace namespace1;
class sometype {}
?>
<?php
namespace namespace2;
class sometype {}
?>
<?php
namespace test;
some%()
?>
Both completions insert "sometype". The import statement will be
added in an InsertCompletionHide hook by kak-lsp (it uses select-cmd
to determine which completion was selected).
To support this use case, refine the duplicate detection to not filter
out completions with different select-cmd values.
Parsing a (non-valid) font with a comma in the name of the base colour
makes Kakoune crash. It is not a valid face, but Kakoune should just
return an error message instead.
Reproducer:
:set-face global foo ,red@,blue
Note the comma "," after the "@". This is not a valid base name, and it
leads to a crash. Let's see what happens.
At the beginning of parse_face(), we have the following code:
auto bg_it = find(facedesc, ',');
auto underline_it = bg_it == facedesc.end() ? bg_it : std::find(bg_it+1, facedesc.end(), ',');
auto attr_it = find(facedesc, '+');
auto base_it = find(facedesc, '@');
[...]
auto colors_end = std::min(attr_it, base_it);
After this:
- bg_it points to ",red@,blue"
- bg_it != facedesc.end(), so we have underline_it pointing to the first
comma after bg_it. This means that underline_it points to ",blue"
- base_it points to "@,blue"
- attr_it points to the end of facedesc (no "+" marker), so colors_end
points to base_it, "@,blue"
Later in the code, just after parsing the foreground and background
colours, we have:
if (underline_it != facedesc.end())
face.underline = parse_color({underline_it+1, colors_end});
When passing {underline_it+1, colors_end} to parse_color(), we pass in
fact iterators pointing to {",blue", "@,blue"}. Because the second one
starts _before_ the first one in the string, this means that the
resulting string is considered to have a _negative_ length.
parse_color() passes the string to str_to_color(), who fails to turn up
the colour, and attempts to throw:
throw runtime_error(format("unable to parse color: '{}'", color));
The variable "color" still has this negative length, and this goes all
the way down to an assert in src/units.hh where we expect that string to
be >= 0, and we crash on the assertion failure.
For similar reasons, we also get a crash if the comma comes after the
marker for the face attributes:
:set-face global foo ,red+,a
To fix both cases, let's add a check to make sure that the underline_it,
marked with a comma, never gets detected as present and pointing after
colors_end, be it "@" or "+".
As pointed out in [1], when insert mode autocomplete is disabled,
<c-n> could be used to activate insert mode completions temporarily
[2]. This regressed in 6f7c5aed (Do not show custom completions when
autocomplete is off, 2022-01-03). Fix this by enabling completions
on <c-n>/<c-p>. This allows us to remove a special case for explicit
completers.
Alternative behavior (future?): make <c-n> toggle completion like
<c-o>. This can be done today, as suggested by Screwtape on IRC:
map global insert <c-n> %{<c-o><c-n><a-;>:toggle-ctrl-n<ret>}
define-command toggle-ctrl-n %{
hook global InsertCompletionShow .* %{ map window insert <c-n> <c-n> }
hook global InsertCompletionHide .* %{ unmap window insert <c-n> <c-n> }
}
[1] https://github.com/mawww/kakoune/pull/4493#issuecomment-1031189823
[2] <c-n> completion only lives for the lifetime of the completion
menu, whereas <c-o> lasts until you exit insert mode. This means
that autocompletion is much more convenient than <c-n> or <c-x>f,
because those require an explicit completion request for each
path component.
The ThreadedRegexVM implementation does not execute split opcodes as
expected: on split the pending thread is pushed on top of the thread
stack, which means that when multiple splits are executed in a row
(such as with a disjunction with 3 or more branches) the last split
target gets on top of the thread stack and gets executed next (when the
thread from the first split target would be the expected one)
Fixing this in the ThreadedRegexVM would have a performance impact as
we would not be able to use a plain stack for current threads, so the
best solution at the moment is to reverse the order of splits generated
by a disjunction.
Fixes#4519
A recent commit wrapped diff.kak into a module. The module includes the
hook that adds diff highlighting to filetype=diff buffers. This means
that the hook is only loaded after opening the first diff buffer in a
Kakoune session, so it only actually fires for the second diff buffer.
Fix this by moving the hook out of the module.
Fixes#4525
I dedicate any and all copyright interest in this software to the
public domain. I make this dedication for the benefit of the public at
large and to the detriment of my heirs and successors. I intend this
dedication to be an overt act of relinquishment in perpetuity of all
present and future rights to this software under copyright law.
The wrapper for "git blame" creates flags for each line of the buffer.
It parses the output from git and would send a flag (or a series of
flags) each time the commit to blame for a line differs from the
previous one. For files that were touched by a large number of commits,
this results in a high number of kakoune processes being launched, and
may take some time. This is visible in the session through the flags for
the different commits appearing on the lines one by one, possibly during
several seconds.
To speed up the process, batch flags before passing them to the kak
session. One solution could be to send all flags at once, but this might
delay the appearance of commit info for too long if "git blame" really
takes a long time. The alternative solution retained for this commit
consists in grouping as many flags as we can during one second
(roughly), to pass them to kakoune, and then to move on to the next
flags. This way, a new batch of commit information flags appears every
second or so in the client, until all information is added. This should
be much faster than lauching a kakoune process for each commit
reported by "git blame": tests have shown that blaming a large file in
the Linux repository goes 4.5 times faster when batching flags.
Co-authored-by: Johannes Altmanninger <aclopte@gmail.com>