Merge #6597 'winhighlight'

This commit is contained in:
Justin M. Keyes 2017-05-08 16:17:57 +02:00
commit b23aa1cf09
12 changed files with 460 additions and 28 deletions

View File

@ -3128,7 +3128,8 @@ A jump table for the options with a short description can be found at |Q_op|.
use for that occasion. The occasions are: use for that occasion. The occasions are:
|hl-SpecialKey| 8 Meta and special keys listed with ":map" |hl-SpecialKey| 8 Meta and special keys listed with ":map"
|hl-Whitespace| 0 |hl-Whitespace| 0
|hl-EndOfBuffer| ~ lines after the last line in the buffer |hl-EndOfBuffer| ~ lines after the last line in the buffer
|hl-NormalNC| I non-current ("inactive") window
|hl-TermCursor| z Cursor in a focused terminal |hl-TermCursor| z Cursor in a focused terminal
|hl-TermCursorNC| Z Cursor in an unfocused terminal |hl-TermCursorNC| Z Cursor in an unfocused terminal
|hl-NonText| @ '@' at the end of the window and |hl-NonText| @ '@' at the end of the window and
@ -6843,6 +6844,17 @@ A jump table for the options with a short description can be found at |Q_op|.
'winheight' applies to the current window. Use 'winminheight' to set 'winheight' applies to the current window. Use 'winminheight' to set
the minimal height for other windows. the minimal height for other windows.
*'winhighlight'* *'winhl'*
'winhighlight' 'winhl' string (default empty)
local to window
Window-local highlights. Comma-delimited list of |group-name| pairs
"{hl-builtin}:{hl-group},..." where each {hl-builtin} is a group (from
|highlight-groups|) to be overridden by {hl-group} in the window where
this option was set.
Currently |hl-Normal| and |hl-NormalNC| can be overridden.
Useful for changing the background color. Example: >
set winhighlight=Normal:MyNormal,NormalNC:MyNormalNC
<
*'winfixheight'* *'wfh'* *'nowinfixheight'* *'nowfh'* *'winfixheight'* *'wfh'* *'nowinfixheight'* *'nowfh'*
'winfixheight' 'wfh' boolean (default off) 'winfixheight' 'wfh' boolean (default off)
local to window local to window

View File

@ -4922,6 +4922,8 @@ NonText '@' at the end of the window, characters from 'showbreak'
fit at the end of the line). See also |hl-EndOfBuffer|. fit at the end of the line). See also |hl-EndOfBuffer|.
*hl-Normal* *hl-Normal*
Normal normal text Normal normal text
*hl-NormalNC*
NormalNC normal text in non-current window
*hl-Pmenu* *hl-Pmenu*
Pmenu Popup menu: normal item. Pmenu Popup menu: normal item.
*hl-PmenuSel* *hl-PmenuSel*

View File

@ -2316,7 +2316,7 @@ void get_winopts(buf_T *buf)
/* Set 'foldlevel' to 'foldlevelstart' if it's not negative. */ /* Set 'foldlevel' to 'foldlevelstart' if it's not negative. */
if (p_fdls >= 0) if (p_fdls >= 0)
curwin->w_p_fdl = p_fdls; curwin->w_p_fdl = p_fdls;
check_colorcolumn(curwin); didset_window_options(curwin);
} }
/* /*

View File

@ -233,6 +233,8 @@ typedef struct {
# define w_p_crb_save w_onebuf_opt.wo_crb_save # define w_p_crb_save w_onebuf_opt.wo_crb_save
char_u *wo_scl; char_u *wo_scl;
# define w_p_scl w_onebuf_opt.wo_scl // 'signcolumn' # define w_p_scl w_onebuf_opt.wo_scl // 'signcolumn'
char_u *wo_winhl;
# define w_p_winhl w_onebuf_opt.wo_winhl // 'winhighlight'
int wo_scriptID[WV_COUNT]; /* SIDs for window-local options */ int wo_scriptID[WV_COUNT]; /* SIDs for window-local options */
# define w_p_scriptID w_onebuf_opt.wo_scriptID # define w_p_scriptID w_onebuf_opt.wo_scriptID
@ -930,6 +932,10 @@ struct window_S {
synblock_T *w_s; /* for :ownsyntax */ synblock_T *w_s; /* for :ownsyntax */
int w_hl_id; ///< 'winhighlight' id
int w_hl_id_inactive; ///< 'winhighlight' id for inactive window
int w_hl_attr; ///< 'winhighlight' final attrs
win_T *w_prev; /* link to previous window */ win_T *w_prev; /* link to previous window */
win_T *w_next; /* link to next window */ win_T *w_next; /* link to next window */
bool w_closing; /* window is being closed, don't let bool w_closing; /* window is being closed, don't let

View File

@ -465,6 +465,7 @@ typedef enum {
, HLF_MC // 'colorcolumn' , HLF_MC // 'colorcolumn'
, HLF_QFL // selected quickfix line , HLF_QFL // selected quickfix line
, HLF_0 // Whitespace , HLF_0 // Whitespace
, HLF_INACTIVE // NormalNC: Normal text in non-current windows
, HLF_COUNT // MUST be the last one , HLF_COUNT // MUST be the last one
} hlf_T; } hlf_T;
@ -473,7 +474,7 @@ typedef enum {
#define HL_FLAGS { '8', '~', 'z', 'Z', '@', 'd', 'e', 'i', 'l', 'm', 'M', 'n', \ #define HL_FLAGS { '8', '~', 'z', 'Z', '@', 'd', 'e', 'i', 'l', 'm', 'M', 'n', \
'N', 'r', 's', 'S', 'c', 't', 'v', 'V', 'w', 'W', 'f', 'F', \ 'N', 'r', 's', 'S', 'c', 't', 'v', 'V', 'w', 'W', 'f', 'F', \
'A', 'C', 'D', 'T', '-', '>', 'B', 'P', 'R', 'L', '+', '=', \ 'A', 'C', 'D', 'T', '-', '>', 'B', 'P', 'R', 'L', '+', '=', \
'x', 'X', '*', '#', '_', '!', '.', 'o', 'q', '0' } 'x', 'X', '*', '#', '_', '!', '.', 'o', 'q', '0', 'I' }
EXTERN int highlight_attr[HLF_COUNT]; /* Highl. attr for each context. */ EXTERN int highlight_attr[HLF_COUNT]; /* Highl. attr for each context. */
EXTERN int highlight_user[9]; /* User[1-9] attributes */ EXTERN int highlight_user[9]; /* User[1-9] attributes */

View File

@ -8,6 +8,9 @@
// - Add a BV_XX or WV_XX entry to option_defs.h // - Add a BV_XX or WV_XX entry to option_defs.h
// - Add a variable to the window or buffer struct in buffer_defs.h. // - Add a variable to the window or buffer struct in buffer_defs.h.
// - For a window option, add some code to copy_winopt(). // - For a window option, add some code to copy_winopt().
// - For a window string option, add code to check_winopt()
// and clear_winopt(). If setting the option needs parsing,
// add some code to didset_window_options().
// - For a buffer option, add some code to buf_copy_options(). // - For a buffer option, add some code to buf_copy_options().
// - For a buffer string option, add code to check_buf_options(). // - For a buffer string option, add code to check_buf_options().
// - If it's a numeric option, add any necessary bounds checks to do_set(). // - If it's a numeric option, add any necessary bounds checks to do_set().
@ -249,7 +252,7 @@ typedef struct vimoption {
"B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel," \ "B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel," \
"x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill," \ "x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill," \
"!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine," \ "!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine," \
"0:Whitespace" "0:Whitespace,I:NormalNC"
/* /*
* options[] is initialized here. * options[] is initialized here.
@ -3171,6 +3174,10 @@ did_set_string_option (
if (!valid_filetype(*varp)) { if (!valid_filetype(*varp)) {
errmsg = e_invarg; errmsg = e_invarg;
} }
} else if (varp == &curwin->w_p_winhl) {
if (!parse_winhl_opt(curwin)) {
errmsg = e_invarg;
}
} else { } else {
// Options that are a list of flags. // Options that are a list of flags.
p = NULL; p = NULL;
@ -3579,6 +3586,38 @@ static char_u *compile_cap_prog(synblock_T *synblock)
return NULL; return NULL;
} }
/// Handle setting `winhighlight' in window "wp"
static bool parse_winhl_opt(win_T *wp)
{
int w_hl_id = 0, w_hl_id_inactive = 0;
const char *p = (const char *)wp->w_p_winhl;
while (*p) {
char *colon = strchr(p, ':');
if (!colon) {
return false;
}
size_t nlen = (size_t)(colon-p);
char *hi = colon+1;
char *commap = xstrchrnul(hi, ',');
int hl_id = syn_check_group((char_u *)hi, (int)(commap-hi));
if (strncmp("Normal", p, nlen) == 0) {
w_hl_id = hl_id;
} else if (strncmp("NormalNC", p, nlen) == 0) {
w_hl_id_inactive = hl_id;
} else {
return false;
}
p = *commap ? commap+1 : "";
}
wp->w_hl_id = w_hl_id;
wp->w_hl_id_inactive = w_hl_id_inactive;
return true;
}
/* /*
* Set the scriptID for an option, taking care of setting the buffer- or * Set the scriptID for an option, taking care of setting the buffer- or
* window-local value. * window-local value.
@ -5488,6 +5527,7 @@ static char_u *get_varp(vimoption_T *p)
case PV_WM: return (char_u *)&(curbuf->b_p_wm); case PV_WM: return (char_u *)&(curbuf->b_p_wm);
case PV_KMAP: return (char_u *)&(curbuf->b_p_keymap); case PV_KMAP: return (char_u *)&(curbuf->b_p_keymap);
case PV_SCL: return (char_u *)&(curwin->w_p_scl); case PV_SCL: return (char_u *)&(curwin->w_p_scl);
case PV_WINHL: return (char_u *)&(curwin->w_p_winhl);
default: EMSG(_("E356: get_varp ERROR")); default: EMSG(_("E356: get_varp ERROR"));
} }
/* always return a valid pointer to avoid a crash! */ /* always return a valid pointer to avoid a crash! */
@ -5514,7 +5554,6 @@ void win_copy_options(win_T *wp_from, win_T *wp_to)
copy_winopt(&wp_from->w_allbuf_opt, &wp_to->w_allbuf_opt); copy_winopt(&wp_from->w_allbuf_opt, &wp_to->w_allbuf_opt);
/* Is this right? */ /* Is this right? */
wp_to->w_farsi = wp_from->w_farsi; wp_to->w_farsi = wp_from->w_farsi;
briopt_check(wp_to);
} }
/* /*
@ -5566,6 +5605,7 @@ void copy_winopt(winopt_T *from, winopt_T *to)
to->wo_fdt = vim_strsave(from->wo_fdt); to->wo_fdt = vim_strsave(from->wo_fdt);
to->wo_fmr = vim_strsave(from->wo_fmr); to->wo_fmr = vim_strsave(from->wo_fmr);
to->wo_scl = vim_strsave(from->wo_scl); to->wo_scl = vim_strsave(from->wo_scl);
to->wo_winhl = vim_strsave(from->wo_winhl);
check_winopt(to); // don't want NULL pointers check_winopt(to); // don't want NULL pointers
} }
@ -5595,6 +5635,7 @@ static void check_winopt(winopt_T *wop)
check_string_option(&wop->wo_cc); check_string_option(&wop->wo_cc);
check_string_option(&wop->wo_cocu); check_string_option(&wop->wo_cocu);
check_string_option(&wop->wo_briopt); check_string_option(&wop->wo_briopt);
check_string_option(&wop->wo_winhl);
} }
/* /*
@ -5614,8 +5655,17 @@ void clear_winopt(winopt_T *wop)
clear_string_option(&wop->wo_cc); clear_string_option(&wop->wo_cc);
clear_string_option(&wop->wo_cocu); clear_string_option(&wop->wo_cocu);
clear_string_option(&wop->wo_briopt); clear_string_option(&wop->wo_briopt);
clear_string_option(&wop->wo_winhl);
} }
void didset_window_options(win_T *wp)
{
check_colorcolumn(wp);
briopt_check(wp);
parse_winhl_opt(wp);
}
/* /*
* Copy global option values to local options for one buffer. * Copy global option values to local options for one buffer.
* Used when creating a new buffer and sometimes when entering a buffer. * Used when creating a new buffer and sometimes when entering a buffer.

View File

@ -807,6 +807,7 @@ enum {
, WV_WFW , WV_WFW
, WV_WRAP , WV_WRAP
, WV_SCL , WV_SCL
, WV_WINHL
, WV_COUNT // must be the last one , WV_COUNT // must be the last one
}; };

View File

@ -2701,6 +2701,14 @@ return {
varname='p_wak', varname='p_wak',
defaults={if_true={vi="menu"}} defaults={if_true={vi="menu"}}
}, },
{
full_name='winhighlight', abbreviation='winhl',
type='string', scope={'window'},
vi_def=true,
alloced=true,
redraw={'current_window'},
defaults={if_true={vi=""}}
},
{ {
full_name='window', abbreviation='wi', full_name='window', abbreviation='wi',
type='number', scope={'global'}, type='number', scope={'global'},

View File

@ -1584,6 +1584,11 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h
# define FDC_OFF n # define FDC_OFF n
int fdc = compute_foldcolumn(wp, 0); int fdc = compute_foldcolumn(wp, 0);
int attr = hl_attr(hl);
if (wp->w_hl_attr != 0) {
attr = hl_combine_attr(wp->w_hl_attr, attr);
}
if (wp->w_p_rl) { if (wp->w_p_rl) {
// No check for cmdline window: should never be right-left. // No check for cmdline window: should never be right-left.
n = fdc; n = fdc;
@ -1612,10 +1617,10 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h
screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, screen_fill(wp->w_winrow + row, wp->w_winrow + endrow,
wp->w_wincol, W_ENDCOL(wp) - 1 - FDC_OFF, wp->w_wincol, W_ENDCOL(wp) - 1 - FDC_OFF,
c2, c2, hl_attr(hl)); c2, c2, attr);
screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, screen_fill(wp->w_winrow + row, wp->w_winrow + endrow,
W_ENDCOL(wp) - 1 - FDC_OFF, W_ENDCOL(wp) - FDC_OFF, W_ENDCOL(wp) - 1 - FDC_OFF, W_ENDCOL(wp) - FDC_OFF,
c1, c2, hl_attr(hl)); c1, c2, attr);
} else { } else {
if (cmdwin_type != 0 && wp == curwin) { if (cmdwin_type != 0 && wp == curwin) {
/* draw the cmdline character in the leftmost column */ /* draw the cmdline character in the leftmost column */
@ -1653,7 +1658,7 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h
screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, screen_fill(wp->w_winrow + row, wp->w_winrow + endrow,
wp->w_wincol + FDC_OFF, W_ENDCOL(wp), wp->w_wincol + FDC_OFF, W_ENDCOL(wp),
c1, c2, hl_attr(hl)); c1, c2, attr);
} }
set_empty_rows(wp, row); set_empty_rows(wp, row);
} }
@ -2418,6 +2423,10 @@ win_line (
line_attr = hl_attr(HLF_QFL); line_attr = hl_attr(HLF_QFL);
} }
if (wp->w_hl_attr != 0) {
line_attr = hl_combine_attr(wp->w_hl_attr, line_attr);
}
if (line_attr != 0) { if (line_attr != 0) {
area_highlighting = true; area_highlighting = true;
} }
@ -2849,6 +2858,10 @@ win_line (
} else } else
char_attr = 0; char_attr = 0;
} }
if (wp->w_hl_attr != 0) {
char_attr = hl_combine_attr(wp->w_hl_attr, char_attr);
}
} }
/* When still displaying '$' of change command, stop at cursor */ /* When still displaying '$' of change command, stop at cursor */
@ -3083,10 +3096,14 @@ win_line (
mb_l = 1; mb_l = 1;
mb_utf8 = FALSE; mb_utf8 = FALSE;
multi_attr = hl_attr(HLF_AT); multi_attr = hl_attr(HLF_AT);
/* put the pointer back to output the double-width if (wp->w_hl_attr != 0) {
* character at the start of the next line. */ multi_attr = hl_combine_attr(wp->w_hl_attr, multi_attr);
++n_extra; }
--p_extra;
// put the pointer back to output the double-width
// character at the start of the next line.
n_extra++;
p_extra--;
} else { } else {
n_extra -= mb_l - 1; n_extra -= mb_l - 1;
p_extra += mb_l - 1; p_extra += mb_l - 1;
@ -3221,11 +3238,15 @@ win_line (
mb_utf8 = FALSE; mb_utf8 = FALSE;
mb_l = 1; mb_l = 1;
multi_attr = hl_attr(HLF_AT); multi_attr = hl_attr(HLF_AT);
/* Put pointer back so that the character will be if (wp->w_hl_attr != 0) {
* displayed at the start of the next line. */ multi_attr = hl_combine_attr(wp->w_hl_attr, multi_attr);
--ptr; }
} else if (*ptr != NUL) // Put pointer back so that the character will be
// displayed at the start of the next line.
ptr--;
} else if (*ptr != NUL) {
ptr += mb_l - 1; ptr += mb_l - 1;
}
/* If a double-width char doesn't fit at the left side display /* If a double-width char doesn't fit at the left side display
* a '<' in the first column. Don't do this for unprintable * a '<' in the first column. Don't do this for unprintable
@ -3752,7 +3773,10 @@ win_line (
mb_utf8 = false; // don't draw as UTF-8 mb_utf8 = false; // don't draw as UTF-8
} }
saved_attr3 = char_attr; // save current attr saved_attr3 = char_attr; // save current attr
char_attr = hl_attr(HLF_AT); // later copied to char_attr char_attr = hl_attr(HLF_AT); // overwriting char_attr
if (wp->w_hl_attr != 0) {
char_attr = hl_combine_attr(wp->w_hl_attr, char_attr);
}
n_attr3 = 1; n_attr3 = 1;
} }
@ -3836,6 +3860,10 @@ win_line (
} }
} }
} }
if (wp->w_hl_attr != 0) {
char_attr = hl_combine_attr(wp->w_hl_attr, char_attr);
}
ScreenAttrs[off] = char_attr; ScreenAttrs[off] = char_attr;
if (wp->w_p_rl) { if (wp->w_p_rl) {
--col; --col;
@ -3897,6 +3925,14 @@ win_line (
if (rightmost_vcol < color_cols[i]) if (rightmost_vcol < color_cols[i])
rightmost_vcol = color_cols[i]; rightmost_vcol = color_cols[i];
int cuc_attr = hl_attr(HLF_CUC);
int mc_attr = hl_attr(HLF_MC);
if (wp->w_hl_attr != 0) {
cuc_attr = hl_combine_attr(wp->w_hl_attr, cuc_attr);
mc_attr = hl_combine_attr(wp->w_hl_attr, mc_attr);
}
while (col < wp->w_width) { while (col < wp->w_width) {
ScreenLines[off] = ' '; ScreenLines[off] = ' ';
if (enc_utf8) if (enc_utf8)
@ -3906,12 +3942,13 @@ win_line (
draw_color_col = advance_color_col(VCOL_HLC, draw_color_col = advance_color_col(VCOL_HLC,
&color_cols); &color_cols);
if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol) if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol) {
ScreenAttrs[off++] = hl_attr(HLF_CUC); ScreenAttrs[off++] = cuc_attr;
else if (draw_color_col && VCOL_HLC == *color_cols) } else if (draw_color_col && VCOL_HLC == *color_cols) {
ScreenAttrs[off++] = hl_attr(HLF_MC); ScreenAttrs[off++] = mc_attr;
else } else {
ScreenAttrs[off++] = 0; ScreenAttrs[off++] = wp->w_hl_attr;
}
if (VCOL_HLC >= rightmost_vcol) if (VCOL_HLC >= rightmost_vcol)
break; break;
@ -3920,6 +3957,7 @@ win_line (
} }
} }
// TODO(bfredl): integrate with the common beyond-the-end-loop
if (wp->w_buffer->terminal) { if (wp->w_buffer->terminal) {
// terminal buffers may need to highlight beyond the end of the // terminal buffers may need to highlight beyond the end of the
// logical line // logical line
@ -3961,6 +3999,9 @@ win_line (
|| (n_extra && (c_extra != NUL || *p_extra != NUL)))) { || (n_extra && (c_extra != NUL || *p_extra != NUL)))) {
c = lcs_ext; c = lcs_ext;
char_attr = hl_attr(HLF_AT); char_attr = hl_attr(HLF_AT);
if (wp->w_hl_attr != 0) {
char_attr = hl_combine_attr(wp->w_hl_attr, char_attr);
}
mb_c = c; mb_c = c;
if (enc_utf8 && (*mb_char2len)(c) > 1) { if (enc_utf8 && (*mb_char2len)(c) > 1) {
mb_utf8 = TRUE; mb_utf8 = TRUE;
@ -5510,7 +5551,19 @@ static void init_search_hl(win_T *wp)
search_hl.buf = wp->w_buffer; search_hl.buf = wp->w_buffer;
search_hl.lnum = 0; search_hl.lnum = 0;
search_hl.first_lnum = 0; search_hl.first_lnum = 0;
/* time limit is set at the toplevel, for all windows */ // time limit is set at the toplevel, for all windows
// determine window specific background set in 'winhighlight'
if (wp != curwin && wp->w_hl_id_inactive > 0) {
wp->w_hl_attr = syn_id2attr(wp->w_hl_id_inactive);
} else if (wp->w_hl_id > 0) {
wp->w_hl_attr = syn_id2attr(wp->w_hl_id);
} else {
wp->w_hl_attr = 0;
}
if (wp != curwin) {
wp->w_hl_attr = hl_combine_attr(hl_attr(HLF_INACTIVE), wp->w_hl_attr);
}
} }
/* /*

View File

@ -1043,7 +1043,7 @@ static void win_init(win_T *newp, win_T *oldp, int flags)
win_init_some(newp, oldp); win_init_some(newp, oldp);
check_colorcolumn(newp); didset_window_options(newp);
} }
/* /*
@ -3722,6 +3722,12 @@ static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid,
if (restart_edit) if (restart_edit)
redraw_later(VALID); /* causes status line redraw */ redraw_later(VALID); /* causes status line redraw */
if (hl_attr(HLF_INACTIVE)
|| (prevwin && prevwin->w_hl_id_inactive)
|| curwin->w_hl_id_inactive) {
redraw_all_later(NOT_VALID);
}
/* set window height to desired minimal value */ /* set window height to desired minimal value */
if (curwin->w_height < p_wh && !curwin->w_p_wfh) if (curwin->w_height < p_wh && !curwin->w_p_wfh)
win_setheight((int)p_wh); win_setheight((int)p_wh);

View File

@ -194,8 +194,8 @@ describe('ui/cursor', function()
if m.blinkoff then m.blinkoff = 400 end if m.blinkoff then m.blinkoff = 400 end
if m.blinkwait then m.blinkwait = 700 end if m.blinkwait then m.blinkwait = 700 end
end end
if m.hl_id then m.hl_id = 46 end if m.hl_id then m.hl_id = 47 end
if m.id_lm then m.id_lm = 47 end if m.id_lm then m.id_lm = 48 end
end end
-- Assert the new expectation. -- Assert the new expectation.

View File

@ -3,7 +3,7 @@ local Screen = require('test.functional.ui.screen')
local os = require('os') local os = require('os')
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local command = helpers.command local command = helpers.command
local eval = helpers.eval local eval, exc_exec = helpers.eval, helpers.exc_exec
local feed_command, request, eq = helpers.feed_command, helpers.request, helpers.eq local feed_command, request, eq = helpers.feed_command, helpers.request, helpers.eq
describe('colorscheme compatibility', function() describe('colorscheme compatibility', function()
@ -650,3 +650,296 @@ describe("'listchars' highlight", function()
]]) ]])
end) end)
end) end)
describe("'winhighlight' highlight", function()
local screen
before_each(function()
clear()
screen = Screen.new(20,8)
screen:attach()
screen:set_default_attr_ids({
[0] = {bold=true, foreground=Screen.colors.Blue},
[1] = {background = Screen.colors.DarkBlue},
[2] = {background = Screen.colors.DarkBlue, bold = true, foreground = Screen.colors.Blue1},
[3] = {bold = true, reverse = true},
[4] = {reverse = true},
[5] = {background = Screen.colors.DarkGreen},
[6] = {background = Screen.colors.DarkGreen, bold = true, foreground = Screen.colors.Blue1},
[7] = {background = Screen.colors.DarkMagenta},
[8] = {background = Screen.colors.DarkMagenta, bold = true, foreground = Screen.colors.Blue1},
[9] = {foreground = Screen.colors.Brown},
[10] = {foreground = Screen.colors.Brown, background = Screen.colors.DarkBlue},
})
command("hi Background1 guibg=DarkBlue")
command("hi Background2 guibg=DarkGreen")
end)
it('works', function()
insert("aa")
command("split")
command("set winhl=Normal:Background1")
screen:expect([[
{1:a^a }|
{2:~ }|
{2:~ }|
{3:[No Name] [+] }|
aa |
{0:~ }|
{4:[No Name] [+] }|
|
]])
command("enew")
screen:expect([[
{1:^ }|
{2:~ }|
{2:~ }|
{3:[No Name] }|
aa |
{0:~ }|
{4:[No Name] [+] }|
|
]])
end)
it('handles invalid values', function()
command("set winhl=Normal:Background1")
screen:expect([[
{1:^ }|
{2:~ }|
{2:~ }|
{2:~ }|
{2:~ }|
{2:~ }|
{2:~ }|
|
]])
eq('Vim(set):E474: Invalid argument: winhl=xxx:yyy',
exc_exec("set winhl=xxx:yyy"))
eq('Normal:Background1', eval('&winhl'))
screen:expect([[
{1:^ }|
{2:~ }|
{2:~ }|
{2:~ }|
{2:~ }|
{2:~ }|
{2:~ }|
|
]])
end)
it('works local to the buffer', function()
insert("aa")
command("split")
command("setlocal winhl=Normal:Background1")
screen:expect([[
{1:a^a }|
{2:~ }|
{2:~ }|
{3:[No Name] [+] }|
aa |
{0:~ }|
{4:[No Name] [+] }|
|
]])
command("enew")
screen:expect([[
^ |
{0:~ }|
{0:~ }|
{3:[No Name] }|
aa |
{0:~ }|
{4:[No Name] [+] }|
|
]])
command("bnext")
screen:expect([[
{1:^aa }|
{2:~ }|
{2:~ }|
{3:[No Name] [+] }|
aa |
{0:~ }|
{4:[No Name] [+] }|
<f 1 --100%-- col 1 |
]])
end)
it('for inactive window works', function()
command("set winhl=Normal:Background1,NormalNC:Background2")
-- tests global value is copied across split
command("split")
screen:expect([[
{1:^ }|
{2:~ }|
{2:~ }|
{3:[No Name] }|
{5: }|
{6:~ }|
{4:[No Name] }|
|
]])
feed("<c-w><c-w>")
screen:expect([[
{5: }|
{6:~ }|
{6:~ }|
{4:[No Name] }|
{1:^ }|
{2:~ }|
{3:[No Name] }|
|
]])
feed("<c-w><c-w>")
screen:expect([[
{1:^ }|
{2:~ }|
{2:~ }|
{3:[No Name] }|
{5: }|
{6:~ }|
{4:[No Name] }|
|
]])
end)
it('works with NormalNC', function()
command("hi NormalNC guibg=DarkMagenta")
-- tests global value is copied across split
command("split")
screen:expect([[
^ |
{0:~ }|
{0:~ }|
{3:[No Name] }|
{7: }|
{8:~ }|
{4:[No Name] }|
|
]])
command("wincmd w")
screen:expect([[
{7: }|
{8:~ }|
{8:~ }|
{4:[No Name] }|
^ |
{0:~ }|
{3:[No Name] }|
|
]])
-- winbg=Normal:... overrides global NormalNC
command("set winhl=Normal:Background1")
screen:expect([[
{7: }|
{8:~ }|
{8:~ }|
{4:[No Name] }|
{1:^ }|
{2:~ }|
{3:[No Name] }|
|
]])
command("wincmd w")
screen:expect([[
^ |
{0:~ }|
{0:~ }|
{3:[No Name] }|
{1: }|
{2:~ }|
{4:[No Name] }|
|
]])
command("wincmd w")
command("set winhl=Normal:Background1,NormalNC:Background2")
screen:expect([[
{7: }|
{8:~ }|
{8:~ }|
{4:[No Name] }|
{1:^ }|
{2:~ }|
{3:[No Name] }|
|
]])
command("wincmd w")
screen:expect([[
^ |
{0:~ }|
{0:~ }|
{3:[No Name] }|
{5: }|
{6:~ }|
{4:[No Name] }|
|
]])
end)
it('applies also to non-text', function()
insert('Lorem ipsum dolor sit amet ')
command('set shiftwidth=2')
feed('>>')
command('set number')
command('set breakindent')
command('set briopt=shift:5,min:0')
command('set list')
command('set showbreak=↪')
screen:expect([[
{9: 1 } ^Lorem ipsum do|
{9: } {0:}lor sit |
{9: } {0:}amet{0:-} |
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
|
]])
command('set winhl=Normal:Background1')
screen:expect([[
{10: 1 }{1: ^Lorem ipsum do}|
{10: }{1: }{2:}{1:lor sit }|
{10: }{1: }{2:}{1:amet}{2:-}{1: }|
{2:~ }|
{2:~ }|
{2:~ }|
{2:~ }|
|
]])
command('set nowrap')
command('set listchars+=extends:,precedes:')
feed('3w')
screen:expect([[
{10: 1 }{2:}{1: dolor ^sit ame}{2:}|
{2:~ }|
{2:~ }|
{2:~ }|
{2:~ }|
{2:~ }|
{2:~ }|
|
]])
end)
end)