options: allow different highlights in windows

This commit is contained in:
Björn Linse 2017-04-26 18:17:29 +02:00
parent 443399c27d
commit bfcaf36404
10 changed files with 143 additions and 24 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:
|hl-SpecialKey| 8 Meta and special keys listed with ":map"
|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 inactive (not the current) window
|hl-TermCursor| z Cursor in a focused terminal
|hl-TermCursorNC| Z Cursor in an unfocused terminal
|hl-NonText| @ '@' at the end of the window and

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|.
*hl-Normal*
Normal normal text
*hl-NormalNC*
NormalNC normal text in non-current window
*hl-Pmenu*
Pmenu Popup menu: normal item.
*hl-PmenuSel*

View File

@ -233,6 +233,8 @@ typedef struct {
# define w_p_crb_save w_onebuf_opt.wo_crb_save
char_u *wo_scl;
# 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 */
# define w_p_scriptID w_onebuf_opt.wo_scriptID
@ -930,6 +932,10 @@ struct window_S {
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_next; /* link to next window */
bool w_closing; /* window is being closed, don't let

View File

@ -465,6 +465,7 @@ typedef enum {
, HLF_MC // 'colorcolumn'
, HLF_QFL // selected quickfix line
, HLF_0 // Whitespace
, HLF_INACTIVE // Inactive window
, HLF_COUNT // MUST be the last one
} hlf_T;
@ -473,7 +474,7 @@ typedef enum {
#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', \
'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_user[9]; /* User[1-9] attributes */

View File

@ -252,7 +252,7 @@ typedef struct vimoption {
"B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel," \
"x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill," \
"!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine," \
"0:Whitespace"
"0:Whitespace,I:NormalNC"
/*
* options[] is initialized here.
@ -3174,6 +3174,10 @@ did_set_string_option (
if (!valid_filetype(*varp)) {
errmsg = e_invarg;
}
} else if (varp == &curwin->w_p_winhl) {
if (!parse_winhl_opt(curwin)) {
errmsg = e_invarg;
}
} else {
// Options that are a list of flags.
p = NULL;
@ -3582,6 +3586,38 @@ static char_u *compile_cap_prog(synblock_T *synblock)
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
* window-local value.
@ -5491,6 +5527,7 @@ static char_u *get_varp(vimoption_T *p)
case PV_WM: return (char_u *)&(curbuf->b_p_wm);
case PV_KMAP: return (char_u *)&(curbuf->b_p_keymap);
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"));
}
/* always return a valid pointer to avoid a crash! */
@ -5568,6 +5605,7 @@ void copy_winopt(winopt_T *from, winopt_T *to)
to->wo_fdt = vim_strsave(from->wo_fdt);
to->wo_fmr = vim_strsave(from->wo_fmr);
to->wo_scl = vim_strsave(from->wo_scl);
to->wo_winhl = vim_strsave(from->wo_winhl);
check_winopt(to); // don't want NULL pointers
}
@ -5597,6 +5635,7 @@ static void check_winopt(winopt_T *wop)
check_string_option(&wop->wo_cc);
check_string_option(&wop->wo_cocu);
check_string_option(&wop->wo_briopt);
check_string_option(&wop->wo_winhl);
}
/*
@ -5616,12 +5655,14 @@ void clear_winopt(winopt_T *wop)
clear_string_option(&wop->wo_cc);
clear_string_option(&wop->wo_cocu);
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);
}

View File

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

View File

@ -2701,6 +2701,14 @@ return {
varname='p_wak',
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',
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
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) {
// No check for cmdline window: should never be right-left.
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,
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,
W_ENDCOL(wp) - 1 - FDC_OFF, W_ENDCOL(wp) - FDC_OFF,
c1, c2, hl_attr(hl));
c1, c2, attr);
} else {
if (cmdwin_type != 0 && wp == curwin) {
/* 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,
wp->w_wincol + FDC_OFF, W_ENDCOL(wp),
c1, c2, hl_attr(hl));
c1, c2, attr);
}
set_empty_rows(wp, row);
}
@ -2418,6 +2423,10 @@ win_line (
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) {
area_highlighting = true;
}
@ -2849,6 +2858,10 @@ win_line (
} else
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 */
@ -3083,10 +3096,14 @@ win_line (
mb_l = 1;
mb_utf8 = FALSE;
multi_attr = hl_attr(HLF_AT);
/* put the pointer back to output the double-width
* character at the start of the next line. */
++n_extra;
--p_extra;
if (wp->w_hl_attr != 0) {
multi_attr = hl_combine_attr(wp->w_hl_attr, multi_attr);
}
// put the pointer back to output the double-width
// character at the start of the next line.
n_extra++;
p_extra--;
} else {
n_extra -= mb_l - 1;
p_extra += mb_l - 1;
@ -3221,11 +3238,15 @@ win_line (
mb_utf8 = FALSE;
mb_l = 1;
multi_attr = hl_attr(HLF_AT);
/* Put pointer back so that the character will be
* displayed at the start of the next line. */
--ptr;
} else if (*ptr != NUL)
if (wp->w_hl_attr != 0) {
multi_attr = hl_combine_attr(wp->w_hl_attr, multi_attr);
}
// 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;
}
/* If a double-width char doesn't fit at the left side display
* 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
}
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;
}
@ -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;
if (wp->w_p_rl) {
--col;
@ -3897,6 +3925,14 @@ win_line (
if (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) {
ScreenLines[off] = ' ';
if (enc_utf8)
@ -3906,12 +3942,13 @@ win_line (
draw_color_col = advance_color_col(VCOL_HLC,
&color_cols);
if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol)
ScreenAttrs[off++] = hl_attr(HLF_CUC);
else if (draw_color_col && VCOL_HLC == *color_cols)
ScreenAttrs[off++] = hl_attr(HLF_MC);
else
ScreenAttrs[off++] = 0;
if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol) {
ScreenAttrs[off++] = cuc_attr;
} else if (draw_color_col && VCOL_HLC == *color_cols) {
ScreenAttrs[off++] = mc_attr;
} else {
ScreenAttrs[off++] = wp->w_hl_attr;
}
if (VCOL_HLC >= rightmost_vcol)
break;
@ -3920,6 +3957,7 @@ win_line (
}
}
// TODO(bfredl): integrate with the common beyond-the-end-loop
if (wp->w_buffer->terminal) {
// terminal buffers may need to highlight beyond the end of the
// logical line
@ -3961,6 +3999,9 @@ win_line (
|| (n_extra && (c_extra != NUL || *p_extra != NUL)))) {
c = lcs_ext;
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;
if (enc_utf8 && (*mb_char2len)(c) > 1) {
mb_utf8 = TRUE;
@ -5510,7 +5551,19 @@ static void init_search_hl(win_T *wp)
search_hl.buf = wp->w_buffer;
search_hl.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

@ -3722,6 +3722,12 @@ static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid,
if (restart_edit)
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 */
if (curwin->w_height < p_wh && !curwin->w_p_wfh)
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.blinkwait then m.blinkwait = 700 end
end
if m.hl_id then m.hl_id = 46 end
if m.id_lm then m.id_lm = 47 end
if m.hl_id then m.hl_id = 47 end
if m.id_lm then m.id_lm = 48 end
end
-- Assert the new expectation.