0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 8.2.0455: cannot set the highlight group for a specific terminal

Problem:    Cannot set the highlight group for a specific terminal.
Solution:   Add the "highlight" option to term_start(). (closes #5818)
This commit is contained in:
Bram Moolenaar 2020-03-26 20:34:00 +01:00
parent 3ed9efc2b1
commit 83d4790a04
8 changed files with 194 additions and 32 deletions

View File

@ -1,4 +1,4 @@
*terminal.txt* For Vim version 8.2. Last change: 2020 Jan 30
*terminal.txt* For Vim version 8.2. Last change: 2020 Mar 26
VIM REFERENCE MANUAL by Bram Moolenaar
@ -148,7 +148,12 @@ terminal window will start with a white or black background.
To use a different color the Terminal highlight group can be used, for
example: >
hi Terminal ctermbg=lightgrey ctermfg=blue guibg=lightgrey guifg=blue
<
The highlight needs to be defined before the terminal is created. Doing it
later, or setting 'wincolor', will only have effect when the program running
in the terminal displays text or clears the terminal.
Instead of Terminal another group can be specified with the "term_highlight"
option for `term_start()`.
*g:terminal_ansi_colors*
In GUI mode or with 'termguicolors', the 16 ANSI colors used by default in new
terminal windows may be configured using the variable
@ -857,6 +862,8 @@ term_start({cmd} [, {options}]) *term_start()*
have "%d" where the buffer number goes,
e.g. "10split|buffer %d"; when not
specified "botright sbuf %d" is used
"term_highlight" highlight group to use instead of
"Terminal"
"eof_chars" Text to send after all buffer lines were
written to the terminal. When not set
CTRL-D is used on MS-Windows. For Python

View File

@ -5168,6 +5168,21 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported, int supported2)
memcpy(opt->jo_ansi_colors, rgb, sizeof(rgb));
}
# endif
else if (STRCMP(hi->hi_key, "term_highlight") == 0)
{
char_u *p;
if (!(supported2 & JO2_TERM_HIGHLIGHT))
break;
opt->jo_set2 |= JO2_TERM_HIGHLIGHT;
p = tv_get_string_buf_chk(item, opt->jo_term_highlight_buf);
if (p == NULL || *p == NUL)
{
semsg(_(e_invargval), "term_highlight");
return FAIL;
}
opt->jo_term_highlight = p;
}
else if (STRCMP(hi->hi_key, "term_api") == 0)
{
if (!(supported2 & JO2_TERM_API))

View File

@ -2071,6 +2071,7 @@ struct channel_S {
#define JO2_TTY_TYPE 0x10000 // "tty_type"
#define JO2_BUFNR 0x20000 // "bufnr"
#define JO2_TERM_API 0x40000 // "term_api"
#define JO2_TERM_HIGHLIGHT 0x80000 // "highlight"
#define JO_MODE_ALL (JO_MODE + JO_IN_MODE + JO_OUT_MODE + JO_ERR_MODE)
#define JO_CB_ALL \
@ -2143,6 +2144,8 @@ typedef struct
# if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
long_u jo_ansi_colors[16];
# endif
char_u jo_term_highlight_buf[NUMBUFLEN];
char_u *jo_term_highlight;
int jo_tty_type; // first character of "tty_type"
char_u jo_term_api_buf[NUMBUFLEN];
char_u *jo_term_api;

View File

@ -148,6 +148,8 @@ struct terminal_S {
int tl_scrollback_scrolled;
garray_T tl_scrollback_postponed;
char_u *tl_highlight_name; // replaces "Terminal"; allocated
cellattr_T tl_default_color;
linenr_T tl_top_diff_rows; // rows of top diff file or zero
@ -665,6 +667,9 @@ term_start(
else
term->tl_api = vim_strsave((char_u *)"Tapi_");
if (opt->jo_set2 & JO2_TERM_HIGHLIGHT)
term->tl_highlight_name = vim_strsave(opt->jo_term_highlight);
// System dependent: setup the vterm and maybe start the job in it.
if (argv == NULL
&& argvar->v_type == VAR_STRING
@ -1024,6 +1029,7 @@ free_unused_terminals()
if (term->tl_out_fd != NULL)
fclose(term->tl_out_fd);
#endif
vim_free(term->tl_highlight_name);
vim_free(term->tl_cursor_color);
vim_free(term);
}
@ -2215,6 +2221,17 @@ terminal_is_active()
return in_terminal_loop != NULL;
}
/*
* Return the highight group name for the terminal; "Terminal" if not set.
*/
static char_u *
term_get_highlight_name(term_T *term)
{
if (term->tl_highlight_name == NULL)
return (char_u *)"Terminal";
return term->tl_highlight_name;
}
#if defined(FEAT_GUI) || defined(PROTO)
cursorentry_T *
term_get_cursor_shape(guicolor_T *fg, guicolor_T *bg)
@ -2237,8 +2254,8 @@ term_get_cursor_shape(guicolor_T *fg, guicolor_T *bg)
entry.blinkoff = 250;
}
// The "Terminal" highlight group overrules the defaults.
id = syn_name2id((char_u *)"Terminal");
// The highlight group overrules the defaults.
id = syn_name2id(term_get_highlight_name(term));
if (id != 0)
{
syn_id2colors(id, &term_fg, &term_bg);
@ -2617,6 +2634,48 @@ may_toggle_cursor(term_T *term)
}
}
/*
* Cache "Terminal" highlight group colors.
*/
void
set_terminal_default_colors(int cterm_fg, int cterm_bg)
{
term_default_cterm_fg = cterm_fg - 1;
term_default_cterm_bg = cterm_bg - 1;
}
static int
get_default_cterm_fg(term_T *term)
{
if (term->tl_highlight_name != NULL)
{
int id = syn_name2id(term->tl_highlight_name);
int fg = -1;
int bg = -1;
if (id > 0)
syn_id2cterm_bg(id, &fg, &bg);
return fg;
}
return term_default_cterm_fg;
}
static int
get_default_cterm_bg(term_T *term)
{
if (term->tl_highlight_name != NULL)
{
int id = syn_name2id(term->tl_highlight_name);
int fg = -1;
int bg = -1;
if (id > 0)
syn_id2cterm_bg(id, &fg, &bg);
return bg;
}
return term_default_cterm_bg;
}
/*
* Reverse engineer the RGB value into a cterm color index.
* First color is 1. Return 0 if no match found (default color).
@ -2738,6 +2797,7 @@ hl2vtermAttr(int attr, cellattr_T *cell)
*/
static int
cell2attr(
term_T *term,
win_T *wp,
VTermScreenCellAttrs cellattrs,
VTermColor cellfg,
@ -2792,15 +2852,25 @@ cell2attr(
{
if (wincolor_fg >= 0)
fg = wincolor_fg + 1;
else if (term_default_cterm_fg >= 0)
fg = term_default_cterm_fg + 1;
else
{
int cterm_fg = get_default_cterm_fg(term);
if (cterm_fg >= 0)
fg = cterm_fg + 1;
}
}
if (bg == 0)
{
if (wincolor_bg >= 0)
bg = wincolor_bg + 1;
else if (term_default_cterm_bg >= 0)
bg = term_default_cterm_bg + 1;
else
{
int cterm_bg = get_default_cterm_bg(term);
if (cterm_bg >= 0)
bg = cterm_bg + 1;
}
}
}
@ -2856,7 +2926,7 @@ term_scroll_up(term_T *term, int start_row, int count)
// Set the color to clear lines with.
vterm_state_get_default_colors(vterm_obtain_state(term->tl_vterm),
&fg, &bg);
clear_attr = cell2attr(wp, attr, fg, bg);
clear_attr = cell2attr(term, wp, attr, fg, bg);
win_del_lines(wp, start_row, count, FALSE, FALSE, clear_attr);
}
}
@ -3416,6 +3486,7 @@ term_check_channel_closed_recently()
*/
static void
term_line2screenline(
term_T *term,
win_T *wp,
VTermScreen *screen,
VTermPos *pos,
@ -3484,7 +3555,7 @@ term_line2screenline(
else
ScreenLines[off] = c;
}
ScreenAttrs[off] = cell2attr(wp, cell.attrs, cell.fg, cell.bg);
ScreenAttrs[off] = cell2attr(term, wp, cell.attrs, cell.fg, cell.bg);
++pos->col;
++off;
@ -3535,7 +3606,7 @@ update_system_term(term_T *term)
{
int max_col = MIN(Columns, term->tl_cols);
term_line2screenline(NULL, screen, &pos, max_col);
term_line2screenline(term, NULL, screen, &pos, max_col);
}
else
pos.col = 0;
@ -3649,7 +3720,7 @@ term_update_window(win_T *wp)
{
int max_col = MIN(wp->w_width, term->tl_cols);
term_line2screenline(wp, screen, &pos, max_col);
term_line2screenline(term, wp, screen, &pos, max_col);
}
else
pos.col = 0;
@ -3732,7 +3803,7 @@ term_get_attr(win_T *wp, linenr_T lnum, int col)
else
cellattr = line->sb_cells + col;
}
return cell2attr(wp, cellattr->attrs, cellattr->fg, cellattr->bg);
return cell2attr(term, wp, cellattr->attrs, cellattr->fg, cellattr->bg);
}
/*
@ -3776,11 +3847,11 @@ init_default_colors(term_T *term, win_T *wp)
bg->red = bg->green = bg->blue = bgval;
fg->ansi_index = bg->ansi_index = VTERM_ANSI_INDEX_DEFAULT;
// The 'wincolor' or "Terminal" highlight group overrules the defaults.
// The 'wincolor' or the highlight group overrules the defaults.
if (wp != NULL && *wp->w_p_wcr != NUL)
id = syn_name2id(wp->w_p_wcr);
else
id = syn_name2id((char_u *)"Terminal");
id = syn_name2id(term_get_highlight_name(term));
// Use the actual color for the GUI and when 'termguicolors' is set.
#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
@ -3844,10 +3915,13 @@ init_default_colors(term_T *term, win_T *wp)
#endif
if (id != 0 && t_colors >= 16)
{
if (term_default_cterm_fg >= 0)
cterm_color2vterm(term_default_cterm_fg, fg);
if (term_default_cterm_bg >= 0)
cterm_color2vterm(term_default_cterm_bg, bg);
int cterm_fg = get_default_cterm_fg(term);
int cterm_bg = get_default_cterm_bg(term);
if (cterm_fg >= 0)
cterm_color2vterm(cterm_fg, fg);
if (cterm_bg >= 0)
cterm_color2vterm(cterm_bg, bg);
}
else
{
@ -4386,16 +4460,6 @@ set_ref_in_term(int copyID)
return abort;
}
/*
* Cache "Terminal" highlight group colors.
*/
void
set_terminal_default_colors(int cterm_fg, int cterm_bg)
{
term_default_cterm_fg = cterm_fg - 1;
term_default_cterm_bg = cterm_bg - 1;
}
/*
* Get the buffer from the first argument in "argvars".
* Returns NULL when the buffer is not for a terminal window and logs a message
@ -5745,7 +5809,7 @@ f_term_scrape(typval_T *argvars, typval_T *rettv)
bg.red, bg.green, bg.blue);
dict_add_string(dcell, "bg", rgb);
dict_add_number(dcell, "attr", cell2attr(NULL, attrs, fg, bg));
dict_add_number(dcell, "attr", cell2attr(term, NULL, attrs, fg, bg));
dict_add_number(dcell, "width", width);
++pos.col;
@ -5937,7 +6001,7 @@ f_term_start(typval_T *argvars, typval_T *rettv)
JO2_TERM_NAME + JO2_TERM_FINISH + JO2_HIDDEN + JO2_TERM_OPENCMD
+ JO2_TERM_COLS + JO2_TERM_ROWS + JO2_VERTICAL + JO2_CURWIN
+ JO2_CWD + JO2_ENV + JO2_EOF_CHARS
+ JO2_NORESTORE + JO2_TERM_KILL
+ JO2_NORESTORE + JO2_TERM_KILL + JO2_TERM_HIGHLIGHT
+ JO2_ANSI_COLORS + JO2_TTY_TYPE + JO2_TERM_API) == FAIL)
return;
@ -6861,6 +6925,8 @@ term_and_job_init(
jobopt_T *orig_opt UNUSED)
{
term->tl_arg0_cmd = NULL;
if (opt->jo_set2 & JO2_TERM_HIGHLIGHT)
term->tl_highlight_name = vim_strsave(opt->jo_term_highlight);
if (create_vterm(term, term->tl_rows, term->tl_cols) == FAIL)
return FAIL;

View File

@ -0,0 +1,15 @@
|0+0&#ffffff0| @73
|1| @73
|2| @73
|3| @73
|4| @24|╔+0#0000001#ffd7ff255|═@19|╗| +0#0000000#ffffff0@26
|5| @24|║+0#0000001#ffd7ff255|h+0#00e0003#5fd7ff255|e|l@1|o| @14|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@26
|6| @24|║+0#0000001#ffd7ff255|h+0#00e0003#5fd7ff255|e|l@1|o| @14|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@26
|7| @24|║+0#0000001#ffd7ff255> +0#00e0003#5fd7ff255@19|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@26
|8| @24|║+0#0000001#ffd7ff255| +0#00e0003#5fd7ff255@19|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@26
|9| @24|║+0#0000001#ffd7ff255| +0#00e0003#5fd7ff255@19|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@26
|1|0| @23|╚+0#0000001#ffd7ff255|═@19|╝| +0#0000000#ffffff0@26
|1@1| @72
|1|2| @72
|1|3| @72
@75

View File

@ -0,0 +1,15 @@
|0+0&#ffffff0| @73
|1| @73
|2| @73
|3| @73
|4| @24|╔+0#0000001#ffd7ff255|═@19|╗| +0#0000000#ffffff0@26
|5| @24|║+0#0000001#ffd7ff255|h+0#4040ff13#ffff4012|e|l@1|o| @14|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@26
|6| @24|║+0#0000001#ffd7ff255|h+0#4040ff13#ffff4012|e|l@1|o| @14|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@26
|7| @24|║+0#0000001#ffd7ff255> +0#4040ff13#ffff4012@19|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@26
|8| @24|║+0#0000001#ffd7ff255| +0#4040ff13#ffff4012@19|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@26
|9| @24|║+0#0000001#ffd7ff255| +0#4040ff13#ffff4012@19|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@26
|1|0| @23|╚+0#0000001#ffd7ff255|═@19|╝| +0#0000000#ffffff0@26
|1@1| @72
|1|2| @72
|1|3| @72
@75

View File

@ -2434,7 +2434,6 @@ func Test_terminal_in_popup_min_size()
let lines = [
\ 'set t_u7=',
\ 'call setline(1, range(20))',
\ 'hi PopTerm ctermbg=grey',
\ 'func OpenTerm()',
\ " let s:buf = term_start('cat Xtext', #{hidden: 1})",
\ ' let g:winid = popup_create(s:buf, #{ border: []})',
@ -2457,6 +2456,46 @@ func Test_terminal_in_popup_min_size()
call delete('XtermPopup')
endfunc
" Check a terminal in popup window with different colors
func Terminal_in_popup_colored(group_name, highlight_cmd, highlight_opt)
CheckRunVimInTerminal
CheckUnix
let lines = [
\ 'set t_u7=',
\ 'call setline(1, range(20))',
\ 'func OpenTerm()',
\ " let s:buf = term_start('cat', #{hidden: 1, "
\ .. a:highlight_opt .. "})",
\ ' let g:winid = popup_create(s:buf, #{ border: []})',
\ 'endfunc',
\ a:highlight_cmd,
\ ]
call writefile(lines, 'XtermPopup')
let buf = RunVimInTerminal('-S XtermPopup', #{rows: 15})
call term_wait(buf, 200)
call term_sendkeys(buf, ":set noruler\<CR>")
call term_sendkeys(buf, ":call OpenTerm()\<CR>")
call term_wait(buf, 100)
call term_sendkeys(buf, "hello\<CR>")
call VerifyScreenDump(buf, 'Test_terminal_popup_' .. a:group_name, {})
call term_sendkeys(buf, "\<C-D>")
call term_wait(buf, 100)
call term_sendkeys(buf, ":q\<CR>")
call term_wait(buf, 100) " wait for terminal to vanish
call StopVimInTerminal(buf)
call delete('XtermPopup')
endfunc
func Test_terminal_in_popup_colored_Terminal()
call Terminal_in_popup_colored("Terminal", "highlight Terminal ctermfg=blue ctermbg=yellow", "")
endfunc
func Test_terminal_in_popup_colored_group()
call Terminal_in_popup_colored("MyTermCol", "highlight MyTermCol ctermfg=darkgreen ctermbg=lightblue", "term_highlight: 'MyTermCol',")
endfunc
func Test_double_popup_terminal()
let buf1 = term_start(&shell, #{hidden: 1})
let win1 = popup_create(buf1, {})

View File

@ -738,6 +738,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
455,
/**/
454,
/**/