Skip to content

Commit 0c0eddd

Browse files
committed
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.
1 parent 4a021df commit 0c0eddd

File tree

11 files changed

+172
-5
lines changed

11 files changed

+172
-5
lines changed

runtime/doc/eval.txt

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2194,7 +2194,8 @@ v:termresponse The escape sequence returned by the terminal for the |t_RV|
21942194
'c', with only digits and ';' in between.
21952195
When this option is set, the TermResponse autocommand event is
21962196
fired, so that you can react to the response from the
2197-
terminal.
2197+
terminal. You can use |terminalprops()| to see what Vim
2198+
figured out about the terminal.
21982199
The response from a new xterm is: "<Esc>[> Pp ; Pv ; Pc c". Pp
21992200
is the terminal type: 0 for vt100 and 1 for vt220. Pv is the
22002201
patch level (since this was introduced in patch 95, it's
@@ -2870,6 +2871,7 @@ term_setsize({buf}, {rows}, {cols})
28702871
none set the size of a terminal
28712872
term_start({cmd} [, {options}]) Number open a terminal window and run a job
28722873
term_wait({buf} [, {time}]) Number wait for screen to be updated
2874+
terminalprops() Dict properties of the terminal
28732875
test_alloc_fail({id}, {countdown}, {repeat})
28742876
none make memory allocation fail
28752877
test_autochdir() none enable 'autochdir' during startup
@@ -10390,6 +10392,41 @@ tempname() *tempname()* *temp-file-name*
1039010392

1039110393
term_ functions are documented here: |terminal-function-details|
1039210394

10395+
10396+
terminalprops() *terminalprops()*
10397+
Returns a dictionary with properties of the terminal that Vim
10398+
detected from the response to |t_RV| request. See
10399+
|v:termresponse| for the response itself. If |v:termresponse|
10400+
is empty most values here will be 'u' for unknown.
10401+
cursor_style wether sending |t_RS| works **
10402+
cursor_blink_mode wether sending |t_RC| works **
10403+
underline_rgb whether |t_8u| works **
10404+
mouse mouse type supported
10405+
10406+
** value 'u' for unknown, 'y' for yes, 'n' for no
10407+
10408+
If the |+termresponse| feature is missing then the result is
10409+
an empty dictionary.
10410+
10411+
If "cursor_style" is 'y' then |t_RS| will be send to request the
10412+
current cursor style.
10413+
If "cursor_blink_mode" is 'y' then |t_RC| will be send to
10414+
request the cursor blink status.
10415+
"cursor_style" and "cursor_blink_mode" are also set if |t_u7|
10416+
is not empty, Vim will detect the working of sending |t_RS|
10417+
and |t_RC| on startup.
10418+
10419+
When "underline_rgb" is not 'y', then |t_8u| will be made empty.
10420+
This avoids sending it to xterm, which would clear the colors.
10421+
10422+
For "mouse" the value 'u' is unknown
10423+
10424+
Also see:
10425+
- 'ambiwidth' - detected by using |t_u7|.
10426+
- |v:termstyleresp| and |v:termblinkresp| for the response to
10427+
|t_RS| and |t_RC|.
10428+
10429+
1039310430
test_ functions are documented here: |test-functions-details|
1039410431

1039510432

runtime/doc/testing.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ test_override({name}, {val}) *test_override()*
165165
terminals
166166
no_wait_return set the "no_wait_return" flag. Not restored
167167
with "ALL".
168+
term_props reset all terminal properties when the version
169+
string is detected
168170
ALL clear all overrides ({val} is not used)
169171

170172
"starting" is to be used when a test should behave like

runtime/doc/usr_41.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,7 @@ Various: *various-functions*
11481148
getimstatus() check if IME status is active
11491149
interrupt() interrupt script execution
11501150
windowsversion() get MS-Windows version
1151+
terminalprops() properties of the terminal
11511152

11521153
libcall() call a function in an external library
11531154
libcallnr() idem, returning a number

src/evalfunc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,7 @@ static funcentry_T global_functions[] =
944944
{"term_setsize", 3, 3, FEARG_1, ret_void, TERM_FUNC(f_term_setsize)},
945945
{"term_start", 1, 2, FEARG_1, ret_number, TERM_FUNC(f_term_start)},
946946
{"term_wait", 1, 2, FEARG_1, ret_void, TERM_FUNC(f_term_wait)},
947+
{"terminalprops", 0, 0, 0, ret_dict_string, f_terminalprops},
947948
{"test_alloc_fail", 3, 3, FEARG_1, ret_void, f_test_alloc_fail},
948949
{"test_autochdir", 0, 0, 0, ret_void, f_test_autochdir},
949950
{"test_feedinput", 1, 1, FEARG_1, ret_void, f_test_feedinput},

src/globals.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1839,6 +1839,7 @@ EXTERN int disable_redraw_for_testing INIT(= FALSE);
18391839
EXTERN int ignore_redraw_flag_for_testing INIT(= FALSE);
18401840
EXTERN int nfa_fail_for_testing INIT(= FALSE);
18411841
EXTERN int no_query_mouse_for_testing INIT(= FALSE);
1842+
EXTERN int reset_term_props_on_termresponse INIT(= FALSE);
18421843

18431844
EXTERN int in_free_unref_items INIT(= FALSE);
18441845
#endif

src/main.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,10 @@ main
407407
init_highlight(TRUE, FALSE); // set the default highlight groups
408408
TIME_MSG("init highlight");
409409

410+
#if defined(FEAT_TERMRESPONSE)
411+
init_term_props(TRUE);
412+
#endif
413+
410414
#ifdef FEAT_EVAL
411415
// Set the break level after the terminal is initialized.
412416
debug_break_level = params.use_debug_break_level;

src/proto/term.pro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/* term.c */
22
guicolor_T termgui_get_color(char_u *name);
33
guicolor_T termgui_mch_get_rgb(guicolor_T color);
4+
void init_term_props(int all);
5+
void f_terminalprops(typval_T *argvars, typval_T *rettv);
46
void set_color_count(int nr);
57
int set_termname(char_u *term);
68
void getlinecol(long *cp, long *rp);

src/term.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,7 +1470,7 @@ static termprop_T term_props[TPR_COUNT];
14701470
* When "all" is FALSE only set those that are detected from the version
14711471
* response.
14721472
*/
1473-
static void
1473+
void
14741474
init_term_props(int all)
14751475
{
14761476
int i;
@@ -1488,6 +1488,29 @@ init_term_props(int all)
14881488
if (all || term_props[i].tpr_set_by_termresponse)
14891489
term_props[i].tpr_status = TPR_UNKNOWN;
14901490
}
1491+
#endif
1492+
1493+
#if defined(FEAT_EVAL) || defined(PROTO)
1494+
void
1495+
f_terminalprops(typval_T *argvars UNUSED, typval_T *rettv)
1496+
{
1497+
# ifdef FEAT_TERMRESPONSE
1498+
int i;
1499+
# endif
1500+
1501+
if (rettv_dict_alloc(rettv) != OK)
1502+
return;
1503+
# ifdef FEAT_TERMRESPONSE
1504+
for (i = 0; i < TPR_COUNT; ++i)
1505+
{
1506+
char_u value[2];
1507+
1508+
value[0] = term_props[i].tpr_status;
1509+
value[1] = NUL;
1510+
dict_add_string(rettv->vval.v_dict, term_props[i].tpr_name, value);
1511+
}
1512+
# endif
1513+
}
14911514
#endif
14921515

14931516
static struct builtin_term *
@@ -3676,8 +3699,6 @@ check_terminal_behavior(void)
36763699
{
36773700
int did_send = FALSE;
36783701

3679-
init_term_props(TRUE);
3680-
36813702
if (!can_get_termresponse() || starting != 0 || *T_U7 == NUL)
36823703
return;
36833704

@@ -4516,7 +4537,8 @@ handle_version_response(int first, int *arg, int argc, char_u *tp)
45164537

45174538
// Reset terminal properties that are set based on the termresponse.
45184539
// Mainly useful for tests that send the termresponse multiple times.
4519-
init_term_props(FALSE);
4540+
// For testing all props can be reset.
4541+
init_term_props(reset_term_props_on_termresponse);
45204542

45214543
// If this code starts with CSI, you can bet that the
45224544
// terminal uses 8-bit codes.

src/testdir/test_termcodes.vim

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -922,6 +922,7 @@ endfunc
922922
func Test_xx01_term_style_response()
923923
" Termresponse is only parsed when t_RV is not empty.
924924
set t_RV=x
925+
call test_override('term_props', 1)
925926

926927
" send the termresponse to trigger requesting the XT codes
927928
let seq = "\<Esc>[>41;337;0c"
@@ -932,7 +933,15 @@ func Test_xx01_term_style_response()
932933
call feedkeys(seq, 'Lx!')
933934
call assert_equal(seq, v:termstyleresp)
934935

936+
call assert_equal(#{
937+
\ cursor_style: 'u',
938+
\ cursor_blink_mode: 'u',
939+
\ underline_rgb: 'u',
940+
\ mouse: 's'
941+
\ }, terminalprops())
942+
935943
set t_RV=
944+
call test_override('term_props', 0)
936945
endfunc
937946

938947
" This checks the iTerm2 version response.
@@ -941,6 +950,7 @@ endfunc
941950
func Test_xx02_iTerm2_response()
942951
" Termresponse is only parsed when t_RV is not empty.
943952
set t_RV=x
953+
call test_override('term_props', 1)
944954

945955
" Old versions of iTerm2 used a different style term response.
946956
set ttymouse=xterm
@@ -957,7 +967,15 @@ func Test_xx02_iTerm2_response()
957967
call assert_equal(seq, v:termresponse)
958968
call assert_equal('sgr', &ttymouse)
959969

970+
call assert_equal(#{
971+
\ cursor_style: 'n',
972+
\ cursor_blink_mode: 'u',
973+
\ underline_rgb: 'u',
974+
\ mouse: 's'
975+
\ }, terminalprops())
976+
960977
set t_RV=
978+
call test_override('term_props', 0)
961979
endfunc
962980

963981
" This checks the libvterm version response.
@@ -966,6 +984,7 @@ endfunc
966984
func Test_xx03_libvterm_response()
967985
" Termresponse is only parsed when t_RV is not empty.
968986
set t_RV=x
987+
call test_override('term_props', 1)
969988

970989
set ttymouse=xterm
971990
call test_option_not_set('ttymouse')
@@ -974,7 +993,15 @@ func Test_xx03_libvterm_response()
974993
call assert_equal(seq, v:termresponse)
975994
call assert_equal('sgr', &ttymouse)
976995

996+
call assert_equal(#{
997+
\ cursor_style: 'n',
998+
\ cursor_blink_mode: 'u',
999+
\ underline_rgb: 'u',
1000+
\ mouse: 's'
1001+
\ }, terminalprops())
1002+
9771003
set t_RV=
1004+
call test_override('term_props', 0)
9781005
endfunc
9791006

9801007
" This checks the Mac Terminal.app version response.
@@ -983,6 +1010,7 @@ endfunc
9831010
func Test_xx04_Mac_Terminal_response()
9841011
" Termresponse is only parsed when t_RV is not empty.
9851012
set t_RV=x
1013+
call test_override('term_props', 1)
9861014

9871015
set ttymouse=xterm
9881016
call test_option_not_set('ttymouse')
@@ -991,10 +1019,18 @@ func Test_xx04_Mac_Terminal_response()
9911019
call assert_equal(seq, v:termresponse)
9921020
call assert_equal('sgr', &ttymouse)
9931021

1022+
call assert_equal(#{
1023+
\ cursor_style: 'n',
1024+
\ cursor_blink_mode: 'u',
1025+
\ underline_rgb: 'y',
1026+
\ mouse: 's'
1027+
\ }, terminalprops())
1028+
9941029
" Reset is_not_xterm and is_mac_terminal.
9951030
set t_RV=
9961031
set term=xterm
9971032
set t_RV=x
1033+
call test_override('term_props', 0)
9981034
endfunc
9991035

10001036
" This checks the mintty version response.
@@ -1003,6 +1039,7 @@ endfunc
10031039
func Test_xx05_mintty_response()
10041040
" Termresponse is only parsed when t_RV is not empty.
10051041
set t_RV=x
1042+
call test_override('term_props', 1)
10061043

10071044
set ttymouse=xterm
10081045
call test_option_not_set('ttymouse')
@@ -1011,7 +1048,15 @@ func Test_xx05_mintty_response()
10111048
call assert_equal(seq, v:termresponse)
10121049
call assert_equal('sgr', &ttymouse)
10131050

1051+
call assert_equal(#{
1052+
\ cursor_style: 'n',
1053+
\ cursor_blink_mode: 'u',
1054+
\ underline_rgb: 'y',
1055+
\ mouse: 's'
1056+
\ }, terminalprops())
1057+
10141058
set t_RV=
1059+
call test_override('term_props', 0)
10151060
endfunc
10161061

10171062
" This checks the screen version response.
@@ -1020,6 +1065,7 @@ endfunc
10201065
func Test_xx06_screen_response()
10211066
" Termresponse is only parsed when t_RV is not empty.
10221067
set t_RV=x
1068+
call test_override('term_props', 1)
10231069

10241070
" Old versions of screen don't support SGR mouse mode.
10251071
set ttymouse=xterm
@@ -1037,7 +1083,15 @@ func Test_xx06_screen_response()
10371083
call assert_equal(seq, v:termresponse)
10381084
call assert_equal('sgr', &ttymouse)
10391085

1086+
call assert_equal(#{
1087+
\ cursor_style: 'n',
1088+
\ cursor_blink_mode: 'n',
1089+
\ underline_rgb: 'y',
1090+
\ mouse: 's'
1091+
\ }, terminalprops())
1092+
10401093
set t_RV=
1094+
call test_override('term_props', 0)
10411095
endfunc
10421096

10431097
" This checks the xterm version response.
@@ -1046,6 +1100,7 @@ endfunc
10461100
func Test_xx07_xterm_response()
10471101
" Termresponse is only parsed when t_RV is not empty.
10481102
set t_RV=x
1103+
call test_override('term_props', 1)
10491104

10501105
" Do Terminal.app first to check that is_mac_terminal is reset.
10511106
set ttymouse=xterm
@@ -1066,6 +1121,13 @@ func Test_xx07_xterm_response()
10661121
call assert_equal(seq, v:termresponse)
10671122
call assert_equal('xterm', &ttymouse)
10681123

1124+
call assert_equal(#{
1125+
\ cursor_style: 'n',
1126+
\ cursor_blink_mode: 'u',
1127+
\ underline_rgb: 'y',
1128+
\ mouse: 'u'
1129+
\ }, terminalprops())
1130+
10691131
" xterm >= 95 < 277 "xterm2"
10701132
set ttymouse=xterm
10711133
call test_option_not_set('ttymouse')
@@ -1074,6 +1136,13 @@ func Test_xx07_xterm_response()
10741136
call assert_equal(seq, v:termresponse)
10751137
call assert_equal('xterm2', &ttymouse)
10761138

1139+
call assert_equal(#{
1140+
\ cursor_style: 'n',
1141+
\ cursor_blink_mode: 'u',
1142+
\ underline_rgb: 'u',
1143+
\ mouse: '2'
1144+
\ }, terminalprops())
1145+
10771146
" xterm >= 277: "sgr"
10781147
set ttymouse=xterm
10791148
call test_option_not_set('ttymouse')
@@ -1082,7 +1151,30 @@ func Test_xx07_xterm_response()
10821151
call assert_equal(seq, v:termresponse)
10831152
call assert_equal('sgr', &ttymouse)
10841153

1154+
call assert_equal(#{
1155+
\ cursor_style: 'n',
1156+
\ cursor_blink_mode: 'u',
1157+
\ underline_rgb: 'u',
1158+
\ mouse: 's'
1159+
\ }, terminalprops())
1160+
1161+
" xterm >= 279: "sgr" and cursor_style not reset
1162+
set ttymouse=xterm
1163+
call test_option_not_set('ttymouse')
1164+
let seq = "\<Esc>[>0;279;0c"
1165+
call feedkeys(seq, 'Lx!')
1166+
call assert_equal(seq, v:termresponse)
1167+
call assert_equal('sgr', &ttymouse)
1168+
1169+
call assert_equal(#{
1170+
\ cursor_style: 'u',
1171+
\ cursor_blink_mode: 'u',
1172+
\ underline_rgb: 'u',
1173+
\ mouse: 's'
1174+
\ }, terminalprops())
1175+
10851176
set t_RV=
1177+
call test_override('term_props', 0)
10861178
endfunc
10871179

10881180
func Test_get_termcode()

0 commit comments

Comments
 (0)