To: vim_dev@googlegroups.com Subject: Patch 8.2.0455 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0455 Problem: Cannot set the highlight group for a specific terminal. Solution: Add the "highlight" option to term_start(). (closes #5818) Files: src/terminal.c, src/structs.h, src/channel.c, src/testdir/test_terminal.vim, runtime/doc/terminal.txt, src/testdir/dumps/Test_terminal_popup_Terminal.dump, src/testdir/dumps/Test_terminal_popup_MyTermCol.dump *** ../vim-8.2.0454/src/terminal.c 2020-03-22 19:25:46.235919583 +0100 --- src/terminal.c 2020-03-26 20:01:37.125924367 +0100 *************** *** 148,153 **** --- 148,155 ---- 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,670 **** --- 667,675 ---- 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,1029 **** --- 1029,1035 ---- 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,2220 **** --- 2221,2237 ---- 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,2244 **** entry.blinkoff = 250; } ! // The "Terminal" highlight group overrules the defaults. ! id = syn_name2id((char_u *)"Terminal"); if (id != 0) { syn_id2colors(id, &term_fg, &term_bg); --- 2254,2261 ---- entry.blinkoff = 250; } ! // The highlight group overrules the defaults. ! id = syn_name2id(term_get_highlight_name(term)); if (id != 0) { syn_id2colors(id, &term_fg, &term_bg); *************** *** 2618,2623 **** --- 2635,2682 ---- } /* + * 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,2743 **** --- 2797,2803 ---- */ static int cell2attr( + term_T *term, win_T *wp, VTermScreenCellAttrs cellattrs, VTermColor cellfg, *************** *** 2792,2806 **** { if (wincolor_fg >= 0) fg = wincolor_fg + 1; ! else if (term_default_cterm_fg >= 0) ! fg = term_default_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; } } --- 2852,2876 ---- { if (wincolor_fg >= 0) fg = wincolor_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 ! { ! int cterm_bg = get_default_cterm_bg(term); ! ! if (cterm_bg >= 0) ! bg = cterm_bg + 1; ! } } } *************** *** 2856,2862 **** // 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); win_del_lines(wp, start_row, count, FALSE, FALSE, clear_attr); } } --- 2926,2932 ---- // Set the color to clear lines with. vterm_state_get_default_colors(vterm_obtain_state(term->tl_vterm), &fg, &bg); ! clear_attr = cell2attr(term, wp, attr, fg, bg); win_del_lines(wp, start_row, count, FALSE, FALSE, clear_attr); } } *************** *** 3416,3421 **** --- 3486,3492 ---- */ static void term_line2screenline( + term_T *term, win_T *wp, VTermScreen *screen, VTermPos *pos, *************** *** 3484,3490 **** else ScreenLines[off] = c; } ! ScreenAttrs[off] = cell2attr(wp, cell.attrs, cell.fg, cell.bg); ++pos->col; ++off; --- 3555,3561 ---- else ScreenLines[off] = c; } ! ScreenAttrs[off] = cell2attr(term, wp, cell.attrs, cell.fg, cell.bg); ++pos->col; ++off; *************** *** 3535,3541 **** { int max_col = MIN(Columns, term->tl_cols); ! term_line2screenline(NULL, screen, &pos, max_col); } else pos.col = 0; --- 3606,3612 ---- { int max_col = MIN(Columns, term->tl_cols); ! term_line2screenline(term, NULL, screen, &pos, max_col); } else pos.col = 0; *************** *** 3649,3655 **** { int max_col = MIN(wp->w_width, term->tl_cols); ! term_line2screenline(wp, screen, &pos, max_col); } else pos.col = 0; --- 3720,3726 ---- { int max_col = MIN(wp->w_width, term->tl_cols); ! term_line2screenline(term, wp, screen, &pos, max_col); } else pos.col = 0; *************** *** 3732,3738 **** else cellattr = line->sb_cells + col; } ! return cell2attr(wp, cellattr->attrs, cellattr->fg, cellattr->bg); } /* --- 3803,3809 ---- else cellattr = line->sb_cells + col; } ! return cell2attr(term, wp, cellattr->attrs, cellattr->fg, cellattr->bg); } /* *************** *** 3776,3786 **** 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. if (wp != NULL && *wp->w_p_wcr != NUL) id = syn_name2id(wp->w_p_wcr); else ! id = syn_name2id((char_u *)"Terminal"); // Use the actual color for the GUI and when 'termguicolors' is set. #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) --- 3847,3857 ---- bg->red = bg->green = bg->blue = bgval; fg->ansi_index = bg->ansi_index = VTERM_ANSI_INDEX_DEFAULT; ! // 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(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,3853 **** #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); } else { --- 3915,3927 ---- #endif if (id != 0 && t_colors >= 16) { ! 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 { *************** *** 4387,4402 **** } /* - * 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 * with "where". --- 4461,4466 ---- *************** *** 5745,5751 **** 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, "width", width); ++pos.col; --- 5809,5815 ---- bg.red, bg.green, bg.blue); dict_add_string(dcell, "bg", rgb); ! dict_add_number(dcell, "attr", cell2attr(term, NULL, attrs, fg, bg)); dict_add_number(dcell, "width", width); ++pos.col; *************** *** 5937,5943 **** 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_ANSI_COLORS + JO2_TTY_TYPE + JO2_TERM_API) == FAIL) return; --- 6001,6007 ---- 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_TERM_HIGHLIGHT + JO2_ANSI_COLORS + JO2_TTY_TYPE + JO2_TERM_API) == FAIL) return; *************** *** 6861,6866 **** --- 6925,6932 ---- 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; *** ../vim-8.2.0454/src/structs.h 2020-03-20 18:39:42.981273170 +0100 --- src/structs.h 2020-03-26 18:15:45.482442176 +0100 *************** *** 2071,2076 **** --- 2071,2077 ---- #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,2148 **** --- 2144,2151 ---- # 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; *** ../vim-8.2.0454/src/channel.c 2020-03-26 16:03:41.574559657 +0100 --- src/channel.c 2020-03-26 19:13:25.651085391 +0100 *************** *** 5168,5173 **** --- 5168,5188 ---- 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)) *** ../vim-8.2.0454/src/testdir/test_terminal.vim 2020-03-25 21:27:19.278387463 +0100 --- src/testdir/test_terminal.vim 2020-03-26 19:54:05.719692855 +0100 *************** *** 2434,2440 **** 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: []})', --- 2434,2439 ---- *************** *** 2457,2462 **** --- 2456,2501 ---- 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\") + call term_sendkeys(buf, ":call OpenTerm()\") + call term_wait(buf, 100) + call term_sendkeys(buf, "hello\") + call VerifyScreenDump(buf, 'Test_terminal_popup_' .. a:group_name, {}) + + call term_sendkeys(buf, "\") + call term_wait(buf, 100) + call term_sendkeys(buf, ":q\") + 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, {}) *** ../vim-8.2.0454/runtime/doc/terminal.txt 2019-12-12 12:49:06.000000000 +0100 --- runtime/doc/terminal.txt 2020-03-26 20:32:19.939155449 +0100 *************** *** 148,154 **** To use a different color the Terminal highlight group can be used, for example: > hi Terminal ctermbg=lightgrey ctermfg=blue guibg=lightgrey guifg=blue ! < *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 --- 148,159 ---- 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 *************** *** 641,648 **** term_getstatus({buf}) *term_getstatus()* ! Get the status of terminal {buf}. This returns a comma ! separated list of these items: running job is running finished job has finished normal in Terminal-Normal mode --- 646,653 ---- term_getstatus({buf}) *term_getstatus()* ! Get the status of terminal {buf}. This returns a String with ! a comma separated list of these items: running job is running finished job has finished normal in Terminal-Normal mode *************** *** 857,862 **** --- 862,869 ---- 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 *************** *** 1025,1031 **** For an example see the Test_syntax_c() function in src/testdir/test_syntax.vim. The main parts are: - Write a file you want to test with. This is useful for testing syntax ! highlighting. You can also start Vim with en empty buffer. - Run Vim in a terminal with a specific size. The default is 20 lines of 75 characters. This makes sure the dump is always this size. The function RunVimInTerminal() takes care of this. Pass it the arguments for the Vim --- 1032,1038 ---- For an example see the Test_syntax_c() function in src/testdir/test_syntax.vim. The main parts are: - Write a file you want to test with. This is useful for testing syntax ! highlighting. You can also start Vim with an empty buffer. - Run Vim in a terminal with a specific size. The default is 20 lines of 75 characters. This makes sure the dump is always this size. The function RunVimInTerminal() takes care of this. Pass it the arguments for the Vim *** ../vim-8.2.0454/src/testdir/dumps/Test_terminal_popup_Terminal.dump 2020-03-26 20:29:57.087613443 +0100 --- src/testdir/dumps/Test_terminal_popup_Terminal.dump 2020-03-26 19:44:32.989521515 +0100 *************** *** 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 *** ../vim-8.2.0454/src/testdir/dumps/Test_terminal_popup_MyTermCol.dump 2020-03-26 20:29:57.091613429 +0100 --- src/testdir/dumps/Test_terminal_popup_MyTermCol.dump 2020-03-26 20:01:57.821834179 +0100 *************** *** 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 *** ../vim-8.2.0454/src/version.c 2020-03-26 16:50:53.413148743 +0100 --- src/version.c 2020-03-26 20:29:18.079748972 +0100 *************** *** 740,741 **** --- 740,743 ---- { /* Add new patch number below this line */ + /**/ + 455, /**/ -- Seen on the back of a biker's vest: If you can read this, my wife fell off. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///