Mercurial > vim
comparison src/terminal.c @ 11993:92a86fe8adc0 v8.0.0877
patch 8.0.0877: using CTRL- CTRL-N in terminal is inconsistent
commit https://github.com/vim/vim/commit/6d8197485dc84532e37aced2c39292bff374200d
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Aug 6 14:57:49 2017 +0200
patch 8.0.0877: using CTRL-\ CTRL-N in terminal is inconsistent
Problem: Using CTRL-\ CTRL-N in terminal is inconsistent.
Solution: Stay in Normal mode.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sun, 06 Aug 2017 15:00:04 +0200 |
parents | d036c1c8537d |
children | 64b822c4f7ae |
comparison
equal
deleted
inserted
replaced
11992:e5c731391a9f | 11993:92a86fe8adc0 |
---|---|
34 * | 34 * |
35 * When the job ends the text is put in a buffer. Redrawing then happens from | 35 * When the job ends the text is put in a buffer. Redrawing then happens from |
36 * that buffer, attributes come from the scrollback buffer tl_scrollback. | 36 * that buffer, attributes come from the scrollback buffer tl_scrollback. |
37 * | 37 * |
38 * TODO: | 38 * TODO: |
39 * - MS-Windows: no redraw for 'updatetime' #1915 | 39 * - Add argument to term_wait() for waiting time. |
40 * - add argument to term_wait() for waiting time. | |
41 * - For the scrollback buffer store lines in the buffer, only attributes in | 40 * - For the scrollback buffer store lines in the buffer, only attributes in |
42 * tl_scrollback. | 41 * tl_scrollback. |
43 * - When the job ends: | 42 * - When the job ends: |
44 * - Need an option or argument to drop the window+buffer right away, to be | 43 * - Need an option or argument to drop the window+buffer right away, to be |
45 * used for a shell or Vim. 'termfinish'; "close", "open" (open window when | 44 * used for a shell or Vim. 'termfinish'; "close", "open" (open window when |
46 * job finishes). | 45 * job finishes). |
47 * - add option values to the command: | 46 * - add option values to the command: |
48 * :term <24x80> <close> vim notes.txt | 47 * :term <24x80> <close> vim notes.txt |
49 * - support different cursor shapes, colors and attributes | 48 * - support different cursor shapes, colors and attributes |
49 * - MS-Windows: no redraw for 'updatetime' #1915 | |
50 * - make term_getcursor() return type (none/block/bar/underline) and | 50 * - make term_getcursor() return type (none/block/bar/underline) and |
51 * attributes (color, blink, etc.) | 51 * attributes (color, blink, etc.) |
52 * - To set BS correctly, check get_stty(); Pass the fd of the pty. | 52 * - To set BS correctly, check get_stty(); Pass the fd of the pty. |
53 * For the GUI fill termios with default values, perhaps like pangoterm: | 53 * For the GUI fill termios with default values, perhaps like pangoterm: |
54 * http://bazaar.launchpad.net/~leonerd/pangoterm/trunk/view/head:/main.c#L134 | 54 * http://bazaar.launchpad.net/~leonerd/pangoterm/trunk/view/head:/main.c#L134 |
113 | 113 |
114 /* used when tl_job is NULL and only a pty was created */ | 114 /* used when tl_job is NULL and only a pty was created */ |
115 int tl_tty_fd; | 115 int tl_tty_fd; |
116 char_u *tl_tty_name; | 116 char_u *tl_tty_name; |
117 | 117 |
118 int tl_terminal_mode; /* 0, TMODE_ONCE or TMODE_LOOP */ | 118 int tl_normal_mode; /* TRUE: Terminal-Normal mode */ |
119 int tl_channel_closed; | 119 int tl_channel_closed; |
120 | 120 |
121 #ifdef WIN3264 | 121 #ifdef WIN3264 |
122 void *tl_winpty_config; | 122 void *tl_winpty_config; |
123 void *tl_winpty; | 123 void *tl_winpty; |
460 } | 460 } |
461 | 461 |
462 static void | 462 static void |
463 update_cursor(term_T *term, int redraw) | 463 update_cursor(term_T *term, int redraw) |
464 { | 464 { |
465 if (term->tl_terminal_mode != 0) | 465 if (term->tl_normal_mode) |
466 return; | 466 return; |
467 setcursor(); | 467 setcursor(); |
468 if (redraw && term->tl_buffer == curbuf) | 468 if (redraw && term->tl_buffer == curbuf) |
469 { | 469 { |
470 if (term->tl_cursor_visible) | 470 if (term->tl_cursor_visible) |
493 return; | 493 return; |
494 } | 494 } |
495 ch_log(channel, "writing %d bytes to terminal", (int)len); | 495 ch_log(channel, "writing %d bytes to terminal", (int)len); |
496 term_write_job_output(term, msg, len); | 496 term_write_job_output(term, msg, len); |
497 | 497 |
498 if (term->tl_terminal_mode == 0) | 498 if (!term->tl_normal_mode) |
499 { | 499 { |
500 /* TODO: only update once in a while. */ | 500 /* TODO: only update once in a while. */ |
501 update_screen(0); | 501 update_screen(0); |
502 update_cursor(term, TRUE); | 502 update_cursor(term, TRUE); |
503 } | 503 } |
806 } | 806 } |
807 } | 807 } |
808 } | 808 } |
809 | 809 |
810 static void | 810 static void |
811 set_terminal_mode(term_T *term, int mode) | 811 set_terminal_mode(term_T *term, int normal_mode) |
812 { | 812 { |
813 term->tl_terminal_mode = mode; | 813 term->tl_normal_mode = normal_mode; |
814 vim_free(term->tl_status_text); | 814 vim_free(term->tl_status_text); |
815 term->tl_status_text = NULL; | 815 term->tl_status_text = NULL; |
816 if (term->tl_buffer == curbuf) | 816 if (term->tl_buffer == curbuf) |
817 maketitle(); | 817 maketitle(); |
818 } | 818 } |
824 static void | 824 static void |
825 cleanup_vterm(term_T *term) | 825 cleanup_vterm(term_T *term) |
826 { | 826 { |
827 move_terminal_to_buffer(term); | 827 move_terminal_to_buffer(term); |
828 term_free_vterm(term); | 828 term_free_vterm(term); |
829 set_terminal_mode(term, 0); | 829 set_terminal_mode(term, FALSE); |
830 } | 830 } |
831 | 831 |
832 /* | 832 /* |
833 * Switch from Terminal-Job mode to Terminal-Normal mode. | 833 * Switch from Terminal-Job mode to Terminal-Normal mode. |
834 * Suspends updating the terminal window. | 834 * Suspends updating the terminal window. |
835 */ | 835 */ |
836 static void | 836 static void |
837 term_enter_terminal_mode(int mode) | 837 term_enter_normal_mode(void) |
838 { | 838 { |
839 term_T *term = curbuf->b_term; | 839 term_T *term = curbuf->b_term; |
840 | 840 |
841 /* Append the current terminal contents to the buffer. */ | 841 /* Append the current terminal contents to the buffer. */ |
842 move_terminal_to_buffer(term); | 842 move_terminal_to_buffer(term); |
843 | 843 |
844 set_terminal_mode(term, mode); | 844 set_terminal_mode(term, TRUE); |
845 | 845 |
846 if (mode == TMODE_ONCE) | 846 /* Move the window cursor to the position of the cursor in the |
847 { | 847 * terminal. */ |
848 /* Move the window cursor to the position of the cursor in the | 848 curwin->w_cursor.lnum = term->tl_scrollback_scrolled |
849 * terminal. */ | 849 + term->tl_cursor_pos.row + 1; |
850 curwin->w_cursor.lnum = term->tl_scrollback_scrolled | 850 check_cursor(); |
851 + term->tl_cursor_pos.row + 1; | 851 coladvance(term->tl_cursor_pos.col); |
852 check_cursor(); | 852 |
853 coladvance(term->tl_cursor_pos.col); | 853 /* Display the same lines as in the terminal. */ |
854 | 854 curwin->w_topline = term->tl_scrollback_scrolled + 1; |
855 /* Display the same lines as in the terminal. */ | |
856 curwin->w_topline = term->tl_scrollback_scrolled + 1; | |
857 } | |
858 } | 855 } |
859 | 856 |
860 /* | 857 /* |
861 * Returns TRUE if the current window contains a terminal and we are in | 858 * Returns TRUE if the current window contains a terminal and we are in |
862 * Terminal-Normal mode. | 859 * Terminal-Normal mode. |
863 */ | 860 */ |
864 int | 861 int |
865 term_in_terminal_mode() | 862 term_in_normal_mode(void) |
866 { | 863 { |
867 term_T *term = curbuf->b_term; | 864 term_T *term = curbuf->b_term; |
868 | 865 |
869 return term != NULL && term->tl_terminal_mode != 0; | 866 return term != NULL && term->tl_normal_mode; |
870 } | 867 } |
871 | 868 |
872 /* | 869 /* |
873 * Switch from Terminal-Normal mode to Terminal-Job mode. | 870 * Switch from Terminal-Normal mode to Terminal-Job mode. |
874 * Restores updating the terminal window. | 871 * Restores updating the terminal window. |
875 */ | 872 */ |
876 void | 873 void |
877 term_leave_terminal_mode() | 874 term_enter_job_mode() |
878 { | 875 { |
879 term_T *term = curbuf->b_term; | 876 term_T *term = curbuf->b_term; |
880 sb_line_T *line; | 877 sb_line_T *line; |
881 garray_T *gap; | 878 garray_T *gap; |
882 | 879 |
891 if (gap->ga_len == 0) | 888 if (gap->ga_len == 0) |
892 break; | 889 break; |
893 } | 890 } |
894 check_cursor(); | 891 check_cursor(); |
895 | 892 |
896 set_terminal_mode(term, 0); | 893 set_terminal_mode(term, FALSE); |
897 | 894 |
898 if (term->tl_channel_closed) | 895 if (term->tl_channel_closed) |
899 cleanup_vterm(term); | 896 cleanup_vterm(term); |
900 redraw_buf_and_status_later(curbuf, NOT_VALID); | 897 redraw_buf_and_status_later(curbuf, NOT_VALID); |
901 } | 898 } |
1051 /* | 1048 /* |
1052 * Returns TRUE if the current window contains a terminal and we are sending | 1049 * Returns TRUE if the current window contains a terminal and we are sending |
1053 * keys to the job. | 1050 * keys to the job. |
1054 */ | 1051 */ |
1055 int | 1052 int |
1056 term_use_loop(int once) | 1053 term_use_loop(void) |
1057 { | 1054 { |
1058 term_T *term = curbuf->b_term; | 1055 term_T *term = curbuf->b_term; |
1059 | 1056 |
1060 return term != NULL | 1057 return term != NULL |
1061 && (once ? term->tl_terminal_mode != TMODE_LOOP | 1058 && !term->tl_normal_mode |
1062 : term->tl_terminal_mode == 0) | |
1063 && term->tl_vterm != NULL | 1059 && term->tl_vterm != NULL |
1064 && term_job_running(term); | 1060 && term_job_running(term); |
1065 } | 1061 } |
1066 | 1062 |
1067 /* | 1063 /* |
1075 terminal_loop(void) | 1071 terminal_loop(void) |
1076 { | 1072 { |
1077 int c; | 1073 int c; |
1078 int termkey = 0; | 1074 int termkey = 0; |
1079 | 1075 |
1080 if (curbuf->b_term->tl_terminal_mode != 0) | |
1081 { | |
1082 /* Got back from TMODE_ONCE, enter Terminal-Job mode. */ | |
1083 term_leave_terminal_mode(); | |
1084 update_cursor(curbuf->b_term, TRUE); | |
1085 } | |
1086 | |
1087 if (*curwin->w_p_tk != NUL) | 1076 if (*curwin->w_p_tk != NUL) |
1088 termkey = string_to_key(curwin->w_p_tk, TRUE); | 1077 termkey = string_to_key(curwin->w_p_tk, TRUE); |
1089 position_cursor(curwin, &curbuf->b_term->tl_cursor_pos); | 1078 position_cursor(curwin, &curbuf->b_term->tl_cursor_pos); |
1090 | 1079 |
1091 for (;;) | 1080 for (;;) |
1095 while (curwin->w_redr_type != 0) | 1084 while (curwin->w_redr_type != 0) |
1096 update_screen(0); | 1085 update_screen(0); |
1097 update_cursor(curbuf->b_term, FALSE); | 1086 update_cursor(curbuf->b_term, FALSE); |
1098 | 1087 |
1099 c = term_vgetc(); | 1088 c = term_vgetc(); |
1100 if (!term_use_loop(FALSE)) | 1089 if (!term_use_loop()) |
1101 /* job finished while waiting for a character */ | 1090 /* job finished while waiting for a character */ |
1102 break; | 1091 break; |
1103 | 1092 |
1104 #ifdef UNIX | 1093 #ifdef UNIX |
1105 may_send_sigint(c, curbuf->b_term->tl_job->jv_pid, 0); | 1094 may_send_sigint(c, curbuf->b_term->tl_job->jv_pid, 0); |
1122 #endif | 1111 #endif |
1123 c = term_vgetc(); | 1112 c = term_vgetc(); |
1124 #ifdef FEAT_CMDL_INFO | 1113 #ifdef FEAT_CMDL_INFO |
1125 clear_showcmd(); | 1114 clear_showcmd(); |
1126 #endif | 1115 #endif |
1127 if (!term_use_loop(FALSE)) | 1116 if (!term_use_loop()) |
1128 /* job finished while waiting for a character */ | 1117 /* job finished while waiting for a character */ |
1129 break; | 1118 break; |
1130 | 1119 |
1131 if (prev_c == Ctrl_BSL) | 1120 if (prev_c == Ctrl_BSL) |
1132 { | 1121 { |
1133 if (c == Ctrl_N) | 1122 if (c == Ctrl_N) |
1134 { | 1123 { |
1135 /* CTRL-\ CTRL-N : execute one Normal mode command. */ | 1124 /* CTRL-\ CTRL-N : go to Terminal-Normal mode. */ |
1136 term_enter_terminal_mode(TMODE_ONCE); | 1125 term_enter_normal_mode(); |
1137 return OK; | 1126 return FAIL; |
1138 } | 1127 } |
1139 /* Send both keys to the terminal. */ | 1128 /* Send both keys to the terminal. */ |
1140 send_keys_to_term(curbuf->b_term, prev_c, TRUE); | 1129 send_keys_to_term(curbuf->b_term, prev_c, TRUE); |
1141 } | 1130 } |
1142 else if (termkey == 0 && c == '.') | 1131 else if (termkey == 0 && c == '.') |
1144 /* "CTRL-W .": send CTRL-W to the job */ | 1133 /* "CTRL-W .": send CTRL-W to the job */ |
1145 c = Ctrl_W; | 1134 c = Ctrl_W; |
1146 } | 1135 } |
1147 else if (c == 'N') | 1136 else if (c == 'N') |
1148 { | 1137 { |
1149 term_enter_terminal_mode(TMODE_LOOP); | 1138 /* CTRL-W N : go to Terminal-Normal mode. */ |
1139 term_enter_normal_mode(); | |
1150 return FAIL; | 1140 return FAIL; |
1151 } | 1141 } |
1152 else if (c == '"') | 1142 else if (c == '"') |
1153 { | 1143 { |
1154 term_paste_register(prev_c); | 1144 term_paste_register(prev_c); |
1247 FOR_ALL_WINDOWS(wp) | 1237 FOR_ALL_WINDOWS(wp) |
1248 { | 1238 { |
1249 if (wp->w_buffer == term->tl_buffer) | 1239 if (wp->w_buffer == term->tl_buffer) |
1250 position_cursor(wp, &pos); | 1240 position_cursor(wp, &pos); |
1251 } | 1241 } |
1252 if (term->tl_buffer == curbuf && term->tl_terminal_mode == 0) | 1242 if (term->tl_buffer == curbuf && !term->tl_normal_mode) |
1253 { | 1243 { |
1254 may_toggle_cursor(term); | 1244 may_toggle_cursor(term); |
1255 update_cursor(term, term->tl_cursor_visible); | 1245 update_cursor(term, term->tl_cursor_visible); |
1256 } | 1246 } |
1257 | 1247 |
1383 term->tl_title = NULL; | 1373 term->tl_title = NULL; |
1384 vim_free(term->tl_status_text); | 1374 vim_free(term->tl_status_text); |
1385 term->tl_status_text = NULL; | 1375 term->tl_status_text = NULL; |
1386 | 1376 |
1387 /* Unless in Terminal-Normal mode: clear the vterm. */ | 1377 /* Unless in Terminal-Normal mode: clear the vterm. */ |
1388 if (term->tl_terminal_mode == 0) | 1378 if (!term->tl_normal_mode) |
1389 cleanup_vterm(term); | 1379 cleanup_vterm(term); |
1390 | 1380 |
1391 redraw_buf_and_status_later(term->tl_buffer, NOT_VALID); | 1381 redraw_buf_and_status_later(term->tl_buffer, NOT_VALID); |
1392 did_one = TRUE; | 1382 did_one = TRUE; |
1393 } | 1383 } |
1571 } | 1561 } |
1572 return 0; | 1562 return 0; |
1573 } | 1563 } |
1574 | 1564 |
1575 /* | 1565 /* |
1576 * Called to update the window that contains a terminal. | 1566 * Called to update a window that contains an active terminal. |
1577 * Returns FAIL when there is no terminal running in this window. | 1567 * Returns FAIL when there is no terminal running in this window or in |
1568 * Terminal-Normal mode. | |
1578 */ | 1569 */ |
1579 int | 1570 int |
1580 term_update_window(win_T *wp) | 1571 term_update_window(win_T *wp) |
1581 { | 1572 { |
1582 term_T *term = wp->w_buffer->b_term; | 1573 term_T *term = wp->w_buffer->b_term; |
1583 VTerm *vterm; | 1574 VTerm *vterm; |
1584 VTermScreen *screen; | 1575 VTermScreen *screen; |
1585 VTermState *state; | 1576 VTermState *state; |
1586 VTermPos pos; | 1577 VTermPos pos; |
1587 | 1578 |
1588 if (term == NULL || term->tl_vterm == NULL || term->tl_terminal_mode != 0) | 1579 if (term == NULL || term->tl_vterm == NULL || term->tl_normal_mode) |
1589 return FAIL; | 1580 return FAIL; |
1590 | 1581 |
1591 vterm = term->tl_vterm; | 1582 vterm = term->tl_vterm; |
1592 screen = vterm_obtain_screen(vterm); | 1583 screen = vterm_obtain_screen(vterm); |
1593 state = vterm_obtain_state(vterm); | 1584 state = vterm_obtain_state(vterm); |
1705 return buf->b_term != NULL && buf->b_term->tl_vterm == NULL; | 1696 return buf->b_term != NULL && buf->b_term->tl_vterm == NULL; |
1706 } | 1697 } |
1707 | 1698 |
1708 /* | 1699 /* |
1709 * Return TRUE if "wp" is a terminal window where the job has finished or we | 1700 * Return TRUE if "wp" is a terminal window where the job has finished or we |
1710 * are in Terminal-Normal mode. | 1701 * are in Terminal-Normal mode, thus we show the buffer contents. |
1711 */ | 1702 */ |
1712 int | 1703 int |
1713 term_show_buffer(buf_T *buf) | 1704 term_show_buffer(buf_T *buf) |
1714 { | 1705 { |
1715 term_T *term = buf->b_term; | 1706 term_T *term = buf->b_term; |
1716 | 1707 |
1717 return term != NULL | 1708 return term != NULL && (term->tl_vterm == NULL || term->tl_normal_mode); |
1718 && (term->tl_vterm == NULL || term->tl_terminal_mode != 0); | |
1719 } | 1709 } |
1720 | 1710 |
1721 /* | 1711 /* |
1722 * The current buffer is going to be changed. If there is terminal | 1712 * The current buffer is going to be changed. If there is terminal |
1723 * highlighting remove it now. | 1713 * highlighting remove it now. |
1796 if (term->tl_status_text == NULL) | 1786 if (term->tl_status_text == NULL) |
1797 { | 1787 { |
1798 char_u *txt; | 1788 char_u *txt; |
1799 size_t len; | 1789 size_t len; |
1800 | 1790 |
1801 if (term->tl_terminal_mode != 0) | 1791 if (term->tl_normal_mode) |
1802 { | 1792 { |
1803 if (term_job_running(term)) | 1793 if (term_job_running(term)) |
1804 txt = (char_u *)_("Terminal"); | 1794 txt = (char_u *)_("Terminal"); |
1805 else | 1795 else |
1806 txt = (char_u *)_("Terminal-finished"); | 1796 txt = (char_u *)_("Terminal-finished"); |
2023 | 2013 |
2024 if (term_job_running(term)) | 2014 if (term_job_running(term)) |
2025 STRCPY(val, "running"); | 2015 STRCPY(val, "running"); |
2026 else | 2016 else |
2027 STRCPY(val, "finished"); | 2017 STRCPY(val, "finished"); |
2028 if (term->tl_terminal_mode != 0) | 2018 if (term->tl_normal_mode) |
2029 STRCAT(val, ",terminal"); | 2019 STRCAT(val, ",normal"); |
2030 rettv->vval.v_string = vim_strsave(val); | 2020 rettv->vval.v_string = vim_strsave(val); |
2031 } | 2021 } |
2032 | 2022 |
2033 /* | 2023 /* |
2034 * "term_gettitle(buf)" function | 2024 * "term_gettitle(buf)" function |
2185 { | 2175 { |
2186 send_keys_to_term(term, PTR2CHAR(msg), FALSE); | 2176 send_keys_to_term(term, PTR2CHAR(msg), FALSE); |
2187 msg += MB_PTR2LEN(msg); | 2177 msg += MB_PTR2LEN(msg); |
2188 } | 2178 } |
2189 | 2179 |
2190 if (term->tl_terminal_mode == 0) | 2180 if (!term->tl_normal_mode) |
2191 { | 2181 { |
2192 /* TODO: only update once in a while. */ | 2182 /* TODO: only update once in a while. */ |
2193 update_screen(0); | 2183 update_screen(0); |
2194 if (buf == curbuf) | 2184 if (buf == curbuf) |
2195 update_cursor(term, TRUE); | 2185 update_cursor(term, TRUE); |