-
-
Notifications
You must be signed in to change notification settings - Fork 6.3k
[WIP] support transparent & ctermbg cursor + minimal highlight api #6566
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
src/nvim/tui/tui.c
Outdated
|
||
if (ui->rgb) { | ||
|
||
RgbValue bg = aep->rgb_bg_color; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this more succinct using a ternary?
// if gui=reverse, swap bg and fg colors
RgbValue bg = aep->rgb_ae_attr == HL_INVERSE ? aep->rgb_fg_color : aep->rgb_bg_color;
Just a random thought..might not be worth changing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes a line 80 chars wide line so it ends up not being clearer
src/nvim/tui/tui.c
Outdated
const char *val) | ||
{ | ||
if (!unibi_get_str(ut, str)) { | ||
const char *temp = unibi_get_str(ut, str); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why use temp here? Can't one just:
if (!unibi_get_str(ut, str)) {
unibi_set_str(ut, str, val);
return true;
}
return false;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leftover of a debug session. Removed the temp variable. Kept returning the bool as it helps debug and should be optimized out by compiler anyway.
src/nvim/tui/tui.c
Outdated
RgbValue bg = aep->rgb_bg_color; | ||
|
||
// if gui=reverse, swap bg and fg colors | ||
if (aep->rgb_ae_attr == HL_INVERSE) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should it be aep->rgb_ae_attr & HL_INVERSE
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
In #6425 (comment) @zhou13 mentioned control sequence |
@zhou13 I can't find out what I don't get why I have this error: terminal tests look ok for the rest :/
Thus I checked out terminals (I don't use the feature) and saw that in both master and this PR I get some (red) artifacts: |
tested in xfce4-terminal. |
What terminal? I didn't see that on iTerm. Is the test failing consistently? |
Stupid me, it's just a plugin showing space at end of line. Thought it was linked to guicursor because I used to test with a red cursor. The tests pass on master, but fail consistently for this PR (on travis too). Seems like |
It's an Operating System Command (OSC). They're of the form Any terminal supporting these should respond to the PR. xterm does, if
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
supporting the "gui=inverse" thing seems hard so I dropped it.
I haven't tested this much but cursor color seems to follow ctermbg with set notermguicolors.
It is possible to hide cursor with guibg=None.
guicursor is resent for each highlight_changed(). Less then optimal but cursor is updated properly.
The easiest way to deal with guicursor would be to send the full mode description on mode change (=stateless) but it was suggested that as this information doesn't change often, it can be stateful. Hence it is sent via mode_info_set. Sending guicursor colors in mode_change seems like a bad compromise between the 2 as cursor highlights shouldn't change much either.
UIs will need to retrieve highlights in all cases (because externalized components will need to match vim colors), so I believe letting the UIs subscribe to chosen highlight changes (such as the cursor's highlights) would be the best approach ? .
Meanwhile as a quickfix, I sent cursor colors along with guicursor info.
If this is blocking for 0.2 feel free to take over as I am not sure when I can complete this.
src/nvim/api/private/helpers.c
Outdated
} else { | ||
attrs.background = aep->cterm_bg_color - 1; | ||
} | ||
ILOG("attr=%d color to %d", attr_code, attrs.background); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
todo remove
} | ||
|
||
return NULL; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't this function along with cterm_color_name and color_numbers_X live in one of the terminal libraries ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not that I know of.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not know the scope of libtermkey or unibilium but this part should apply to all terminals so it might make sense to have it there.
typedef struct attr_entry { | ||
int16_t rgb_ae_attr, cterm_ae_attr; // HL_BOLD, etc. | ||
int16_t rgb_ae_attr, cterm_ae_attr; ///< \ref HL_ATTRIBUTES | ||
RgbValue rgb_fg_color, rgb_bg_color, rgb_sp_color; | ||
int cterm_fg_color, cterm_bg_color; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the hl_group retains the original cterm values, cterm_Xg_color could now be RgbValues too ?!
src/nvim/tui/tui.c
Outdated
@@ -91,13 +91,14 @@ typedef struct { | |||
int enable_mouse, disable_mouse; | |||
int enable_bracketed_paste, disable_bracketed_paste; | |||
int set_rgb_foreground, set_rgb_background; | |||
int set_cursor_color; | |||
int set_cursor_bg_color; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
renamed for clarity as some terms (iTerm?) seem to have a set_cursor_fg_color
src/nvim/tui/tui.c
Outdated
@@ -482,6 +500,9 @@ static cursorentry_T decode_cursor_entry(Dictionary args) | |||
r.blinkoff = (int)value.data.integer; | |||
} else if (strequal(key, "hl_id")) { | |||
r.id = (int)value.data.integer; | |||
} else if (strequal(key, "hl_dict")) { | |||
r.attrs = decode_hl_entry(value.data.dictionary); | |||
ILOG("decoded hl_dict with bg=%d", r.attrs.background); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove
src/nvim/tui/tui.c
Outdated
if (cursor_bg == -1) { | ||
unibi_out(ui, unibi_cursor_invisible); | ||
} else { | ||
unibi_out(ui, unibi_cursor_normal); // display if previously invisible |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this call could be prevented with an additionnal check if we save the visibility status. worth it ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It only happens on mode-change, so it's ok. Incidentally we do unibi_cursor_normal quite often, it's part of UI "flush".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact this call may not be needed at all, the next UI flush will show the cursor again.
src/nvim/ui.c
Outdated
api_free_array(style); | ||
UI_CALL(mode_info_set, enabled, mode_style_array(ui->rgb)); | ||
// todo | ||
// api_free_array(style); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with the new style I can't free the array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why?
"Cyan", "LightCyan", "Red", "LightRed", "Magenta", | ||
"LightMagenta", "Yellow", "LightYellow", "White", "NONE" | ||
}; | ||
// terminals with less than 16 colors... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't care about them for 'guicursor' purposes. (Oh, I see you factored this out of do_highlight()
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mhinz asked to be able to change cursor via setting ctermbg. ctermbg=ColorName is straightforward but ctermbg=4
needed a function to convert the integer to the colorname.
src/nvim/tui/tui.c
Outdated
@@ -1060,7 +1093,7 @@ static void flush_buf(UI *ui, bool toggle_cursor) | |||
uv_buf_t buf; | |||
TUIData *data = ui->data; | |||
|
|||
if (toggle_cursor && !data->busy) { | |||
if (toggle_cursor && !data->busy && cursor_bg != -1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be better to communicate this via the existing toggle_cursor
. The only call that needs modification is the one in tui_flush
.
src/nvim/tui/tui.c
Outdated
ut, NULL, "\033]Pl%p1%06x\033\\"); | ||
} else { | ||
data->unibi_ext.set_cursor_color = (int)unibi_add_ext_str( | ||
// new form rgb:X/X/X does not seem to work so well |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
outdated comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's up to date but might be more relevant in the git log. rgb:X/X/X is supposed to work (see xparsecolor) but there are different forms such as rgb:XXX/XXX/XXX, rgb:XX/XX/XX and not all had an effect in termite. I would have to ask on vte tracker.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
vte is supposed to convert the rgb:rrr/ggg/bbb
(independent of the arity of each color) to the #rrrgggbbb
form and then pass that on to pango_color_parse
.
Older versions of vte used gdk_parse_color
instead, but either one should handle the format fine.
If you're seeing different behavior, then I'd either guess it's an old version of vte or the terminal using vte is doing something wrong.
Current code might be hard to follow as there is some dead code (I stopped implementing some functionality as it seemed overkill). A few interrogations:
|
transparent cursor works in termite. cursor color can also now be set via ctermbg + notermguicolors. I've added tests for the highlight api (nvim_hl_*). Also nvim -u NORC -c ":hi Normal" now works as it should. |
src/nvim/api/vim.c
Outdated
/// | ||
/// @param highlights a list of highlights id (string or integer) to look for | ||
/// todo return array instead ? ArrayOf(HlAttrs) | ||
Object nvim_hl_get_list(Array highlights, Error *err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if this is a batched version of the methods above then it is not needed (use call_atomic or lua)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok done
src/nvim/tui/tui.c
Outdated
@@ -805,6 +841,16 @@ static void tui_set_icon(UI *ui, String icon) | |||
// to make a copy for the tui thread | |||
static void tui_event(UI *ui, char *name, Array args, bool *args_consumed) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this shouldn't be used. In fact ui_event impl should be just deleted from ui_bridge and tui. (the infrastructure checks for funptr being NULL, so this is safe). Instead, mark events as not REMOTE_ONLY to have them acessible from TUI.
src/nvim/syntax.c
Outdated
for (int i = 1; i <= highlight_ga.ga_len && !got_int; ++i) | ||
/* TODO: only call when the group has attributes set */ | ||
for (int i = 0; i < highlight_ga.ga_len && !got_int; i++) { | ||
// todo: only call when the group has attributes set |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO(vim):
src/nvim/syntax.c
Outdated
|
||
static bool did_syntax_onoff = false; | ||
static int invalid_group_id = -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be either a constant named kFoo
or a define named FOO
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I renamed it to kInvalidGroupId.
src/nvim/syntax.c
Outdated
/* | ||
* Translate a group ID to the final group ID (following links). | ||
*/ | ||
bool hl_invalid_id(int hl_id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FUNC_ATTR_PURE. can it also be static?
same for hl_is_valid()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added the FUNC_ATTR_PURE. I renamed hl_is_valid to hl_valid_id. I think it makes sense to keep one function available (either hl_invalid_id or hl_valid_id) for other units for instance it is used in tui.c. I can inline or remove the 2nd one.
src/nvim/api/ui_events.in.h
Outdated
@@ -58,6 +58,8 @@ void set_title(String title) | |||
FUNC_API_SINCE(3); | |||
void set_icon(String icon) | |||
FUNC_API_SINCE(3); | |||
void highlights_changed(Array highlights_changed) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The naming precedent is "set", we don't have "changed" (though we do have "change"... oh dear). We already have highlight_set
, which is a UI change, whereas this new event is a property change.
Kind of a mess. Naming this highlight_info_set
at least is analogous to mode_info_set
. We can use "info" as the pattern for "property changes".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed "set" is better. The UI event stream tells the current state, not whether something changed or not
@teto No objection to 1/, but 2/ sounds like the UI is making decisions to work around TUI limits. In general I suggest: give UIs all relevant info and let the UIs make the decisions. If TUI sees that guifg=bg it can decide to hide the cursor. It does that by inspecting |
I think it is better to encode explicitly that the cursor should be hidden, one would expect this to happen consistently in both TUI and GUI, for instance by using -2 like option 1. |
I went with option 1 as it was just a few lines of code. Setting guibg=NONE now translates to -2 in the datastructure instead of -1. The PR now seems to behave as intended. I'll clean up a bit, try to split it into 2 PRs as the changes to hl group index is not related and might be seen as potentially harmful. |
for the cursor | ||
for the cursor. If an invalid group is set, the TUI won't change colors | ||
contrary to vim. If the group has guibg=NONE then the cursor becomes | ||
invisible. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did you mean UI instead of TUI? (We can't control what GUIs do, but we can add to the guidelines at :help dev-ui
which should be considered the "official UI behavior").
Can elide "contrary to vim". (mention it at vim_diff.txt if you want to call out contrary-to-vim things)
src/nvim/tui/tui.c
Outdated
@@ -474,7 +474,7 @@ CursorShape tui_cursor_decode_shape(const char *shape_str) | |||
// if the cursor should be visible according to guicursor | |||
static bool cursor_visible(void) | |||
{ | |||
return cursor_bg != -1; | |||
return cursor_bg != -2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kColorFoo ?
@@ -142,6 +142,104 @@ void ui_event(char *name, Array args) | |||
} | |||
} | |||
|
|||
bool attr2hlattr(int attr_code, bool use_rgb, HlAttrs *out) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, I should have clarified. These functions should live in syntax.c (wasn't that where they originally were?)
} | ||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is rather pointless, since nothing uses the return value; and for what it's worth I have something in the works that I hope will do away with quite a number of calls to this function.
Guys, so cool that you are working on this, thanks a lot! |
Trying to write some tests to check for certain sequences such as
Any precise test in mind ? I've been lookling at job_spec.lua and do sthg like:
my trouble is that the on_stdout seems to be called many times, not sure against which line to check or how many times I should call next_msg (if incorrect, it leaves the test pending). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am a bit at a loss as how to use jobsend to send input to a background nvim.
I would like for instance to insert "toto" and then go back to normal mode.
So I send jobsend(j, "itoto\<c-c>:q!")
but the on_stdout callback isn't called for "toto", just for <c-c>:q!
.
then I try sthg like jobsend(j, "itoto\<c-r>\<c-l>:q!")
and it gives me 2 lines of output or is it the same line redrawn ? why the \13 ?
{
"notification",
"onout",
{
{
"itoto^R\13",
"itoto^L:q!"
}
}
}
This is still WIP but to see the behavior, one can run
LANG=C TEST_FILE=test/functional/terminal/tui_spec.lua make functionaltest 2>&1 >log && nvim log
local pattern = shape_ver_noblink.."(.*)toto" | ||
-- :append (line("."), "zaza") | ||
-- :append (line(\".\"), \"zaza\") | ||
gen('n-v-c-sm:block,i-ci-ve:ver25,r-cr-o:hor20', [[itoto\e:q!]], pattern) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here
@@ -704,12 +756,21 @@ void nvim_unsubscribe(uint64_t channel_id, String event) | |||
channel_unsubscribe(channel_id, e); | |||
} | |||
|
|||
/// Translate to integer if \p name is an hex value (e.g. #XXXXXX), | |||
/// else look into \p color_name_table to translate a color name to its |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
color_name_table sounds like an internal datastructure. Also the descriptions of nvim_get_color_map
sounds like they use two different color tables.
@@ -5,7 +5,7 @@ msgid "" | |||
msgstr "" | |||
"Project-Id-Version: Vim 7.1\n" | |||
"Report-Msgid-Bugs-To: \n" | |||
"POT-Creation-Date: 2014-07-02 21:54+0200\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Normally we don't update po files in unrelated PRs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mistake on my side.
Is this still being worked on @teto? I'm interested in If this PR is not active anymore, maybe it's possible to pick out some of the features and implement them separately? I'd be happy to help getting the VTE cursor reset working. |
@chrisduerr I promised some users to get the transparent cursor working but the lack of dynamic update when changing highlights was a pain so I wanted to solve it first in #8006. For many reasons, I can't work on neovim at the moment so please go ahead. I would |
Thanks for the quick response. I'm not sure if I can get to it this weekend, but I'll definitely look into it when I've got some time and this PR is still open. :) |
The PR is likely to stick for a few more months/years xD feel free to ask if you have any question. |
this is very old and almost everything has been implemented apart from the transparent TUI cursor. see #11519 for that |
See #3688 and #6428 .
printf "\x1b[0 q"
)As for setting cursor foreground color, VTE api allows it (termite has a cursor_foreground parameter for instance) but there is no OSC yet. https://bugzilla.gnome.org/show_bug.cgi?id=695011 proposes OSC20 for that but rxvt has a pre-existing use of OSC 20 (for background pixmap). Thomas Dickey (xterm maintainer) seems ok with a patch that would set cursor foreground color, so anyone feel free to propose such a patch.