comparison src/terminal.c @ 13438:33eea5ce5415 v8.0.1593

patch 8.0.1593: :qall never exits with an active terminal window commit https://github.com/vim/vim/commit/25cdd9c33b21ddbd31321c075873bb225450d2d2 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Mar 10 20:28:12 2018 +0100 patch 8.0.1593: :qall never exits with an active terminal window Problem: :qall never exits with an active terminal window. Solution: Add a way to kill a job in a terminal window.
author Christian Brabandt <cb@256bit.org>
date Sat, 10 Mar 2018 20:30:04 +0100
parents fa198b71bab2
children 9f06f7aca74c
comparison
equal deleted inserted replaced
13437:02b3f719eacb 13438:33eea5ce5415
135 void *tl_winpty; 135 void *tl_winpty;
136 #endif 136 #endif
137 #if defined(FEAT_SESSION) 137 #if defined(FEAT_SESSION)
138 char_u *tl_command; 138 char_u *tl_command;
139 #endif 139 #endif
140 char_u *tl_kill;
140 141
141 /* last known vterm size */ 142 /* last known vterm size */
142 int tl_rows; 143 int tl_rows;
143 int tl_cols; 144 int tl_cols;
144 /* vterm size does not follow window size */ 145 /* vterm size does not follow window size */
533 else 534 else
534 ga_clear(&ga); 535 ga_clear(&ga);
535 } 536 }
536 #endif 537 #endif
537 538
539 if (opt->jo_term_kill != NULL)
540 {
541 char_u *p = skiptowhite(opt->jo_term_kill);
542
543 term->tl_kill = vim_strnsave(opt->jo_term_kill, p - opt->jo_term_kill);
544 }
545
538 /* System dependent: setup the vterm and maybe start the job in it. */ 546 /* System dependent: setup the vterm and maybe start the job in it. */
539 if (argvar->v_type == VAR_STRING 547 if (argvar->v_type == VAR_STRING
540 && argvar->vval.v_string != NULL 548 && argvar->vval.v_string != NULL
541 && STRCMP(argvar->vval.v_string, "NONE") == 0) 549 && STRCMP(argvar->vval.v_string, "NONE") == 0)
542 res = create_pty_only(term, opt); 550 res = create_pty_only(term, opt);
609 opt.jo_curwin = 1; 617 opt.jo_curwin = 1;
610 else if ((int)(p - cmd) == 6 && STRNICMP(cmd, "hidden", 6) == 0) 618 else if ((int)(p - cmd) == 6 && STRNICMP(cmd, "hidden", 6) == 0)
611 opt.jo_hidden = 1; 619 opt.jo_hidden = 1;
612 else if ((int)(p - cmd) == 9 && STRNICMP(cmd, "norestore", 9) == 0) 620 else if ((int)(p - cmd) == 9 && STRNICMP(cmd, "norestore", 9) == 0)
613 opt.jo_term_norestore = 1; 621 opt.jo_term_norestore = 1;
622 else if ((int)(p - cmd) == 4 && STRNICMP(cmd, "kill", 4) == 0
623 && ep != NULL)
624 {
625 opt.jo_set2 |= JO2_TERM_KILL;
626 opt.jo_term_kill = ep + 1;
627 p = skiptowhite(cmd);
628 }
614 else if ((int)(p - cmd) == 4 && STRNICMP(cmd, "rows", 4) == 0 629 else if ((int)(p - cmd) == 4 && STRNICMP(cmd, "rows", 4) == 0
615 && ep != NULL && isdigit(ep[1])) 630 && ep != NULL && isdigit(ep[1]))
616 { 631 {
617 opt.jo_set2 |= JO2_TERM_ROWS; 632 opt.jo_set2 |= JO2_TERM_ROWS;
618 opt.jo_term_rows = atoi((char *)ep + 1); 633 opt.jo_term_rows = atoi((char *)ep + 1);
642 else 657 else
643 { 658 {
644 if (*p) 659 if (*p)
645 *p = NUL; 660 *p = NUL;
646 EMSG2(_("E181: Invalid attribute: %s"), cmd); 661 EMSG2(_("E181: Invalid attribute: %s"), cmd);
647 return; 662 goto theend;
648 } 663 }
649 cmd = skipwhite(p); 664 cmd = skipwhite(p);
650 } 665 }
651 if (*cmd == NUL) 666 if (*cmd == NUL)
652 /* Make a copy of 'shell', an autocommand may change the option. */ 667 /* Make a copy of 'shell', an autocommand may change the option. */
665 argvar[0].v_type = VAR_STRING; 680 argvar[0].v_type = VAR_STRING;
666 argvar[0].vval.v_string = cmd; 681 argvar[0].vval.v_string = cmd;
667 argvar[1].v_type = VAR_UNKNOWN; 682 argvar[1].v_type = VAR_UNKNOWN;
668 term_start(argvar, &opt, FALSE, eap->forceit); 683 term_start(argvar, &opt, FALSE, eap->forceit);
669 vim_free(tofree); 684 vim_free(tofree);
685
686 theend:
670 vim_free(opt.jo_eof_chars); 687 vim_free(opt.jo_eof_chars);
671 } 688 }
672 689
673 #if defined(FEAT_SESSION) || defined(PROTO) 690 #if defined(FEAT_SESSION) || defined(PROTO)
674 /* 691 /*
756 term_free_vterm(term); 773 term_free_vterm(term);
757 vim_free(term->tl_title); 774 vim_free(term->tl_title);
758 #ifdef FEAT_SESSION 775 #ifdef FEAT_SESSION
759 vim_free(term->tl_command); 776 vim_free(term->tl_command);
760 #endif 777 #endif
778 vim_free(term->tl_kill);
761 vim_free(term->tl_status_text); 779 vim_free(term->tl_status_text);
762 vim_free(term->tl_opencmd); 780 vim_free(term->tl_opencmd);
763 vim_free(term->tl_eof_chars); 781 vim_free(term->tl_eof_chars);
764 if (desired_cursor_color == term->tl_cursor_color) 782 if (desired_cursor_color == term->tl_cursor_color)
765 desired_cursor_color = (char_u *)""; 783 desired_cursor_color = (char_u *)"";
1079 && channel_is_open(term->tl_job->jv_channel) 1097 && channel_is_open(term->tl_job->jv_channel)
1080 && term->tl_job->jv_channel->ch_keep_open; 1098 && term->tl_job->jv_channel->ch_keep_open;
1081 } 1099 }
1082 1100
1083 /* 1101 /*
1102 * Used when exiting: kill the job in "buf" if so desired.
1103 * Return OK when the job finished.
1104 * Return FAIL when the job is still running.
1105 */
1106 int
1107 term_try_stop_job(buf_T *buf)
1108 {
1109 int count;
1110 char *how = (char *)buf->b_term->tl_kill;
1111
1112 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
1113 if ((how == NULL || *how == NUL) && (p_confirm || cmdmod.confirm))
1114 {
1115 char_u buff[DIALOG_MSG_SIZE];
1116 int ret;
1117
1118 dialog_msg(buff, _("Kill job in \"%s\"?"), buf->b_fname);
1119 ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1);
1120 if (ret == VIM_YES)
1121 how = "kill";
1122 else if (ret == VIM_CANCEL)
1123 return FAIL;
1124 }
1125 #endif
1126 if (how == NULL || *how == NUL)
1127 return FAIL;
1128
1129 job_stop(buf->b_term->tl_job, NULL, how);
1130
1131 /* wait for up to a second for the job to die */
1132 for (count = 0; count < 100; ++count)
1133 {
1134 /* buffer, terminal and job may be cleaned up while waiting */
1135 if (!buf_valid(buf)
1136 || buf->b_term == NULL
1137 || buf->b_term->tl_job == NULL)
1138 return OK;
1139
1140 /* call job_status() to update jv_status */
1141 job_status(buf->b_term->tl_job);
1142 if (buf->b_term->tl_job->jv_status >= JOB_ENDED)
1143 return OK;
1144 ui_delay(10L, FALSE);
1145 mch_check_messages();
1146 parse_queued_messages();
1147 }
1148 return FAIL;
1149 }
1150
1151 /*
1084 * Add the last line of the scrollback buffer to the buffer in the window. 1152 * Add the last line of the scrollback buffer to the buffer in the window.
1085 */ 1153 */
1086 static void 1154 static void
1087 add_scrollback_line_to_buffer(term_T *term, char_u *text, int len) 1155 add_scrollback_line_to_buffer(term_T *term, char_u *text, int len)
1088 { 1156 {
2920 term_default_cterm_bg = cterm_bg - 1; 2988 term_default_cterm_bg = cterm_bg - 1;
2921 } 2989 }
2922 2990
2923 /* 2991 /*
2924 * Get the buffer from the first argument in "argvars". 2992 * Get the buffer from the first argument in "argvars".
2925 * Returns NULL when the buffer is not for a terminal window. 2993 * Returns NULL when the buffer is not for a terminal window and logs a message
2994 * with "where".
2926 */ 2995 */
2927 static buf_T * 2996 static buf_T *
2928 term_get_buf(typval_T *argvars) 2997 term_get_buf(typval_T *argvars, char *where)
2929 { 2998 {
2930 buf_T *buf; 2999 buf_T *buf;
2931 3000
2932 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ 3001 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
2933 ++emsg_off; 3002 ++emsg_off;
2934 buf = get_buf_tv(&argvars[0], FALSE); 3003 buf = get_buf_tv(&argvars[0], FALSE);
2935 --emsg_off; 3004 --emsg_off;
2936 if (buf == NULL || buf->b_term == NULL) 3005 if (buf == NULL || buf->b_term == NULL)
3006 {
3007 ch_log(NULL, "%s: invalid buffer argument", where);
2937 return NULL; 3008 return NULL;
3009 }
2938 return buf; 3010 return buf;
2939 } 3011 }
2940 3012
2941 static int 3013 static int
2942 same_color(VTermColor *a, VTermColor *b) 3014 same_color(VTermColor *a, VTermColor *b)
2978 * @{count} 3050 * @{count}
2979 */ 3051 */
2980 void 3052 void
2981 f_term_dumpwrite(typval_T *argvars, typval_T *rettv UNUSED) 3053 f_term_dumpwrite(typval_T *argvars, typval_T *rettv UNUSED)
2982 { 3054 {
2983 buf_T *buf = term_get_buf(argvars); 3055 buf_T *buf = term_get_buf(argvars, "term_dumpwrite()");
2984 term_T *term; 3056 term_T *term;
2985 char_u *fname; 3057 char_u *fname;
2986 int max_height = 0; 3058 int max_height = 0;
2987 int max_width = 0; 3059 int max_width = 0;
2988 stat_T st; 3060 stat_T st;
3717 * "term_getaltscreen(buf)" function 3789 * "term_getaltscreen(buf)" function
3718 */ 3790 */
3719 void 3791 void
3720 f_term_getaltscreen(typval_T *argvars, typval_T *rettv) 3792 f_term_getaltscreen(typval_T *argvars, typval_T *rettv)
3721 { 3793 {
3722 buf_T *buf = term_get_buf(argvars); 3794 buf_T *buf = term_get_buf(argvars, "term_getaltscreen()");
3723 3795
3724 if (buf == NULL) 3796 if (buf == NULL)
3725 return; 3797 return;
3726 rettv->vval.v_number = buf->b_term->tl_using_altscreen; 3798 rettv->vval.v_number = buf->b_term->tl_using_altscreen;
3727 } 3799 }
3764 * "term_getcursor(buf)" function 3836 * "term_getcursor(buf)" function
3765 */ 3837 */
3766 void 3838 void
3767 f_term_getcursor(typval_T *argvars, typval_T *rettv) 3839 f_term_getcursor(typval_T *argvars, typval_T *rettv)
3768 { 3840 {
3769 buf_T *buf = term_get_buf(argvars); 3841 buf_T *buf = term_get_buf(argvars, "term_getcursor()");
3770 term_T *term; 3842 term_T *term;
3771 list_T *l; 3843 list_T *l;
3772 dict_T *d; 3844 dict_T *d;
3773 3845
3774 if (rettv_list_alloc(rettv) == FAIL) 3846 if (rettv_list_alloc(rettv) == FAIL)
3798 * "term_getjob(buf)" function 3870 * "term_getjob(buf)" function
3799 */ 3871 */
3800 void 3872 void
3801 f_term_getjob(typval_T *argvars, typval_T *rettv) 3873 f_term_getjob(typval_T *argvars, typval_T *rettv)
3802 { 3874 {
3803 buf_T *buf = term_get_buf(argvars); 3875 buf_T *buf = term_get_buf(argvars, "term_getjob()");
3804 3876
3805 rettv->v_type = VAR_JOB; 3877 rettv->v_type = VAR_JOB;
3806 rettv->vval.v_job = NULL; 3878 rettv->vval.v_job = NULL;
3807 if (buf == NULL) 3879 if (buf == NULL)
3808 return; 3880 return;
3826 * "term_getline(buf, row)" function 3898 * "term_getline(buf, row)" function
3827 */ 3899 */
3828 void 3900 void
3829 f_term_getline(typval_T *argvars, typval_T *rettv) 3901 f_term_getline(typval_T *argvars, typval_T *rettv)
3830 { 3902 {
3831 buf_T *buf = term_get_buf(argvars); 3903 buf_T *buf = term_get_buf(argvars, "term_getline()");
3832 term_T *term; 3904 term_T *term;
3833 int row; 3905 int row;
3834 3906
3835 rettv->v_type = VAR_STRING; 3907 rettv->v_type = VAR_STRING;
3836 if (buf == NULL) 3908 if (buf == NULL)
3873 * "term_getscrolled(buf)" function 3945 * "term_getscrolled(buf)" function
3874 */ 3946 */
3875 void 3947 void
3876 f_term_getscrolled(typval_T *argvars, typval_T *rettv) 3948 f_term_getscrolled(typval_T *argvars, typval_T *rettv)
3877 { 3949 {
3878 buf_T *buf = term_get_buf(argvars); 3950 buf_T *buf = term_get_buf(argvars, "term_getscrolled()");
3879 3951
3880 if (buf == NULL) 3952 if (buf == NULL)
3881 return; 3953 return;
3882 rettv->vval.v_number = buf->b_term->tl_scrollback_scrolled; 3954 rettv->vval.v_number = buf->b_term->tl_scrollback_scrolled;
3883 } 3955 }
3886 * "term_getsize(buf)" function 3958 * "term_getsize(buf)" function
3887 */ 3959 */
3888 void 3960 void
3889 f_term_getsize(typval_T *argvars, typval_T *rettv) 3961 f_term_getsize(typval_T *argvars, typval_T *rettv)
3890 { 3962 {
3891 buf_T *buf = term_get_buf(argvars); 3963 buf_T *buf = term_get_buf(argvars, "term_getsize()");
3892 list_T *l; 3964 list_T *l;
3893 3965
3894 if (rettv_list_alloc(rettv) == FAIL) 3966 if (rettv_list_alloc(rettv) == FAIL)
3895 return; 3967 return;
3896 if (buf == NULL) 3968 if (buf == NULL)
3905 * "term_getstatus(buf)" function 3977 * "term_getstatus(buf)" function
3906 */ 3978 */
3907 void 3979 void
3908 f_term_getstatus(typval_T *argvars, typval_T *rettv) 3980 f_term_getstatus(typval_T *argvars, typval_T *rettv)
3909 { 3981 {
3910 buf_T *buf = term_get_buf(argvars); 3982 buf_T *buf = term_get_buf(argvars, "term_getstatus()");
3911 term_T *term; 3983 term_T *term;
3912 char_u val[100]; 3984 char_u val[100];
3913 3985
3914 rettv->v_type = VAR_STRING; 3986 rettv->v_type = VAR_STRING;
3915 if (buf == NULL) 3987 if (buf == NULL)
3929 * "term_gettitle(buf)" function 4001 * "term_gettitle(buf)" function
3930 */ 4002 */
3931 void 4003 void
3932 f_term_gettitle(typval_T *argvars, typval_T *rettv) 4004 f_term_gettitle(typval_T *argvars, typval_T *rettv)
3933 { 4005 {
3934 buf_T *buf = term_get_buf(argvars); 4006 buf_T *buf = term_get_buf(argvars, "term_gettitle()");
3935 4007
3936 rettv->v_type = VAR_STRING; 4008 rettv->v_type = VAR_STRING;
3937 if (buf == NULL) 4009 if (buf == NULL)
3938 return; 4010 return;
3939 4011
3945 * "term_gettty(buf)" function 4017 * "term_gettty(buf)" function
3946 */ 4018 */
3947 void 4019 void
3948 f_term_gettty(typval_T *argvars, typval_T *rettv) 4020 f_term_gettty(typval_T *argvars, typval_T *rettv)
3949 { 4021 {
3950 buf_T *buf = term_get_buf(argvars); 4022 buf_T *buf = term_get_buf(argvars, "term_gettty()");
3951 char_u *p; 4023 char_u *p;
3952 int num = 0; 4024 int num = 0;
3953 4025
3954 rettv->v_type = VAR_STRING; 4026 rettv->v_type = VAR_STRING;
3955 if (buf == NULL) 4027 if (buf == NULL)
4003 * "term_scrape(buf, row)" function 4075 * "term_scrape(buf, row)" function
4004 */ 4076 */
4005 void 4077 void
4006 f_term_scrape(typval_T *argvars, typval_T *rettv) 4078 f_term_scrape(typval_T *argvars, typval_T *rettv)
4007 { 4079 {
4008 buf_T *buf = term_get_buf(argvars); 4080 buf_T *buf = term_get_buf(argvars, "term_scrape()");
4009 VTermScreen *screen = NULL; 4081 VTermScreen *screen = NULL;
4010 VTermPos pos; 4082 VTermPos pos;
4011 list_T *l; 4083 list_T *l;
4012 term_T *term; 4084 term_T *term;
4013 char_u *p; 4085 char_u *p;
4112 * "term_sendkeys(buf, keys)" function 4184 * "term_sendkeys(buf, keys)" function
4113 */ 4185 */
4114 void 4186 void
4115 f_term_sendkeys(typval_T *argvars, typval_T *rettv) 4187 f_term_sendkeys(typval_T *argvars, typval_T *rettv)
4116 { 4188 {
4117 buf_T *buf = term_get_buf(argvars); 4189 buf_T *buf = term_get_buf(argvars, "term_sendkeys()");
4118 char_u *msg; 4190 char_u *msg;
4119 term_T *term; 4191 term_T *term;
4120 4192
4121 rettv->v_type = VAR_UNKNOWN; 4193 rettv->v_type = VAR_UNKNOWN;
4122 if (buf == NULL) 4194 if (buf == NULL)
4141 */ 4213 */
4142 void 4214 void
4143 f_term_setrestore(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 4215 f_term_setrestore(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
4144 { 4216 {
4145 #if defined(FEAT_SESSION) 4217 #if defined(FEAT_SESSION)
4146 buf_T *buf = term_get_buf(argvars); 4218 buf_T *buf = term_get_buf(argvars, "term_setrestore()");
4147 term_T *term; 4219 term_T *term;
4148 char_u *cmd; 4220 char_u *cmd;
4149 4221
4150 if (buf == NULL) 4222 if (buf == NULL)
4151 return; 4223 return;
4158 term->tl_command = NULL; 4230 term->tl_command = NULL;
4159 #endif 4231 #endif
4160 } 4232 }
4161 4233
4162 /* 4234 /*
4235 * "term_setkill(buf, how)" function
4236 */
4237 void
4238 f_term_setkill(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
4239 {
4240 buf_T *buf = term_get_buf(argvars, "term_setkill()");
4241 term_T *term;
4242 char_u *how;
4243
4244 if (buf == NULL)
4245 return;
4246 term = buf->b_term;
4247 vim_free(term->tl_kill);
4248 how = get_tv_string_chk(&argvars[1]);
4249 if (how != NULL)
4250 term->tl_kill = vim_strsave(how);
4251 else
4252 term->tl_kill = NULL;
4253 }
4254
4255 /*
4163 * "term_start(command, options)" function 4256 * "term_start(command, options)" function
4164 */ 4257 */
4165 void 4258 void
4166 f_term_start(typval_T *argvars, typval_T *rettv) 4259 f_term_start(typval_T *argvars, typval_T *rettv)
4167 { 4260 {
4175 + JO_CALLBACK + JO_OUT_CALLBACK + JO_ERR_CALLBACK 4268 + JO_CALLBACK + JO_OUT_CALLBACK + JO_ERR_CALLBACK
4176 + JO_EXIT_CB + JO_CLOSE_CALLBACK + JO_OUT_IO, 4269 + JO_EXIT_CB + JO_CLOSE_CALLBACK + JO_OUT_IO,
4177 JO2_TERM_NAME + JO2_TERM_FINISH + JO2_HIDDEN + JO2_TERM_OPENCMD 4270 JO2_TERM_NAME + JO2_TERM_FINISH + JO2_HIDDEN + JO2_TERM_OPENCMD
4178 + JO2_TERM_COLS + JO2_TERM_ROWS + JO2_VERTICAL + JO2_CURWIN 4271 + JO2_TERM_COLS + JO2_TERM_ROWS + JO2_VERTICAL + JO2_CURWIN
4179 + JO2_CWD + JO2_ENV + JO2_EOF_CHARS 4272 + JO2_CWD + JO2_ENV + JO2_EOF_CHARS
4180 + JO2_NORESTORE) == FAIL) 4273 + JO2_NORESTORE + JO2_TERM_KILL) == FAIL)
4181 return; 4274 return;
4182 4275
4183 if (opt.jo_vertical) 4276 if (opt.jo_vertical)
4184 cmdmod.split = WSP_VERT; 4277 cmdmod.split = WSP_VERT;
4185 buf = term_start(&argvars[0], &opt, FALSE, FALSE); 4278 buf = term_start(&argvars[0], &opt, FALSE, FALSE);
4192 * "term_wait" function 4285 * "term_wait" function
4193 */ 4286 */
4194 void 4287 void
4195 f_term_wait(typval_T *argvars, typval_T *rettv UNUSED) 4288 f_term_wait(typval_T *argvars, typval_T *rettv UNUSED)
4196 { 4289 {
4197 buf_T *buf = term_get_buf(argvars); 4290 buf_T *buf = term_get_buf(argvars, "term_wait()");
4198 4291
4199 if (buf == NULL) 4292 if (buf == NULL)
4200 {
4201 ch_log(NULL, "term_wait(): invalid argument");
4202 return; 4293 return;
4203 }
4204 if (buf->b_term->tl_job == NULL) 4294 if (buf->b_term->tl_job == NULL)
4205 { 4295 {
4206 ch_log(NULL, "term_wait(): no job to wait for"); 4296 ch_log(NULL, "term_wait(): no job to wait for");
4207 return; 4297 return;
4208 } 4298 }