Highlight cursors differently when they lie on an end of line

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.
This commit is contained in:
Maxime Coste 2018-02-24 21:24:06 +11:00
parent a0de41d165
commit 6a6e71dc0f
5 changed files with 21 additions and 8 deletions

View File

@ -31,6 +31,8 @@ face PrimarySelection white,blue
face SecondarySelection black,blue face SecondarySelection black,blue
face PrimaryCursor black,white face PrimaryCursor black,white
face SecondaryCursor black,white face SecondaryCursor black,white
face PrimaryCursorEol black,cyan
face SecondaryCursorEol black,cyan
face LineNumbers default,default face LineNumbers default,default
face LineNumberCursor default,default+r face LineNumberCursor default,default+r
face MenuForeground white,blue face MenuForeground white,blue

View File

@ -57,6 +57,12 @@ areas of the user interface:
*SecondaryCursor*:: *SecondaryCursor*::
cursor of the secondary selection cursor of the secondary selection
*PrimaryCursorEol*::
cursor of the primary selection when it lies on and end of line character
*SecondaryCursorEol*::
cursor of the secondary selection when it lies on and end of line character
*LineNumbers*:: *LineNumbers*::
face used by the number_lines highlighter face used by the number_lines highlighter

View File

@ -133,6 +133,8 @@ FaceRegistry::FaceRegistry()
{ "SecondarySelection", {Face{ Color::Black, Color::Blue }} }, { "SecondarySelection", {Face{ Color::Black, Color::Blue }} },
{ "PrimaryCursor", {Face{ Color::Black, Color::White }} }, { "PrimaryCursor", {Face{ Color::Black, Color::White }} },
{ "SecondaryCursor", {Face{ Color::Black, Color::White }} }, { "SecondaryCursor", {Face{ Color::Black, Color::White }} },
{ "PrimaryCursorEol", {Face{ Color::Black, Color::Cyan }} },
{ "SecondaryCursorEol", {Face{ Color::Black, Color::Cyan }} },
{ "LineNumbers", {Face{ Color::Default, Color::Default }} }, { "LineNumbers", {Face{ Color::Default, Color::Default }} },
{ "LineNumberCursor", {Face{ Color::Default, Color::Default, Attribute::Reverse }} }, { "LineNumberCursor", {Face{ Color::Default, Color::Default, Attribute::Reverse }} },
{ "LineNumbersWrapped", {Face{ Color::Default, Color::Default, Attribute::Italic }} }, { "LineNumbersWrapped", {Face{ Color::Default, Color::Default, Attribute::Italic }} },

View File

@ -1163,10 +1163,11 @@ HighlighterAndId create_matching_char_highlighter(HighlighterParameters params)
void highlight_selections(HighlightContext context, DisplayBuffer& display_buffer, BufferRange) void highlight_selections(HighlightContext context, DisplayBuffer& display_buffer, BufferRange)
{ {
const auto& buffer = context.context.buffer(); const auto& buffer = context.context.buffer();
const Face primary_face = get_face("PrimarySelection"); const Face faces[6] = {
const Face secondary_face = get_face("SecondarySelection"); get_face("PrimarySelection"), get_face("SecondarySelection"),
const Face primary_cursor_face = get_face("PrimaryCursor"); get_face("PrimaryCursor"), get_face("SecondaryCursor"),
const Face secondary_cursor_face = get_face("SecondaryCursor"); get_face("PrimaryCursorEol"), get_face("SecondaryCursorEol"),
};
const auto& selections = context.context.selections(); const auto& selections = context.context.selections();
for (size_t i = 0; i < selections.size(); ++i) for (size_t i = 0; i < selections.size(); ++i)
@ -1178,14 +1179,16 @@ void highlight_selections(HighlightContext context, DisplayBuffer& display_buffe
const bool primary = (i == selections.main_index()); const bool primary = (i == selections.main_index());
highlight_range(display_buffer, begin, end, false, highlight_range(display_buffer, begin, end, false,
apply_face(primary ? primary_face : secondary_face)); apply_face(faces[primary ? 0 : 1]));
} }
for (size_t i = 0; i < selections.size(); ++i) for (size_t i = 0; i < selections.size(); ++i)
{ {
auto& sel = selections[i]; auto& sel = selections[i];
const BufferCoord coord = sel.cursor();
const bool primary = (i == selections.main_index()); const bool primary = (i == selections.main_index());
highlight_range(display_buffer, sel.cursor(), buffer.char_next(sel.cursor()), false, const bool eol = buffer[coord.line].length() - 1 == coord.column;
apply_face(primary ? primary_cursor_face : secondary_cursor_face)); highlight_range(display_buffer, coord, buffer.char_next(coord), false,
apply_face(faces[2 + (eol ? 2 : 0) + (primary ? 0 : 1)]));
} }
} }

View File

@ -1,4 +1,4 @@
{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "·" }, { "face": { "fg": "black", "bg": "white", "attributes": [] }, "contents": "¬" }], [{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "¬" }]], { "fg": "default", "bg": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "attributes": [] }] } { "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "·" }, { "face": { "fg": "black", "bg": "cyan", "attributes": [] }, "contents": "¬" }], [{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "¬" }]], { "fg": "default", "bg": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "attributes": [] }] }
{ "jsonrpc": "2.0", "method": "menu_hide", "params": [] } { "jsonrpc": "2.0", "method": "menu_hide", "params": [] }
{ "jsonrpc": "2.0", "method": "info_hide", "params": [] } { "jsonrpc": "2.0", "method": "info_hide", "params": [] }
{ "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "out 1:2 " }, { "face": { "fg": "black", "bg": "yellow", "attributes": [] }, "contents": "[+]" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "yellow", "bg": "default", "attributes": [] }, "contents": "insert" }, { "face": { "fg": "cyan", "bg": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "attributes": [] }, "contents": "1 sels (1)" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " - unnamed0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "attributes": [] }] } { "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": "out 1:2 " }, { "face": { "fg": "black", "bg": "yellow", "attributes": [] }, "contents": "[+]" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "yellow", "bg": "default", "attributes": [] }, "contents": "insert" }, { "face": { "fg": "cyan", "bg": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "attributes": [] }, "contents": "1 sels (1)" }, { "face": { "fg": "default", "bg": "default", "attributes": [] }, "contents": " - unnamed0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "attributes": [] }] }