mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #17187 from lewis6991/master
feat(highlight): ns=0 to set :highlight namespace
This commit is contained in:
commit
5be2cdd913
@ -32,6 +32,7 @@
|
||||
#include "nvim/fileio.h"
|
||||
#include "nvim/getchar.h"
|
||||
#include "nvim/highlight.h"
|
||||
#include "nvim/highlight_defs.h"
|
||||
#include "nvim/lua/executor.h"
|
||||
#include "nvim/mark.h"
|
||||
#include "nvim/memline.h"
|
||||
@ -122,7 +123,9 @@ Dictionary nvim__get_hl_defs(Integer ns_id, Error *err)
|
||||
|
||||
/// Set a highlight group.
|
||||
///
|
||||
/// @param ns_id number of namespace for this highlight
|
||||
/// @param ns_id number of namespace for this highlight. Use value 0
|
||||
/// to set a highlight group in the global (`:highlight`)
|
||||
/// namespace.
|
||||
/// @param name highlight group name, like ErrorMsg
|
||||
/// @param val highlight definition map, like |nvim_get_hl_by_name|.
|
||||
/// in addition the following keys are also recognized:
|
||||
@ -136,18 +139,23 @@ Dictionary nvim__get_hl_defs(Integer ns_id, Error *err)
|
||||
/// same as attributes of gui color
|
||||
/// @param[out] err Error details, if any
|
||||
///
|
||||
/// TODO: ns_id = 0, should modify :highlight namespace
|
||||
/// TODO val should take update vs reset flag
|
||||
// TODO(bfredl): val should take update vs reset flag
|
||||
void nvim_set_hl(Integer ns_id, String name, Dictionary val, Error *err)
|
||||
FUNC_API_SINCE(7)
|
||||
{
|
||||
int hl_id = syn_check_group(name.data, (int)name.size);
|
||||
int link_id = -1;
|
||||
|
||||
HlAttrs attrs = dict2hlattrs(val, true, &link_id, err);
|
||||
if (!ERROR_SET(err)) {
|
||||
ns_hl_def((NS)ns_id, hl_id, attrs, link_id);
|
||||
HlAttrNames *names = NULL; // Only used when setting global namespace
|
||||
if (ns_id == 0) {
|
||||
names = xmalloc(sizeof(*names));
|
||||
*names = HLATTRNAMES_INIT;
|
||||
}
|
||||
HlAttrs attrs = dict2hlattrs(val, true, &link_id, names, err);
|
||||
if (!ERROR_SET(err)) {
|
||||
ns_hl_def((NS)ns_id, hl_id, attrs, link_id, names);
|
||||
}
|
||||
xfree(names);
|
||||
}
|
||||
|
||||
/// Set active namespace for highlights.
|
||||
|
@ -144,13 +144,19 @@ int hl_get_syn_attr(int ns_id, int idx, HlAttrs at_en)
|
||||
}
|
||||
}
|
||||
|
||||
void ns_hl_def(NS ns_id, int hl_id, HlAttrs attrs, int link_id)
|
||||
void ns_hl_def(NS ns_id, int hl_id, HlAttrs attrs, int link_id, HlAttrNames *names)
|
||||
{
|
||||
DecorProvider *p = get_decor_provider(ns_id, true);
|
||||
if ((attrs.rgb_ae_attr & HL_DEFAULT)
|
||||
&& map_has(ColorKey, ColorItem)(&ns_hl, ColorKey(ns_id, hl_id))) {
|
||||
return;
|
||||
}
|
||||
if (ns_id == 0) {
|
||||
assert(names);
|
||||
// set in global (':highlight') namespace
|
||||
set_hl_group(hl_id, attrs, names, link_id);
|
||||
return;
|
||||
}
|
||||
DecorProvider *p = get_decor_provider(ns_id, true);
|
||||
int attr_id = link_id > 0 ? -1 : hl_get_syn_attr(ns_id, hl_id, attrs);
|
||||
ColorItem it = { .attr_id = attr_id,
|
||||
.link_id = link_id,
|
||||
@ -194,7 +200,7 @@ int ns_get_hl(NS ns_id, int hl_id, bool link, bool nodefault)
|
||||
if (ret.type == kObjectTypeDictionary) {
|
||||
Dictionary dict = ret.data.dictionary;
|
||||
fallback = false;
|
||||
attrs = dict2hlattrs(dict, true, &it.link_id, &err);
|
||||
attrs = dict2hlattrs(dict, true, &it.link_id, NULL, &err);
|
||||
for (size_t i = 0; i < dict.size; i++) {
|
||||
char *key = dict.items[i].key.data;
|
||||
Object val = dict.items[i].value;
|
||||
@ -796,7 +802,7 @@ Dictionary hlattrs2dict(HlAttrs ae, bool use_rgb)
|
||||
return hl;
|
||||
}
|
||||
|
||||
HlAttrs dict2hlattrs(Dictionary dict, bool use_rgb, int *link_id, Error *err)
|
||||
HlAttrs dict2hlattrs(Dictionary dict, bool use_rgb, int *link_id, HlAttrNames *names, Error *err)
|
||||
{
|
||||
HlAttrs hlattrs = HLATTRS_INIT;
|
||||
|
||||
@ -820,7 +826,7 @@ HlAttrs dict2hlattrs(Dictionary dict, bool use_rgb, int *link_id, Error *err)
|
||||
{ "italic", HL_ITALIC },
|
||||
{ "reverse", HL_INVERSE },
|
||||
{ "default", HL_DEFAULT },
|
||||
{ "global", HL_GLOBAL },
|
||||
// { "global", HL_GLOBAL },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
@ -857,13 +863,14 @@ HlAttrs dict2hlattrs(Dictionary dict, bool use_rgb, int *link_id, Error *err)
|
||||
const char *name;
|
||||
const char *shortname;
|
||||
int *dest;
|
||||
char **dest_name;
|
||||
} colors[] = {
|
||||
{ "foreground", "fg", &fg },
|
||||
{ "background", "bg", &bg },
|
||||
{ "ctermfg", NULL, &ctermfg },
|
||||
{ "ctermbg", NULL, &ctermbg },
|
||||
{ "special", "sp", &sp },
|
||||
{ NULL, NULL, NULL },
|
||||
{ "foreground", "fg", &fg, names ? &names->fg_name : NULL },
|
||||
{ "background", "bg", &bg, names ? &names->bg_name : NULL },
|
||||
{ "ctermfg", NULL, &ctermfg, NULL },
|
||||
{ "ctermbg", NULL, &ctermbg, NULL },
|
||||
{ "special", "sp", &sp, names ? &names->sp_name : NULL },
|
||||
{ NULL, NULL, NULL, NULL },
|
||||
};
|
||||
|
||||
int k;
|
||||
@ -876,6 +883,9 @@ HlAttrs dict2hlattrs(Dictionary dict, bool use_rgb, int *link_id, Error *err)
|
||||
// TODO(bfredl): be more fancy with "bg", "fg" etc
|
||||
if (str.size) {
|
||||
*colors[k].dest = name_to_color(str.data);
|
||||
if (colors[k].dest_name) {
|
||||
*colors[k].dest_name = str.data;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
|
@ -46,6 +46,18 @@ typedef struct attr_entry {
|
||||
.hl_blend = -1, \
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char *bg_name;
|
||||
char *fg_name;
|
||||
char *sp_name;
|
||||
} HlAttrNames;
|
||||
|
||||
#define HLATTRNAMES_INIT (HlAttrNames) { \
|
||||
.bg_name = NULL, \
|
||||
.fg_name = NULL, \
|
||||
.sp_name = NULL, \
|
||||
}
|
||||
|
||||
/// Values for index in highlight_attr[].
|
||||
/// When making changes, also update hlf_names below!
|
||||
typedef enum {
|
||||
|
@ -6714,6 +6714,90 @@ int lookup_color(const int idx, const bool foreground, TriState *const boldp)
|
||||
return color;
|
||||
}
|
||||
|
||||
void set_hl_group(int id, HlAttrs attrs, HlAttrNames *names, int link_id)
|
||||
{
|
||||
int idx = id - 1; // Index is ID minus one.
|
||||
|
||||
bool is_default = attrs.rgb_ae_attr & HL_DEFAULT;
|
||||
|
||||
// Return if "default" was used and the group already has settings
|
||||
if (is_default && hl_has_settings(idx, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
HlGroup *g = &HL_TABLE()[idx];
|
||||
|
||||
if (link_id > 0) {
|
||||
g->sg_cleared = false;
|
||||
g->sg_link = link_id;
|
||||
g->sg_script_ctx = current_sctx;
|
||||
g->sg_script_ctx.sc_lnum += sourcing_lnum;
|
||||
g->sg_set |= SG_LINK;
|
||||
if (is_default) {
|
||||
g->sg_deflink = link_id;
|
||||
g->sg_deflink_sctx = current_sctx;
|
||||
g->sg_deflink_sctx.sc_lnum += sourcing_lnum;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
g->sg_cleared = false;
|
||||
g->sg_link = 0;
|
||||
g->sg_gui = attrs.rgb_ae_attr;
|
||||
|
||||
g->sg_rgb_fg = attrs.rgb_fg_color;
|
||||
g->sg_rgb_bg = attrs.rgb_bg_color;
|
||||
g->sg_rgb_sp = attrs.rgb_sp_color;
|
||||
|
||||
struct {
|
||||
char **dest; RgbValue val; char *name;
|
||||
} cattrs[] = {
|
||||
{ &g->sg_rgb_fg_name, g->sg_rgb_fg, names->fg_name },
|
||||
{ &g->sg_rgb_bg_name, g->sg_rgb_bg, names->bg_name },
|
||||
{ &g->sg_rgb_sp_name, g->sg_rgb_sp, names->sp_name },
|
||||
{ NULL, -1, NULL },
|
||||
};
|
||||
|
||||
for (int j = 0; cattrs[j].dest; j++) {
|
||||
if (cattrs[j].val != -1) {
|
||||
xfree(*cattrs[j].dest);
|
||||
if (cattrs[j].name) {
|
||||
*cattrs[j].dest = xstrdup(cattrs[j].name);
|
||||
} else {
|
||||
char hex_name[8];
|
||||
snprintf(hex_name, sizeof(hex_name), "#%06x", cattrs[j].val);
|
||||
*cattrs[j].dest = xstrdup(hex_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g->sg_cterm = attrs.cterm_ae_attr;
|
||||
g->sg_cterm_bg = attrs.cterm_bg_color;
|
||||
g->sg_cterm_fg = attrs.cterm_fg_color;
|
||||
g->sg_cterm_bold = g->sg_cterm & HL_BOLD;
|
||||
g->sg_blend = attrs.hl_blend;
|
||||
|
||||
g->sg_script_ctx = current_sctx;
|
||||
g->sg_script_ctx.sc_lnum += sourcing_lnum;
|
||||
|
||||
// 'Normal' is special
|
||||
if (STRCMP(g->sg_name_u, "NORMAL") == 0) {
|
||||
cterm_normal_fg_color = g->sg_cterm_fg;
|
||||
cterm_normal_bg_color = g->sg_cterm_bg;
|
||||
normal_fg = g->sg_rgb_fg;
|
||||
normal_bg = g->sg_rgb_bg;
|
||||
normal_sp = g->sg_rgb_sp;
|
||||
ui_default_colors_set();
|
||||
} else {
|
||||
g->sg_attr = hl_get_syn_attr(0, id, attrs);
|
||||
|
||||
// a cursor style uses this syn_id, make sure its attribute is updated.
|
||||
if (cursor_mode_uses_syn_id(id)) {
|
||||
ui_mode_info_set();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Handle ":highlight" command
|
||||
///
|
||||
|
@ -3,6 +3,7 @@ local clear, nvim = helpers.clear, helpers.nvim
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
local eq, eval = helpers.eq, helpers.eval
|
||||
local command = helpers.command
|
||||
local exec_capture = helpers.exec_capture
|
||||
local meths = helpers.meths
|
||||
local funcs = helpers.funcs
|
||||
local pcall_err = helpers.pcall_err
|
||||
@ -252,4 +253,23 @@ describe("API: set highlight", function()
|
||||
eq(highlight3_result_gui, meths.get_hl_by_name('Test_hl', true))
|
||||
eq(highlight3_result_cterm, meths.get_hl_by_name('Test_hl', false))
|
||||
end)
|
||||
|
||||
it ("can set a highlight in the global namespace", function()
|
||||
meths.set_hl(0, 'Test_hl', highlight2_config)
|
||||
eq('Test_hl xxx cterm=underline,reverse ctermfg=8 ctermbg=15 gui=underline,reverse',
|
||||
exec_capture('highlight Test_hl'))
|
||||
|
||||
meths.set_hl(0, 'Test_hl', { background = highlight_color.bg })
|
||||
eq('Test_hl xxx guibg=#0032aa',
|
||||
exec_capture('highlight Test_hl'))
|
||||
|
||||
meths.set_hl(0, 'Test_hl2', highlight3_config)
|
||||
eq('Test_hl2 xxx cterm=undercurl,italic,reverse ctermfg=8 ctermbg=15 gui=bold,underline,undercurl,italic,reverse guifg=#ff0000 guibg=#0032aa',
|
||||
exec_capture('highlight Test_hl2'))
|
||||
|
||||
-- Colors are stored exactly as they are defined.
|
||||
meths.set_hl(0, 'Test_hl3', { bg = 'reD', fg = 'bLue'})
|
||||
eq('Test_hl3 xxx guifg=bLue guibg=reD',
|
||||
exec_capture('highlight Test_hl3'))
|
||||
end)
|
||||
end)
|
||||
|
Loading…
Reference in New Issue
Block a user