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 "+".
kak-lsp uses these faces to mark errors inside the buffer, instead of the Error
face which is much more jarring, and which does not have an associated warning
face. Since the :spell command marks errors inside the buffer, it's also updated
to use this new face.
Adding these faces to Kakoune makes it more likely that colorschemes will
automatically do the right thing when used with kak-lsp, and makes it possible
to use a subtle appearance (like curly underlines) for in-buffer errors while
keeping Kakoune errors bold and jarring as they should be.
Add support for a third color in face definition that controls
the underline and a 'c' attribute for curly underline (that takes
precedence over 'u' if both are specified)
Allow empty colors to mean default, so that `,,red+u` means the
same as `default,default,red+u`
Fixes#4138
Using <fg>,<bg>+<attr>@<base> will apply the given fg color,
bg color and attributes on top of base dynamically. Simply giving
<base> is a shorthand for default,default@<base>.
Inspired by the discussion in #2862
Final is more granular, it consists of FinalFg (f), FinalBg (g)
and FinalAttr (a) which control if a face's fg, bg, or attributes
fully overwrite the previous face (instead of merging) and if
following faces apply on top of this face or not.
Fixes#2388 if the Whitespace face has the FinalFg flag.
set-face now takes a scope argument, and faces can be overridden on
a buffer or window basis.
colorscheme apply on global scope, which should be good enough for
now.
Fixes#1411
When on an end of line, certain behaviours can be surprising, for
example delete will join the following line (which makes sense, and
is consistent, but hard to predict if we do not know the cursor is
on and end of line).
As Kakoune is moving more and more towards treating end of lines
as any other character, making it clear when the cursor lies on
them seems like a good way to reduce surprise.
The author of this work hereby waives all claim of copyright (economic and moral) in this work and immediately places it in the public domain; it may be used, distorted or destroyed in any manner whatsoever without further attribution or notice to the creator