Merge branch 'master' of github.com:ckelsel/neovim into vim-8.0.0101

This commit is contained in:
ckelsel
2017-10-09 21:17:15 +08:00
38 changed files with 723 additions and 326 deletions

View File

@@ -242,39 +242,7 @@ static void push_call(UI *ui, char *name, Array args)
static void remote_ui_highlight_set(UI *ui, HlAttrs attrs)
{
Array args = ARRAY_DICT_INIT;
Dictionary hl = ARRAY_DICT_INIT;
if (attrs.bold) {
PUT(hl, "bold", BOOLEAN_OBJ(true));
}
if (attrs.underline) {
PUT(hl, "underline", BOOLEAN_OBJ(true));
}
if (attrs.undercurl) {
PUT(hl, "undercurl", BOOLEAN_OBJ(true));
}
if (attrs.italic) {
PUT(hl, "italic", BOOLEAN_OBJ(true));
}
if (attrs.reverse) {
PUT(hl, "reverse", BOOLEAN_OBJ(true));
}
if (attrs.foreground != -1) {
PUT(hl, "foreground", INTEGER_OBJ(attrs.foreground));
}
if (attrs.background != -1) {
PUT(hl, "background", INTEGER_OBJ(attrs.background));
}
if (attrs.special != -1) {
PUT(hl, "special", INTEGER_OBJ(attrs.special));
}
Dictionary hl = hlattrs2dict(attrs);
ADD(args, DICTIONARY_OBJ(hl));
push_call(ui, "highlight_set", args);

View File

@@ -55,6 +55,47 @@ void nvim_command(String command, Error *err)
try_end(err);
}
/// Gets a highlight definition by name.
///
/// @param name Highlight group name
/// @param rgb Export RGB colors
/// @param[out] err Error details, if any
/// @return Highlight definition map
/// @see nvim_get_hl_by_id
Dictionary nvim_get_hl_by_name(String name, Boolean rgb, Error *err)
FUNC_API_SINCE(3)
{
Dictionary result = ARRAY_DICT_INIT;
int id = syn_name2id((const char_u *)name.data);
if (id == 0) {
api_set_error(err, kErrorTypeException, "Invalid highlight name: %s",
name.data);
return result;
}
result = nvim_get_hl_by_id(id, rgb, err);
return result;
}
/// Gets a highlight definition by id. |hlID()|
///
/// @param hl_id Highlight id as returned by |hlID()|
/// @param rgb Export RGB colors
/// @param[out] err Error details, if any
/// @return Highlight definition map
/// @see nvim_get_hl_by_name
Dictionary nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Error *err)
FUNC_API_SINCE(3)
{
Dictionary dic = ARRAY_DICT_INIT;
if (syn_get_final_id((int)hl_id) == 0) {
api_set_error(err, kErrorTypeException, "Invalid highlight id: %d", hl_id);
return dic;
}
int attrcode = syn_id2attr((int)hl_id);
return hl_get_attr_by_id(attrcode, rgb, err);
}
/// Passes input keys to Nvim.
/// On VimL error: Does not fail, but updates v:errmsg.
///

View File

@@ -3069,8 +3069,8 @@ static bool ti_change(char_u *str, char_u **last)
/// Set current window title
void resettitle(void)
{
ui_call_set_title(cstr_as_string((char *)lasttitle));
ui_call_set_icon(cstr_as_string((char *)lasticon));
ui_call_set_title(cstr_as_string((char *)lasttitle));
ui_flush();
}

View File

@@ -762,7 +762,7 @@ bool vim_isIDc(int c)
}
/// Check that "c" is a keyword character:
/// Letters and characters from 'iskeyword' option for current buffer.
/// Letters and characters from 'iskeyword' option for the current buffer.
/// For multi-byte characters mb_get_class() is used (builtin rules).
///
/// @param c character to check

View File

@@ -6733,6 +6733,39 @@ static void prepare_assert_error(garray_T *gap)
}
}
// Append "str" to "gap", escaping unprintable characters.
// Changes NL to \n, CR to \r, etc.
static void ga_concat_esc(garray_T *gap, char_u *str)
{
char_u *p;
char_u buf[NUMBUFLEN];
if (str == NULL) {
ga_concat(gap, (char_u *)"NULL");
return;
}
for (p = str; *p != NUL; p++) {
switch (*p) {
case BS: ga_concat(gap, (char_u *)"\\b"); break;
case ESC: ga_concat(gap, (char_u *)"\\e"); break;
case FF: ga_concat(gap, (char_u *)"\\f"); break;
case NL: ga_concat(gap, (char_u *)"\\n"); break;
case TAB: ga_concat(gap, (char_u *)"\\t"); break;
case CAR: ga_concat(gap, (char_u *)"\\r"); break;
case '\\': ga_concat(gap, (char_u *)"\\\\"); break;
default:
if (*p < ' ') {
vim_snprintf((char *)buf, NUMBUFLEN, "\\x%02x", *p);
ga_concat(gap, buf);
} else {
ga_append(gap, *p);
}
break;
}
}
}
// Fill "gap" with information about an assert error.
static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv,
char_u *exp_str, typval_T *exp_tv,
@@ -6753,11 +6786,11 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv,
ga_concat(gap, (char_u *)"Expected ");
}
if (exp_str == NULL) {
tofree = (char_u *) encode_tv2string(exp_tv, NULL);
ga_concat(gap, tofree);
tofree = (char_u *)encode_tv2string(exp_tv, NULL);
ga_concat_esc(gap, tofree);
xfree(tofree);
} else {
ga_concat(gap, exp_str);
ga_concat_esc(gap, exp_str);
}
if (atype != ASSERT_NOTEQUAL) {
if (atype == ASSERT_MATCH) {
@@ -6768,7 +6801,7 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv,
ga_concat(gap, (char_u *)" but got ");
}
tofree = (char_u *)encode_tv2string(got_tv, NULL);
ga_concat(gap, tofree);
ga_concat_esc(gap, tofree);
xfree(tofree);
}
}
@@ -17495,7 +17528,7 @@ static void f_winsaveview(typval_T *argvars, typval_T *rettv, FunPtr fptr)
tv_dict_add_nr(dict, S_LEN("skipcol"), (varnumber_T)curwin->w_skipcol);
}
/// Writes list of strings to file
/// Write "list" of strings to file "fd".
///
/// @param fp File to write to.
/// @param[in] list List to write.

View File

@@ -868,20 +868,15 @@ int ins_typebuf(char_u *str, int noremap, int offset, int nottyped, bool silent)
addlen = (int)STRLEN(str);
/*
* Easy case: there is room in front of typebuf.tb_buf[typebuf.tb_off]
*/
if (offset == 0 && addlen <= typebuf.tb_off) {
// Easy case: there is room in front of typebuf.tb_buf[typebuf.tb_off]
typebuf.tb_off -= addlen;
memmove(typebuf.tb_buf + typebuf.tb_off, str, (size_t)addlen);
}
/*
* Need to allocate a new buffer.
* In typebuf.tb_buf there must always be room for 3 * MAXMAPLEN + 4
* characters. We add some extra room to avoid having to allocate too
* often.
*/
else {
} else {
// Need to allocate a new buffer.
// In typebuf.tb_buf there must always be room for 3 * MAXMAPLEN + 4
// characters. We add some extra room to avoid having to allocate too
// often.
newoff = MAXMAPLEN + 4;
newlen = typebuf.tb_len + addlen + newoff + 4 * (MAXMAPLEN + 4);
if (newlen < 0) { /* string is getting too long */
@@ -1663,10 +1658,10 @@ static int vgetorpeek(int advance)
}
if (c != NUL && !got_int) {
if (advance) {
/* KeyTyped = FALSE; When the command that stuffed something
* was typed, behave like the stuffed command was typed.
* needed for CTRL-W CTRl-] to open a fold, for example. */
KeyStuffed = TRUE;
// KeyTyped = FALSE; When the command that stuffed something
// was typed, behave like the stuffed command was typed.
// needed for CTRL-W CTRL-] to open a fold, for example.
KeyStuffed = true;
}
if (typebuf.tb_no_abbr_cnt == 0)
typebuf.tb_no_abbr_cnt = 1; /* no abbreviations now */

View File

@@ -13,6 +13,7 @@
#else
# define _(x) ((char *)(x))
# define N_(x) x
# define ngettext(x, xs, n) ((n) == 1 ? (x) : (xs))
# define bindtextdomain(x, y) // empty
# define bind_textdomain_codeset(x, y) // empty
# define textdomain(x) // empty

View File

@@ -734,16 +734,20 @@ static int cin_ispreproc(char_u *s)
return FALSE;
}
/*
* Return TRUE if line "*pp" at "*lnump" is a preprocessor statement or a
* continuation line of a preprocessor statement. Decrease "*lnump" to the
* start and return the line in "*pp".
*/
static int cin_ispreproc_cont(char_u **pp, linenr_T *lnump)
/// Return TRUE if line "*pp" at "*lnump" is a preprocessor statement or a
/// continuation line of a preprocessor statement. Decrease "*lnump" to the
/// start and return the line in "*pp".
/// Put the amount of indent in "*amount".
static int cin_ispreproc_cont(char_u **pp, linenr_T *lnump, int *amount)
{
char_u *line = *pp;
linenr_T lnum = *lnump;
int retval = FALSE;
int retval = false;
int candidate_amount = *amount;
if (*line != NUL && line[STRLEN(line) - 1] == '\\') {
candidate_amount = get_indent_lnum(lnum);
}
for (;; ) {
if (cin_ispreproc(line)) {
@@ -758,8 +762,12 @@ static int cin_ispreproc_cont(char_u **pp, linenr_T *lnump)
break;
}
if (lnum != *lnump)
if (lnum != *lnump) {
*pp = ml_get(*lnump);
}
if (retval) {
*amount = candidate_amount;
}
return retval;
}
@@ -1994,10 +2002,12 @@ int get_c_indent(void)
amount = -1;
for (lnum = cur_curpos.lnum - 1; lnum > our_paren_pos.lnum; --lnum) {
l = skipwhite(ml_get(lnum));
if (cin_nocode(l)) /* skip comment lines */
if (cin_nocode(l)) { // skip comment lines
continue;
if (cin_ispreproc_cont(&l, &lnum))
continue; /* ignore #define, #if, etc. */
}
if (cin_ispreproc_cont(&l, &lnum, &amount)) {
continue; // ignore #define, #if, etc.
}
curwin->w_cursor.lnum = lnum;
/* Skip a comment or raw string. XXX */
@@ -2353,15 +2363,14 @@ int get_c_indent(void)
* up with it.
*/
if (curwin->w_cursor.lnum <= ourscope) {
/* we reached end of scope:
* if looking for an enum or structure initialization
* go further back:
* if it is an initializer (enum xxx or xxx =), then
* don't add ind_continuation, otherwise it is a variable
* declaration:
* int x,
* here; <-- add ind_continuation
*/
// We reached end of scope:
// If looking for a enum or structure initialization
// go further back:
// If it is an initializer (enum xxx or xxx =), then
// don't add ind_continuation, otherwise it is a variable
// declaration:
// int x,
// here; <-- add ind_continuation
if (lookfor == LOOKFOR_ENUM_OR_INIT) {
if (curwin->w_cursor.lnum == 0
|| curwin->w_cursor.lnum
@@ -2389,11 +2398,12 @@ int get_c_indent(void)
continue;
}
/*
* Skip preprocessor directives and blank lines.
*/
if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum))
//
// Skip preprocessor directives and blank lines.
//
if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum, &amount)) {
continue;
}
if (cin_nocode(l))
continue;
@@ -2497,9 +2507,10 @@ int get_c_indent(void)
continue;
}
/* Skip preprocessor directives and blank lines. */
if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum))
// Skip preprocessor directives and blank lines.
if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum, &amount)) {
continue;
}
/* Finally the actual check for "namespace". */
if (cin_is_cpp_namespace(l)) {
@@ -2662,9 +2673,10 @@ int get_c_indent(void)
* unlocked it)
*/
l = get_cursor_line_ptr();
if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum)
|| cin_nocode(l))
if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum, &amount)
|| cin_nocode(l)) {
continue;
}
/*
* Are we at the start of a cpp base class declaration or
@@ -3309,11 +3321,12 @@ term_again:
break;
}
/*
* Skip preprocessor directives and blank lines.
*/
if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum))
//
// Skip preprocessor directives and blank lines.
//
if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum, &amount)) {
continue;
}
if (cin_nocode(l))
continue;
@@ -3405,9 +3418,10 @@ term_again:
while (curwin->w_cursor.lnum > 1) {
look = ml_get(--curwin->w_cursor.lnum);
if (!(cin_nocode(look) || cin_ispreproc_cont(
&look, &curwin->w_cursor.lnum)))
if (!(cin_nocode(look)
|| cin_ispreproc_cont(&look, &curwin->w_cursor.lnum, &amount))) {
break;
}
}
if (curwin->w_cursor.lnum > 0
&& cin_ends_in(look, (char_u *)"}", NULL))

View File

@@ -649,6 +649,11 @@ void getout(int exitval)
/* Position the cursor again, the autocommands may have moved it */
ui_cursor_goto((int)Rows - 1, 0);
// Apply 'titleold'.
if (p_title && *p_titleold != NUL) {
ui_call_set_title(cstr_as_string((char *)p_titleold));
}
#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
iconv_end();
#endif

View File

@@ -2456,8 +2456,8 @@ did_set_string_option (
&& (options[opt_idx].flags & P_SECURE)) {
errmsg = e_secure;
} else if (((options[opt_idx].flags & P_NFNAME)
&& vim_strpbrk(*varp, (char_u *)(secure
? "/\\*?[|;&<>\r\n" : "/\\*?[<>\r\n")) != NULL)
&& vim_strpbrk(*varp, (char_u *)(secure ? "/\\*?[|;&<>\r\n"
: "/\\*?[<>\r\n")) != NULL)
|| ((options[opt_idx].flags & P_NDNAME)
&& vim_strpbrk(*varp, (char_u *)"*?[|;&<>\r\n") != NULL)) {
// Check for a "normal" directory or file name in some options. Disallow a

View File

@@ -2501,7 +2501,7 @@ return {
no_mkrc=true,
vi_def=true,
varname='p_titleold',
defaults={if_true={vi=N_("Thanks for flying Vim")}}
defaults={if_true={vi=N_("")}}
},
{
full_name='titlestring',

View File

@@ -1690,6 +1690,9 @@ int vim_FullName(const char *fname, char *buf, size_t len, bool force)
if (strlen(fname) > (len - 1)) {
xstrlcpy(buf, fname, len); // truncate
#ifdef WIN32
slash_adjust(buf);
#endif
return FAIL;
}
@@ -1702,6 +1705,9 @@ int vim_FullName(const char *fname, char *buf, size_t len, bool force)
if (rv == FAIL) {
xstrlcpy(buf, fname, len); // something failed; use the filename
}
#ifdef WIN32
slash_adjust(buf);
#endif
return rv;
}
@@ -2196,11 +2202,11 @@ static int path_get_absolute_path(const char_u *fname, char_u *buf,
// expand it if forced or not an absolute path
if (force || !path_is_absolute_path(fname)) {
if ((p = vim_strrchr(fname, '/')) != NULL) {
if ((p = vim_strrchr(fname, PATHSEP)) != NULL) {
// relative to root
if (p == fname) {
// only one path component
relative_directory[0] = '/';
relative_directory[0] = PATHSEP;
relative_directory[1] = NUL;
} else {
assert(p >= fname);

View File

@@ -2201,16 +2201,17 @@ win_line (
int change_end = -1; /* last col of changed area */
colnr_T trailcol = MAXCOL; /* start of trailing spaces */
int need_showbreak = false; // overlong line, skip first x chars
int line_attr = 0; /* attribute for the whole line */
matchitem_T *cur; /* points to the match list */
match_T *shl; /* points to search_hl or a match */
int shl_flag; /* flag to indicate whether search_hl
has been processed or not */
int prevcol_hl_flag; /* flag to indicate whether prevcol
equals startcol of search_hl or one
of the matches */
int prev_c = 0; /* previous Arabic character */
int prev_c1 = 0; /* first composing char for prev_c */
int line_attr = 0; // attribute for the whole line
int line_attr_low_priority = 0; // current line, lowest priority
matchitem_T *cur; // points to the match list
match_T *shl; // points to search_hl or a match
int shl_flag; // flag to indicate whether search_hl
// has been processed or not
int prevcol_hl_flag; // flag to indicate whether prevcol
// equals startcol of search_hl or one
// of the matches
int prev_c = 0; // previous Arabic character
int prev_c1 = 0; // first composing char for prev_c
int did_line_attr = 0;
bool search_attr_from_match = false; // if search_attr is from :match
@@ -2427,10 +2428,17 @@ win_line (
filler_lines = wp->w_topfill;
filler_todo = filler_lines;
/* If this line has a sign with line highlighting set line_attr. */
// 'cursorline' highlighting for the current window. Not when Visual mode is
// active, because it's not clear what is selected then.
if (wp->w_p_cul && lnum == wp->w_cursor.lnum
&& !(wp == curwin && VIsual_active)) {
line_attr_low_priority = win_hl_attr(wp, HLF_CUL);
}
v = buf_getsigntype(wp->w_buffer, lnum, SIGN_LINEHL);
if (v != 0)
line_attr = sign_get_attr((int)v, TRUE);
if (v != 0) {
line_attr = sign_get_attr((int)v, true);
}
// Highlight the current line in the quickfix window.
if (bt_quickfix(wp->w_buffer) && qf_current_entry(wp) == lnum) {
@@ -2441,7 +2449,7 @@ win_line (
line_attr = hl_combine_attr(wp->w_hl_attr_normal, line_attr);
}
if (line_attr != 0) {
if (line_attr_low_priority || line_attr) {
area_highlighting = true;
}
@@ -2663,20 +2671,6 @@ win_line (
cur = cur->next;
}
/* Cursor line highlighting for 'cursorline' in the current window. Not
* when Visual mode is active, because it's not clear what is selected
* then. */
if (wp->w_p_cul && lnum == wp->w_cursor.lnum
&& !(wp == curwin && VIsual_active)) {
if (line_attr != 0 && !(State & INSERT) && bt_quickfix(wp->w_buffer)
&& qf_current_entry(wp) == lnum) {
line_attr = hl_combine_attr(win_hl_attr(wp, HLF_CUL), line_attr);
} else {
line_attr = win_hl_attr(wp, HLF_CUL);
}
area_highlighting = true;
}
off = (unsigned)(current_ScreenLine - ScreenLines);
col = 0;
if (wp->w_p_rl) {
@@ -3594,15 +3588,15 @@ win_line (
&& lcs_eol_one > 0) {
// Display a '$' after the line or highlight an extra
// character if the line break is included.
// For a diff line the highlighting continues after the
// "$".
if (diff_hlf == (hlf_T)0 && line_attr == 0) {
/* In virtualedit, visual selections may extend
* beyond end of line. */
// For a diff line the highlighting continues after the "$".
if (diff_hlf == (hlf_T)0
&& line_attr == 0
&& line_attr_low_priority == 0) {
// In virtualedit, visual selections may extend beyond end of line.
if (area_highlighting && virtual_active()
&& tocol != MAXCOL && vcol < tocol)
&& tocol != MAXCOL && vcol < tocol) {
n_extra = 0;
else {
} else {
p_extra = at_end_str;
n_extra = 1;
c_extra = NUL;
@@ -3661,7 +3655,7 @@ win_line (
(col < wp->w_width))) {
c = ' ';
ptr--; // put it back at the NUL
} else if ((diff_hlf != (hlf_T)0 || line_attr != 0)
} else if ((diff_hlf != (hlf_T)0 || line_attr_low_priority || line_attr)
&& (wp->w_p_rl
? (col >= 0)
: (col - boguscols < wp->w_width))) {
@@ -3673,7 +3667,8 @@ win_line (
did_line_attr++;
// don't do search HL for the rest of the line
if (line_attr != 0 && char_attr == search_attr && col > 0) {
if ((line_attr_low_priority || line_attr)
&& char_attr == search_attr && col > 0) {
char_attr = line_attr;
}
if (diff_hlf == HLF_TXD) {
@@ -4035,13 +4030,16 @@ win_line (
if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol
&& lnum != wp->w_cursor.lnum) {
vcol_save_attr = char_attr;
char_attr = hl_combine_attr(char_attr, win_hl_attr(wp, HLF_CUC));
char_attr = hl_combine_attr(win_hl_attr(wp, HLF_CUC), char_attr);
} else if (draw_color_col && VCOL_HLC == *color_cols) {
vcol_save_attr = char_attr;
char_attr = hl_combine_attr(char_attr, win_hl_attr(wp, HLF_MC));
char_attr = hl_combine_attr(win_hl_attr(wp, HLF_MC), char_attr);
}
}
// Apply `line_attr_low_priority` now, so that everthing can override it.
char_attr = hl_combine_attr(line_attr_low_priority, char_attr);
/*
* Store character to be displayed.
* Skip characters that are left of the screen for 'nowrap'.

View File

@@ -42,6 +42,7 @@
#include "nvim/ui.h"
#include "nvim/os/os.h"
#include "nvim/os/time.h"
#include "nvim/api/private/helpers.h"
static bool did_syntax_onoff = false;
@@ -5567,8 +5568,10 @@ bool syntax_present(win_T *win)
static enum {
EXP_SUBCMD, /* expand ":syn" sub-commands */
EXP_CASE /* expand ":syn case" arguments */
EXP_SUBCMD, // expand ":syn" sub-commands
EXP_CASE, // expand ":syn case" arguments
EXP_SPELL, // expand ":syn spell" arguments
EXP_SYNC // expand ":syn sync" arguments
} expand_what;
/*
@@ -5612,6 +5615,10 @@ void set_context_in_syntax_cmd(expand_T *xp, const char *arg)
xp->xp_context = EXPAND_NOTHING;
} else if (STRNICMP(arg, "case", p - arg) == 0) {
expand_what = EXP_CASE;
} else if (STRNICMP(arg, "spell", p - arg) == 0) {
expand_what = EXP_SPELL;
} else if (STRNICMP(arg, "sync", p - arg) == 0) {
expand_what = EXP_SYNC;
} else if (STRNICMP(arg, "keyword", p - arg) == 0
|| STRNICMP(arg, "region", p - arg) == 0
|| STRNICMP(arg, "match", p - arg) == 0
@@ -5624,17 +5631,33 @@ void set_context_in_syntax_cmd(expand_T *xp, const char *arg)
}
}
static char *(case_args[]) = {"match", "ignore", NULL};
/*
* Function given to ExpandGeneric() to obtain the list syntax names for
* expansion.
*/
char_u *get_syntax_name(expand_T *xp, int idx)
{
if (expand_what == EXP_SUBCMD)
return (char_u *)subcommands[idx].name;
return (char_u *)case_args[idx];
switch (expand_what) {
case EXP_SUBCMD:
return (char_u *)subcommands[idx].name;
case EXP_CASE: {
static char *case_args[] = { "match", "ignore", NULL };
return (char_u *)case_args[idx];
}
case EXP_SPELL: {
static char *spell_args[] =
{ "toplevel", "notoplevel", "default", NULL };
return (char_u *)spell_args[idx];
}
case EXP_SYNC: {
static char *sync_args[] =
{ "ccomment", "clear", "fromstart",
"linebreaks=", "linecont", "lines=", "match",
"maxlines=", "minlines=", "region", NULL };
return (char_u *)sync_args[idx];
}
}
return NULL;
}
@@ -6622,7 +6645,6 @@ do_highlight(char_u *line, int forceit, int init) {
syn_unadd_group();
} else {
if (is_normal_group) {
HL_TABLE()[idx].sg_attr = 0;
// Need to update all groups, because they might be using "bg" and/or
// "fg", which have been changed now.
highlight_attr_set_all();
@@ -6825,8 +6847,6 @@ int hl_combine_attr(int char_attr, int prim_attr)
if (char_aep != NULL) {
// Copy all attributes from char_aep to the new entry
new_en = *char_aep;
} else {
memset(&new_en, 0, sizeof(new_en));
}
spell_aep = syn_cterm_attr2entry(prim_attr);
@@ -6859,6 +6879,7 @@ int hl_combine_attr(int char_attr, int prim_attr)
/// \note this function does not apply exclusively to cterm attr contrary
/// to what its name implies
/// \warn don't call it with attr 0 (i.e., the null attribute)
attrentry_T *syn_cterm_attr2entry(int attr)
{
attr -= ATTR_OFF;
@@ -7103,22 +7124,14 @@ syn_list_header(int did_header, int outlen, int id)
return newline;
}
/*
* Set the attribute numbers for a highlight group.
* Called after one of the attributes has changed.
*/
static void
set_hl_attr (
int idx /* index in array */
)
/// Set the attribute numbers for a highlight group.
/// Called after one of the attributes has changed.
/// @param idx corrected highlight index
static void set_hl_attr(int idx)
{
attrentry_T at_en = ATTRENTRY_INIT;
struct hl_group *sgp = HL_TABLE() + idx;
// The "Normal" group doesn't need an attribute number
if (sgp->sg_name_u != NULL && STRCMP(sgp->sg_name_u, "NORMAL") == 0) {
return;
}
at_en.cterm_ae_attr = sgp->sg_cterm;
at_en.cterm_fg_color = sgp->sg_cterm_fg;
@@ -8227,6 +8240,30 @@ RgbValue name_to_color(const uint8_t *name)
return -1;
}
/// Gets highlight description for id `attr_id` as a map.
Dictionary hl_get_attr_by_id(Integer attr_id, Boolean rgb, Error *err)
{
HlAttrs attrs = HLATTRS_INIT;
Dictionary dic = ARRAY_DICT_INIT;
if (attr_id == 0) {
goto end;
}
attrentry_T *aep = syn_cterm_attr2entry((int)attr_id);
if (!aep) {
api_set_error(err, kErrorTypeException,
"Invalid attribute id: %d", attr_id);
return dic;
}
attrs = attrentry2hlattrs(aep, rgb);
end:
return hlattrs2dict(attrs);
}
/**************************************
* End of Highlighting stuff *
**************************************/

View File

@@ -59,6 +59,7 @@ NEW_TESTS ?= \
test_matchadd_conceal.res \
test_matchadd_conceal_utf8.res \
test_mksession.res \
test_mksession_utf8.res \
test_nested_function.res \
test_normal.res \
test_quickfix.res \

View File

@@ -76,3 +76,11 @@ func Test_syntax_after_reload()
call assert_true(exists('g:gotit'))
call delete('Xsomefile')
endfunc
func Test_syntax_completion()
call feedkeys(":syn spell \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"syn spell default notoplevel toplevel', @:)
call feedkeys(":syn sync \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"syn sync ccomment clear fromstart linebreaks= linecont lines= match maxlines= minlines= region', @:)
endfunc

View File

@@ -288,7 +288,7 @@ static void terminfo_stop(UI *ui)
static void tui_terminal_start(UI *ui)
{
TUIData *data = ui->data;
data->print_attrs = EMPTY_ATTRS;
data->print_attrs = HLATTRS_INIT;
ugrid_init(&data->grid);
terminfo_start(ui);
update_size(ui);
@@ -628,7 +628,7 @@ static void clear_region(UI *ui, int top, int bot, int left, int right)
if (grid->bg == -1 && right == ui->width -1) {
// Background is set to the default color and the right edge matches the
// screen end, try to use terminal codes for clearing the requested area.
HlAttrs clear_attrs = EMPTY_ATTRS;
HlAttrs clear_attrs = HLATTRS_INIT;
clear_attrs.foreground = grid->fg;
clear_attrs.background = grid->bg;
update_attrs(ui, clear_attrs);
@@ -926,7 +926,7 @@ static void tui_scroll(UI *ui, Integer count)
cursor_goto(ui, grid->top, grid->left);
// also set default color attributes or some terminals can become funny
if (scroll_clears_to_current_colour) {
HlAttrs clear_attrs = EMPTY_ATTRS;
HlAttrs clear_attrs = HLATTRS_INIT;
clear_attrs.foreground = grid->fg;
clear_attrs.background = grid->bg;
update_attrs(ui, clear_attrs);

View File

@@ -16,7 +16,7 @@
void ugrid_init(UGrid *grid)
{
grid->attrs = EMPTY_ATTRS;
grid->attrs = HLATTRS_INIT;
grid->fg = grid->bg = -1;
grid->cells = NULL;
}
@@ -118,7 +118,7 @@ UCell *ugrid_put(UGrid *grid, uint8_t *text, size_t size)
static void clear_region(UGrid *grid, int top, int bot, int left, int right)
{
HlAttrs clear_attrs = EMPTY_ATTRS;
HlAttrs clear_attrs = HLATTRS_INIT;
clear_attrs.foreground = grid->fg;
clear_attrs.background = grid->bg;
UGRID_FOREACH_CELL(grid, top, bot, left, right, {

View File

@@ -21,8 +21,6 @@ struct ugrid {
UCell **cells;
};
#define EMPTY_ATTRS ((HlAttrs){ false, false, false, false, false, -1, -1, -1 })
#define UGRID_FOREACH_CELL(grid, top, bot, left, right, code) \
do { \
for (int row = top; row <= bot; row++) { \

View File

@@ -166,6 +166,90 @@ void ui_event(char *name, Array args)
}
}
/// Converts an attrentry_T into an HlAttrs
///
/// @param[in] aep data to convert
/// @param use_rgb use 'gui*' settings if true, else resorts to 'cterm*'
HlAttrs attrentry2hlattrs(const attrentry_T *aep, bool use_rgb)
{
assert(aep);
HlAttrs attrs = HLATTRS_INIT;
int mask = 0;
mask = use_rgb ? aep->rgb_ae_attr : aep->cterm_ae_attr;
attrs.bold = mask & HL_BOLD;
attrs.underline = mask & HL_UNDERLINE;
attrs.undercurl = mask & HL_UNDERCURL;
attrs.italic = mask & HL_ITALIC;
attrs.reverse = mask & (HL_INVERSE | HL_STANDOUT);
if (use_rgb) {
if (aep->rgb_fg_color != -1) {
attrs.foreground = aep->rgb_fg_color;
}
if (aep->rgb_bg_color != -1) {
attrs.background = aep->rgb_bg_color;
}
if (aep->rgb_sp_color != -1) {
attrs.special = aep->rgb_sp_color;
}
} else {
if (cterm_normal_fg_color != aep->cterm_fg_color) {
attrs.foreground = aep->cterm_fg_color - 1;
}
if (cterm_normal_bg_color != aep->cterm_bg_color) {
attrs.background = aep->cterm_bg_color - 1;
}
}
return attrs;
}
Dictionary hlattrs2dict(HlAttrs attrs)
{
Dictionary hl = ARRAY_DICT_INIT;
if (attrs.bold) {
PUT(hl, "bold", BOOLEAN_OBJ(true));
}
if (attrs.underline) {
PUT(hl, "underline", BOOLEAN_OBJ(true));
}
if (attrs.undercurl) {
PUT(hl, "undercurl", BOOLEAN_OBJ(true));
}
if (attrs.italic) {
PUT(hl, "italic", BOOLEAN_OBJ(true));
}
if (attrs.reverse) {
PUT(hl, "reverse", BOOLEAN_OBJ(true));
}
if (attrs.foreground != -1) {
PUT(hl, "foreground", INTEGER_OBJ(attrs.foreground));
}
if (attrs.background != -1) {
PUT(hl, "background", INTEGER_OBJ(attrs.background));
}
if (attrs.special != -1) {
PUT(hl, "special", INTEGER_OBJ(attrs.special));
}
return hl;
}
void ui_refresh(void)
{
if (!ui_active()) {
@@ -405,54 +489,20 @@ void ui_flush(void)
static void set_highlight_args(int attr_code)
{
HlAttrs rgb_attrs = { false, false, false, false, false, -1, -1, -1 };
HlAttrs rgb_attrs = HLATTRS_INIT;
HlAttrs cterm_attrs = rgb_attrs;
if (attr_code == HL_NORMAL) {
goto end;
}
int rgb_mask = 0;
int cterm_mask = 0;
attrentry_T *aep = syn_cterm_attr2entry(attr_code);
if (!aep) {
goto end;
}
rgb_mask = aep->rgb_ae_attr;
cterm_mask = aep->cterm_ae_attr;
rgb_attrs.bold = rgb_mask & HL_BOLD;
rgb_attrs.underline = rgb_mask & HL_UNDERLINE;
rgb_attrs.undercurl = rgb_mask & HL_UNDERCURL;
rgb_attrs.italic = rgb_mask & HL_ITALIC;
rgb_attrs.reverse = rgb_mask & (HL_INVERSE | HL_STANDOUT);
cterm_attrs.bold = cterm_mask & HL_BOLD;
cterm_attrs.underline = cterm_mask & HL_UNDERLINE;
cterm_attrs.undercurl = cterm_mask & HL_UNDERCURL;
cterm_attrs.italic = cterm_mask & HL_ITALIC;
cterm_attrs.reverse = cterm_mask & (HL_INVERSE | HL_STANDOUT);
if (aep->rgb_fg_color != normal_fg) {
rgb_attrs.foreground = aep->rgb_fg_color;
}
if (aep->rgb_bg_color != normal_bg) {
rgb_attrs.background = aep->rgb_bg_color;
}
if (aep->rgb_sp_color != normal_sp) {
rgb_attrs.special = aep->rgb_sp_color;
}
if (cterm_normal_fg_color != aep->cterm_fg_color) {
cterm_attrs.foreground = aep->cterm_fg_color - 1;
}
if (cterm_normal_bg_color != aep->cterm_bg_color) {
cterm_attrs.background = aep->cterm_bg_color - 1;
}
rgb_attrs = attrentry2hlattrs(aep, true);
cterm_attrs = attrentry2hlattrs(aep, false);
end:
UI_CALL(highlight_set, (ui->rgb ? rgb_attrs : cterm_attrs));

View File

@@ -21,6 +21,9 @@ typedef struct {
int foreground, background, special;
} HlAttrs;
#define HLATTRS_INIT \
((HlAttrs){ false, false, false, false, false, -1, -1, -1 })
typedef struct ui_t UI;
struct ui_t {

View File

@@ -939,14 +939,14 @@ static const int included_patches[] = {
167,
// 166,
165,
// 164,
164,
// 163 NA
// 162 NA
// 161 NA
// 160,
159,
158,
// 157,
157,
156,
// 155,
// 154,
@@ -955,13 +955,13 @@ static const int included_patches[] = {
// 151,
150,
149,
// 148,
148,
147,
146,
// 145 NA
// 144 NA
143,
// 142,
142,
// 141,
// 140,
// 139 NA