1
0
forked from aniani/vim

patch 8.2.0970: terminal properties are not available in Vim script

Problem:    Terminal properties are not available in Vim script.
Solution:   Add the terminalprops() function.
This commit is contained in:
Bram Moolenaar
2020-06-13 15:47:25 +02:00
parent 4a021dfbee
commit 0c0eddd3dd
11 changed files with 172 additions and 5 deletions

View File

@@ -2194,7 +2194,8 @@ v:termresponse The escape sequence returned by the terminal for the |t_RV|
'c', with only digits and ';' in between. 'c', with only digits and ';' in between.
When this option is set, the TermResponse autocommand event is When this option is set, the TermResponse autocommand event is
fired, so that you can react to the response from the fired, so that you can react to the response from the
terminal. terminal. You can use |terminalprops()| to see what Vim
figured out about the terminal.
The response from a new xterm is: "<Esc>[> Pp ; Pv ; Pc c". Pp The response from a new xterm is: "<Esc>[> Pp ; Pv ; Pc c". Pp
is the terminal type: 0 for vt100 and 1 for vt220. Pv is the is the terminal type: 0 for vt100 and 1 for vt220. Pv is the
patch level (since this was introduced in patch 95, it's patch level (since this was introduced in patch 95, it's
@@ -2870,6 +2871,7 @@ term_setsize({buf}, {rows}, {cols})
none set the size of a terminal none set the size of a terminal
term_start({cmd} [, {options}]) Number open a terminal window and run a job term_start({cmd} [, {options}]) Number open a terminal window and run a job
term_wait({buf} [, {time}]) Number wait for screen to be updated term_wait({buf} [, {time}]) Number wait for screen to be updated
terminalprops() Dict properties of the terminal
test_alloc_fail({id}, {countdown}, {repeat}) test_alloc_fail({id}, {countdown}, {repeat})
none make memory allocation fail none make memory allocation fail
test_autochdir() none enable 'autochdir' during startup test_autochdir() none enable 'autochdir' during startup
@@ -10390,6 +10392,41 @@ tempname() *tempname()* *temp-file-name*
term_ functions are documented here: |terminal-function-details| term_ functions are documented here: |terminal-function-details|
terminalprops() *terminalprops()*
Returns a dictionary with properties of the terminal that Vim
detected from the response to |t_RV| request. See
|v:termresponse| for the response itself. If |v:termresponse|
is empty most values here will be 'u' for unknown.
cursor_style wether sending |t_RS| works **
cursor_blink_mode wether sending |t_RC| works **
underline_rgb whether |t_8u| works **
mouse mouse type supported
** value 'u' for unknown, 'y' for yes, 'n' for no
If the |+termresponse| feature is missing then the result is
an empty dictionary.
If "cursor_style" is 'y' then |t_RS| will be send to request the
current cursor style.
If "cursor_blink_mode" is 'y' then |t_RC| will be send to
request the cursor blink status.
"cursor_style" and "cursor_blink_mode" are also set if |t_u7|
is not empty, Vim will detect the working of sending |t_RS|
and |t_RC| on startup.
When "underline_rgb" is not 'y', then |t_8u| will be made empty.
This avoids sending it to xterm, which would clear the colors.
For "mouse" the value 'u' is unknown
Also see:
- 'ambiwidth' - detected by using |t_u7|.
- |v:termstyleresp| and |v:termblinkresp| for the response to
|t_RS| and |t_RC|.
test_ functions are documented here: |test-functions-details| test_ functions are documented here: |test-functions-details|

View File

@@ -165,6 +165,8 @@ test_override({name}, {val}) *test_override()*
terminals terminals
no_wait_return set the "no_wait_return" flag. Not restored no_wait_return set the "no_wait_return" flag. Not restored
with "ALL". with "ALL".
term_props reset all terminal properties when the version
string is detected
ALL clear all overrides ({val} is not used) ALL clear all overrides ({val} is not used)
"starting" is to be used when a test should behave like "starting" is to be used when a test should behave like

View File

@@ -1148,6 +1148,7 @@ Various: *various-functions*
getimstatus() check if IME status is active getimstatus() check if IME status is active
interrupt() interrupt script execution interrupt() interrupt script execution
windowsversion() get MS-Windows version windowsversion() get MS-Windows version
terminalprops() properties of the terminal
libcall() call a function in an external library libcall() call a function in an external library
libcallnr() idem, returning a number libcallnr() idem, returning a number

View File

@@ -944,6 +944,7 @@ static funcentry_T global_functions[] =
{"term_setsize", 3, 3, FEARG_1, ret_void, TERM_FUNC(f_term_setsize)}, {"term_setsize", 3, 3, FEARG_1, ret_void, TERM_FUNC(f_term_setsize)},
{"term_start", 1, 2, FEARG_1, ret_number, TERM_FUNC(f_term_start)}, {"term_start", 1, 2, FEARG_1, ret_number, TERM_FUNC(f_term_start)},
{"term_wait", 1, 2, FEARG_1, ret_void, TERM_FUNC(f_term_wait)}, {"term_wait", 1, 2, FEARG_1, ret_void, TERM_FUNC(f_term_wait)},
{"terminalprops", 0, 0, 0, ret_dict_string, f_terminalprops},
{"test_alloc_fail", 3, 3, FEARG_1, ret_void, f_test_alloc_fail}, {"test_alloc_fail", 3, 3, FEARG_1, ret_void, f_test_alloc_fail},
{"test_autochdir", 0, 0, 0, ret_void, f_test_autochdir}, {"test_autochdir", 0, 0, 0, ret_void, f_test_autochdir},
{"test_feedinput", 1, 1, FEARG_1, ret_void, f_test_feedinput}, {"test_feedinput", 1, 1, FEARG_1, ret_void, f_test_feedinput},

View File

@@ -1839,6 +1839,7 @@ EXTERN int disable_redraw_for_testing INIT(= FALSE);
EXTERN int ignore_redraw_flag_for_testing INIT(= FALSE); EXTERN int ignore_redraw_flag_for_testing INIT(= FALSE);
EXTERN int nfa_fail_for_testing INIT(= FALSE); EXTERN int nfa_fail_for_testing INIT(= FALSE);
EXTERN int no_query_mouse_for_testing INIT(= FALSE); EXTERN int no_query_mouse_for_testing INIT(= FALSE);
EXTERN int reset_term_props_on_termresponse INIT(= FALSE);
EXTERN int in_free_unref_items INIT(= FALSE); EXTERN int in_free_unref_items INIT(= FALSE);
#endif #endif

View File

@@ -407,6 +407,10 @@ main
init_highlight(TRUE, FALSE); // set the default highlight groups init_highlight(TRUE, FALSE); // set the default highlight groups
TIME_MSG("init highlight"); TIME_MSG("init highlight");
#if defined(FEAT_TERMRESPONSE)
init_term_props(TRUE);
#endif
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
// Set the break level after the terminal is initialized. // Set the break level after the terminal is initialized.
debug_break_level = params.use_debug_break_level; debug_break_level = params.use_debug_break_level;

View File

@@ -1,6 +1,8 @@
/* term.c */ /* term.c */
guicolor_T termgui_get_color(char_u *name); guicolor_T termgui_get_color(char_u *name);
guicolor_T termgui_mch_get_rgb(guicolor_T color); guicolor_T termgui_mch_get_rgb(guicolor_T color);
void init_term_props(int all);
void f_terminalprops(typval_T *argvars, typval_T *rettv);
void set_color_count(int nr); void set_color_count(int nr);
int set_termname(char_u *term); int set_termname(char_u *term);
void getlinecol(long *cp, long *rp); void getlinecol(long *cp, long *rp);

View File

@@ -1470,7 +1470,7 @@ static termprop_T term_props[TPR_COUNT];
* When "all" is FALSE only set those that are detected from the version * When "all" is FALSE only set those that are detected from the version
* response. * response.
*/ */
static void void
init_term_props(int all) init_term_props(int all)
{ {
int i; int i;
@@ -1488,6 +1488,29 @@ init_term_props(int all)
if (all || term_props[i].tpr_set_by_termresponse) if (all || term_props[i].tpr_set_by_termresponse)
term_props[i].tpr_status = TPR_UNKNOWN; term_props[i].tpr_status = TPR_UNKNOWN;
} }
#endif
#if defined(FEAT_EVAL) || defined(PROTO)
void
f_terminalprops(typval_T *argvars UNUSED, typval_T *rettv)
{
# ifdef FEAT_TERMRESPONSE
int i;
# endif
if (rettv_dict_alloc(rettv) != OK)
return;
# ifdef FEAT_TERMRESPONSE
for (i = 0; i < TPR_COUNT; ++i)
{
char_u value[2];
value[0] = term_props[i].tpr_status;
value[1] = NUL;
dict_add_string(rettv->vval.v_dict, term_props[i].tpr_name, value);
}
# endif
}
#endif #endif
static struct builtin_term * static struct builtin_term *
@@ -3676,8 +3699,6 @@ check_terminal_behavior(void)
{ {
int did_send = FALSE; int did_send = FALSE;
init_term_props(TRUE);
if (!can_get_termresponse() || starting != 0 || *T_U7 == NUL) if (!can_get_termresponse() || starting != 0 || *T_U7 == NUL)
return; return;
@@ -4516,7 +4537,8 @@ handle_version_response(int first, int *arg, int argc, char_u *tp)
// Reset terminal properties that are set based on the termresponse. // Reset terminal properties that are set based on the termresponse.
// Mainly useful for tests that send the termresponse multiple times. // Mainly useful for tests that send the termresponse multiple times.
init_term_props(FALSE); // For testing all props can be reset.
init_term_props(reset_term_props_on_termresponse);
// If this code starts with CSI, you can bet that the // If this code starts with CSI, you can bet that the
// terminal uses 8-bit codes. // terminal uses 8-bit codes.

View File

@@ -922,6 +922,7 @@ endfunc
func Test_xx01_term_style_response() func Test_xx01_term_style_response()
" Termresponse is only parsed when t_RV is not empty. " Termresponse is only parsed when t_RV is not empty.
set t_RV=x set t_RV=x
call test_override('term_props', 1)
" send the termresponse to trigger requesting the XT codes " send the termresponse to trigger requesting the XT codes
let seq = "\<Esc>[>41;337;0c" let seq = "\<Esc>[>41;337;0c"
@@ -932,7 +933,15 @@ func Test_xx01_term_style_response()
call feedkeys(seq, 'Lx!') call feedkeys(seq, 'Lx!')
call assert_equal(seq, v:termstyleresp) call assert_equal(seq, v:termstyleresp)
call assert_equal(#{
\ cursor_style: 'u',
\ cursor_blink_mode: 'u',
\ underline_rgb: 'u',
\ mouse: 's'
\ }, terminalprops())
set t_RV= set t_RV=
call test_override('term_props', 0)
endfunc endfunc
" This checks the iTerm2 version response. " This checks the iTerm2 version response.
@@ -941,6 +950,7 @@ endfunc
func Test_xx02_iTerm2_response() func Test_xx02_iTerm2_response()
" Termresponse is only parsed when t_RV is not empty. " Termresponse is only parsed when t_RV is not empty.
set t_RV=x set t_RV=x
call test_override('term_props', 1)
" Old versions of iTerm2 used a different style term response. " Old versions of iTerm2 used a different style term response.
set ttymouse=xterm set ttymouse=xterm
@@ -957,7 +967,15 @@ func Test_xx02_iTerm2_response()
call assert_equal(seq, v:termresponse) call assert_equal(seq, v:termresponse)
call assert_equal('sgr', &ttymouse) call assert_equal('sgr', &ttymouse)
call assert_equal(#{
\ cursor_style: 'n',
\ cursor_blink_mode: 'u',
\ underline_rgb: 'u',
\ mouse: 's'
\ }, terminalprops())
set t_RV= set t_RV=
call test_override('term_props', 0)
endfunc endfunc
" This checks the libvterm version response. " This checks the libvterm version response.
@@ -966,6 +984,7 @@ endfunc
func Test_xx03_libvterm_response() func Test_xx03_libvterm_response()
" Termresponse is only parsed when t_RV is not empty. " Termresponse is only parsed when t_RV is not empty.
set t_RV=x set t_RV=x
call test_override('term_props', 1)
set ttymouse=xterm set ttymouse=xterm
call test_option_not_set('ttymouse') call test_option_not_set('ttymouse')
@@ -974,7 +993,15 @@ func Test_xx03_libvterm_response()
call assert_equal(seq, v:termresponse) call assert_equal(seq, v:termresponse)
call assert_equal('sgr', &ttymouse) call assert_equal('sgr', &ttymouse)
call assert_equal(#{
\ cursor_style: 'n',
\ cursor_blink_mode: 'u',
\ underline_rgb: 'u',
\ mouse: 's'
\ }, terminalprops())
set t_RV= set t_RV=
call test_override('term_props', 0)
endfunc endfunc
" This checks the Mac Terminal.app version response. " This checks the Mac Terminal.app version response.
@@ -983,6 +1010,7 @@ endfunc
func Test_xx04_Mac_Terminal_response() func Test_xx04_Mac_Terminal_response()
" Termresponse is only parsed when t_RV is not empty. " Termresponse is only parsed when t_RV is not empty.
set t_RV=x set t_RV=x
call test_override('term_props', 1)
set ttymouse=xterm set ttymouse=xterm
call test_option_not_set('ttymouse') call test_option_not_set('ttymouse')
@@ -991,10 +1019,18 @@ func Test_xx04_Mac_Terminal_response()
call assert_equal(seq, v:termresponse) call assert_equal(seq, v:termresponse)
call assert_equal('sgr', &ttymouse) call assert_equal('sgr', &ttymouse)
call assert_equal(#{
\ cursor_style: 'n',
\ cursor_blink_mode: 'u',
\ underline_rgb: 'y',
\ mouse: 's'
\ }, terminalprops())
" Reset is_not_xterm and is_mac_terminal. " Reset is_not_xterm and is_mac_terminal.
set t_RV= set t_RV=
set term=xterm set term=xterm
set t_RV=x set t_RV=x
call test_override('term_props', 0)
endfunc endfunc
" This checks the mintty version response. " This checks the mintty version response.
@@ -1003,6 +1039,7 @@ endfunc
func Test_xx05_mintty_response() func Test_xx05_mintty_response()
" Termresponse is only parsed when t_RV is not empty. " Termresponse is only parsed when t_RV is not empty.
set t_RV=x set t_RV=x
call test_override('term_props', 1)
set ttymouse=xterm set ttymouse=xterm
call test_option_not_set('ttymouse') call test_option_not_set('ttymouse')
@@ -1011,7 +1048,15 @@ func Test_xx05_mintty_response()
call assert_equal(seq, v:termresponse) call assert_equal(seq, v:termresponse)
call assert_equal('sgr', &ttymouse) call assert_equal('sgr', &ttymouse)
call assert_equal(#{
\ cursor_style: 'n',
\ cursor_blink_mode: 'u',
\ underline_rgb: 'y',
\ mouse: 's'
\ }, terminalprops())
set t_RV= set t_RV=
call test_override('term_props', 0)
endfunc endfunc
" This checks the screen version response. " This checks the screen version response.
@@ -1020,6 +1065,7 @@ endfunc
func Test_xx06_screen_response() func Test_xx06_screen_response()
" Termresponse is only parsed when t_RV is not empty. " Termresponse is only parsed when t_RV is not empty.
set t_RV=x set t_RV=x
call test_override('term_props', 1)
" Old versions of screen don't support SGR mouse mode. " Old versions of screen don't support SGR mouse mode.
set ttymouse=xterm set ttymouse=xterm
@@ -1037,7 +1083,15 @@ func Test_xx06_screen_response()
call assert_equal(seq, v:termresponse) call assert_equal(seq, v:termresponse)
call assert_equal('sgr', &ttymouse) call assert_equal('sgr', &ttymouse)
call assert_equal(#{
\ cursor_style: 'n',
\ cursor_blink_mode: 'n',
\ underline_rgb: 'y',
\ mouse: 's'
\ }, terminalprops())
set t_RV= set t_RV=
call test_override('term_props', 0)
endfunc endfunc
" This checks the xterm version response. " This checks the xterm version response.
@@ -1046,6 +1100,7 @@ endfunc
func Test_xx07_xterm_response() func Test_xx07_xterm_response()
" Termresponse is only parsed when t_RV is not empty. " Termresponse is only parsed when t_RV is not empty.
set t_RV=x set t_RV=x
call test_override('term_props', 1)
" Do Terminal.app first to check that is_mac_terminal is reset. " Do Terminal.app first to check that is_mac_terminal is reset.
set ttymouse=xterm set ttymouse=xterm
@@ -1066,6 +1121,13 @@ func Test_xx07_xterm_response()
call assert_equal(seq, v:termresponse) call assert_equal(seq, v:termresponse)
call assert_equal('xterm', &ttymouse) call assert_equal('xterm', &ttymouse)
call assert_equal(#{
\ cursor_style: 'n',
\ cursor_blink_mode: 'u',
\ underline_rgb: 'y',
\ mouse: 'u'
\ }, terminalprops())
" xterm >= 95 < 277 "xterm2" " xterm >= 95 < 277 "xterm2"
set ttymouse=xterm set ttymouse=xterm
call test_option_not_set('ttymouse') call test_option_not_set('ttymouse')
@@ -1074,6 +1136,13 @@ func Test_xx07_xterm_response()
call assert_equal(seq, v:termresponse) call assert_equal(seq, v:termresponse)
call assert_equal('xterm2', &ttymouse) call assert_equal('xterm2', &ttymouse)
call assert_equal(#{
\ cursor_style: 'n',
\ cursor_blink_mode: 'u',
\ underline_rgb: 'u',
\ mouse: '2'
\ }, terminalprops())
" xterm >= 277: "sgr" " xterm >= 277: "sgr"
set ttymouse=xterm set ttymouse=xterm
call test_option_not_set('ttymouse') call test_option_not_set('ttymouse')
@@ -1082,7 +1151,30 @@ func Test_xx07_xterm_response()
call assert_equal(seq, v:termresponse) call assert_equal(seq, v:termresponse)
call assert_equal('sgr', &ttymouse) call assert_equal('sgr', &ttymouse)
call assert_equal(#{
\ cursor_style: 'n',
\ cursor_blink_mode: 'u',
\ underline_rgb: 'u',
\ mouse: 's'
\ }, terminalprops())
" xterm >= 279: "sgr" and cursor_style not reset
set ttymouse=xterm
call test_option_not_set('ttymouse')
let seq = "\<Esc>[>0;279;0c"
call feedkeys(seq, 'Lx!')
call assert_equal(seq, v:termresponse)
call assert_equal('sgr', &ttymouse)
call assert_equal(#{
\ cursor_style: 'u',
\ cursor_blink_mode: 'u',
\ underline_rgb: 'u',
\ mouse: 's'
\ }, terminalprops())
set t_RV= set t_RV=
call test_override('term_props', 0)
endfunc endfunc
func Test_get_termcode() func Test_get_termcode()

View File

@@ -854,6 +854,8 @@ f_test_override(typval_T *argvars, typval_T *rettv UNUSED)
no_query_mouse_for_testing = val; no_query_mouse_for_testing = val;
else if (STRCMP(name, (char_u *)"no_wait_return") == 0) else if (STRCMP(name, (char_u *)"no_wait_return") == 0)
no_wait_return = val; no_wait_return = val;
else if (STRCMP(name, (char_u *)"term_props") == 0)
reset_term_props_on_termresponse = val;
else if (STRCMP(name, (char_u *)"ALL") == 0) else if (STRCMP(name, (char_u *)"ALL") == 0)
{ {
disable_char_avail_for_testing = FALSE; disable_char_avail_for_testing = FALSE;
@@ -861,6 +863,7 @@ f_test_override(typval_T *argvars, typval_T *rettv UNUSED)
ignore_redraw_flag_for_testing = FALSE; ignore_redraw_flag_for_testing = FALSE;
nfa_fail_for_testing = FALSE; nfa_fail_for_testing = FALSE;
no_query_mouse_for_testing = FALSE; no_query_mouse_for_testing = FALSE;
reset_term_props_on_termresponse = FALSE;
if (save_starting >= 0) if (save_starting >= 0)
{ {
starting = save_starting; starting = save_starting;

View File

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