To: vim_dev@googlegroups.com Subject: Patch 8.2.0970 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0970 Problem: Terminal properties are not available in Vim script. Solution: Add the terminalprops() function. Files: src/term.c, src/proto/term.pro, src/evalfunc.c, src/main.c, src/testing.c, src/globals.h, src/testdir/test_termcodes.vim, runtime/doc/usr_41.txt, runtime/doc/eval.txt, runtime/doc/testing.txt *** ../vim-8.2.0969/src/term.c 2020-06-12 22:59:07.270097188 +0200 --- src/term.c 2020-06-13 15:33:24.465690574 +0200 *************** *** 1470,1476 **** * When "all" is FALSE only set those that are detected from the version * response. */ ! static void init_term_props(int all) { int i; --- 1470,1476 ---- * When "all" is FALSE only set those that are detected from the version * response. */ ! void init_term_props(int all) { int i; *************** *** 1490,1495 **** --- 1490,1518 ---- } #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 + static struct builtin_term * find_builtin_term(char_u *term) { *************** *** 3676,3683 **** { int did_send = FALSE; - init_term_props(TRUE); - if (!can_get_termresponse() || starting != 0 || *T_U7 == NUL) return; --- 3699,3704 ---- *************** *** 4516,4522 **** // Reset terminal properties that are set based on the termresponse. // Mainly useful for tests that send the termresponse multiple times. ! init_term_props(FALSE); // If this code starts with CSI, you can bet that the // terminal uses 8-bit codes. --- 4537,4544 ---- // Reset terminal properties that are set based on the termresponse. // Mainly useful for tests that send the termresponse multiple times. ! // 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 // terminal uses 8-bit codes. *** ../vim-8.2.0969/src/proto/term.pro 2020-06-09 15:57:32.929019414 +0200 --- src/proto/term.pro 2020-06-13 15:20:25.844880329 +0200 *************** *** 1,6 **** --- 1,8 ---- /* term.c */ guicolor_T termgui_get_color(char_u *name); 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); int set_termname(char_u *term); void getlinecol(long *cp, long *rp); *** ../vim-8.2.0969/src/evalfunc.c 2020-06-10 15:32:04.455653633 +0200 --- src/evalfunc.c 2020-06-13 14:25:10.782442739 +0200 *************** *** 944,949 **** --- 944,950 ---- {"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_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_autochdir", 0, 0, 0, ret_void, f_test_autochdir}, {"test_feedinput", 1, 1, FEARG_1, ret_void, f_test_feedinput}, *** ../vim-8.2.0969/src/main.c 2020-06-09 15:57:32.925019425 +0200 --- src/main.c 2020-06-13 15:20:27.912872040 +0200 *************** *** 407,412 **** --- 407,416 ---- init_highlight(TRUE, FALSE); // set the default highlight groups TIME_MSG("init highlight"); + #if defined(FEAT_TERMRESPONSE) + init_term_props(TRUE); + #endif + #ifdef FEAT_EVAL // Set the break level after the terminal is initialized. debug_break_level = params.use_debug_break_level; *** ../vim-8.2.0969/src/testing.c 2020-06-13 15:13:33.870532936 +0200 --- src/testing.c 2020-06-13 15:31:34.970143155 +0200 *************** *** 854,859 **** --- 854,861 ---- no_query_mouse_for_testing = val; else if (STRCMP(name, (char_u *)"no_wait_return") == 0) 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) { disable_char_avail_for_testing = FALSE; *************** *** 861,866 **** --- 863,869 ---- ignore_redraw_flag_for_testing = FALSE; nfa_fail_for_testing = FALSE; no_query_mouse_for_testing = FALSE; + reset_term_props_on_termresponse = FALSE; if (save_starting >= 0) { starting = save_starting; *** ../vim-8.2.0969/src/globals.h 2020-06-10 20:56:55.021354582 +0200 --- src/globals.h 2020-06-13 15:32:41.345868520 +0200 *************** *** 1839,1844 **** --- 1839,1845 ---- EXTERN int ignore_redraw_flag_for_testing INIT(= FALSE); EXTERN int nfa_fail_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); #endif *** ../vim-8.2.0969/src/testdir/test_termcodes.vim 2020-06-06 22:36:20.464116743 +0200 --- src/testdir/test_termcodes.vim 2020-06-13 15:40:59.767828576 +0200 *************** *** 922,927 **** --- 922,928 ---- func Test_xx01_term_style_response() " Termresponse is only parsed when t_RV is not empty. set t_RV=x + call test_override('term_props', 1) " send the termresponse to trigger requesting the XT codes let seq = "\[>41;337;0c" *************** *** 932,938 **** --- 933,947 ---- call feedkeys(seq, 'Lx!') 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= + call test_override('term_props', 0) endfunc " This checks the iTerm2 version response. *************** *** 941,946 **** --- 950,956 ---- func Test_xx02_iTerm2_response() " Termresponse is only parsed when t_RV is not empty. set t_RV=x + call test_override('term_props', 1) " Old versions of iTerm2 used a different style term response. set ttymouse=xterm *************** *** 957,963 **** --- 967,981 ---- call assert_equal(seq, v:termresponse) call assert_equal('sgr', &ttymouse) + call assert_equal(#{ + \ cursor_style: 'n', + \ cursor_blink_mode: 'u', + \ underline_rgb: 'u', + \ mouse: 's' + \ }, terminalprops()) + set t_RV= + call test_override('term_props', 0) endfunc " This checks the libvterm version response. *************** *** 966,971 **** --- 984,990 ---- func Test_xx03_libvterm_response() " Termresponse is only parsed when t_RV is not empty. set t_RV=x + call test_override('term_props', 1) set ttymouse=xterm call test_option_not_set('ttymouse') *************** *** 974,980 **** --- 993,1007 ---- call assert_equal(seq, v:termresponse) call assert_equal('sgr', &ttymouse) + call assert_equal(#{ + \ cursor_style: 'n', + \ cursor_blink_mode: 'u', + \ underline_rgb: 'u', + \ mouse: 's' + \ }, terminalprops()) + set t_RV= + call test_override('term_props', 0) endfunc " This checks the Mac Terminal.app version response. *************** *** 983,988 **** --- 1010,1016 ---- func Test_xx04_Mac_Terminal_response() " Termresponse is only parsed when t_RV is not empty. set t_RV=x + call test_override('term_props', 1) set ttymouse=xterm call test_option_not_set('ttymouse') *************** *** 991,1000 **** --- 1019,1036 ---- call assert_equal(seq, v:termresponse) 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. set t_RV= set term=xterm set t_RV=x + call test_override('term_props', 0) endfunc " This checks the mintty version response. *************** *** 1003,1008 **** --- 1039,1045 ---- func Test_xx05_mintty_response() " Termresponse is only parsed when t_RV is not empty. set t_RV=x + call test_override('term_props', 1) set ttymouse=xterm call test_option_not_set('ttymouse') *************** *** 1011,1017 **** --- 1048,1062 ---- call assert_equal(seq, v:termresponse) call assert_equal('sgr', &ttymouse) + call assert_equal(#{ + \ cursor_style: 'n', + \ cursor_blink_mode: 'u', + \ underline_rgb: 'y', + \ mouse: 's' + \ }, terminalprops()) + set t_RV= + call test_override('term_props', 0) endfunc " This checks the screen version response. *************** *** 1020,1025 **** --- 1065,1071 ---- func Test_xx06_screen_response() " Termresponse is only parsed when t_RV is not empty. set t_RV=x + call test_override('term_props', 1) " Old versions of screen don't support SGR mouse mode. set ttymouse=xterm *************** *** 1037,1043 **** --- 1083,1097 ---- call assert_equal(seq, v:termresponse) call assert_equal('sgr', &ttymouse) + call assert_equal(#{ + \ cursor_style: 'n', + \ cursor_blink_mode: 'n', + \ underline_rgb: 'y', + \ mouse: 's' + \ }, terminalprops()) + set t_RV= + call test_override('term_props', 0) endfunc " This checks the xterm version response. *************** *** 1046,1051 **** --- 1100,1106 ---- func Test_xx07_xterm_response() " Termresponse is only parsed when t_RV is not empty. set t_RV=x + call test_override('term_props', 1) " Do Terminal.app first to check that is_mac_terminal is reset. set ttymouse=xterm *************** *** 1066,1071 **** --- 1121,1133 ---- call assert_equal(seq, v:termresponse) 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" set ttymouse=xterm call test_option_not_set('ttymouse') *************** *** 1074,1079 **** --- 1136,1148 ---- call assert_equal(seq, v:termresponse) call assert_equal('xterm2', &ttymouse) + call assert_equal(#{ + \ cursor_style: 'n', + \ cursor_blink_mode: 'u', + \ underline_rgb: 'u', + \ mouse: '2' + \ }, terminalprops()) + " xterm >= 277: "sgr" set ttymouse=xterm call test_option_not_set('ttymouse') *************** *** 1082,1088 **** --- 1151,1180 ---- call assert_equal(seq, v:termresponse) 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 = "\[>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= + call test_override('term_props', 0) endfunc func Test_get_termcode() *** ../vim-8.2.0969/runtime/doc/usr_41.txt 2020-06-08 20:50:23.428250680 +0200 --- runtime/doc/usr_41.txt 2020-06-13 14:22:21.619218308 +0200 *************** *** 1143,1148 **** --- 1151,1157 ---- getimstatus() check if IME status is active interrupt() interrupt script execution windowsversion() get MS-Windows version + terminalprops() properties of the terminal libcall() call a function in an external library libcallnr() idem, returning a number *** ../vim-8.2.0969/runtime/doc/eval.txt 2020-06-10 15:32:04.451653647 +0200 --- runtime/doc/eval.txt 2020-06-13 14:22:54.931062892 +0200 *************** *** 2188,2194 **** 'c', with only digits and ';' in between. When this option is set, the TermResponse autocommand event is fired, so that you can react to the response from the ! terminal. The response from a new xterm is: "[> Pp ; Pv ; Pc c". Pp 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 --- 2194,2201 ---- 'c', with only digits and ';' in between. When this option is set, the TermResponse autocommand event is fired, so that you can react to the response from the ! terminal. You can use |terminalprops()| to see what Vim ! figured out about the terminal. The response from a new xterm is: "[> Pp ; Pv ; Pc c". Pp 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 *************** *** 2864,2869 **** --- 2871,2877 ---- none set the size of a terminal term_start({cmd} [, {options}]) Number open a terminal window and run a job term_wait({buf} [, {time}]) Number wait for screen to be updated + terminalprops() Dict properties of the terminal test_alloc_fail({id}, {countdown}, {repeat}) none make memory allocation fail test_autochdir() none enable 'autochdir' during startup *************** *** 10381,10386 **** --- 10393,10433 ---- 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| *** ../vim-8.2.0969/runtime/doc/testing.txt 2020-06-03 19:55:31.111092063 +0200 --- runtime/doc/testing.txt 2020-06-13 15:29:52.022570993 +0200 *************** *** 165,170 **** --- 165,172 ---- terminals no_wait_return set the "no_wait_return" flag. Not restored with "ALL". + term_props reset all terminal properties when the version + string is detected ALL clear all overrides ({val} is not used) "starting" is to be used when a test should behave like *** ../vim-8.2.0969/src/version.c 2020-06-13 15:13:33.870532936 +0200 --- src/version.c 2020-06-13 15:44:43.738919394 +0200 *************** *** 756,757 **** --- 756,759 ---- { /* Add new patch number below this line */ + /**/ + 970, /**/ -- ARTHUR: I did say sorry about the `old woman,' but from the behind you looked-- DENNIS: What I object to is you automatically treat me like an inferior! ARTHUR: Well, I AM king... The Quest for the Holy Grail (Monty Python) /// 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 ///