Mercurial > vim
diff 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 |
line wrap: on
line diff
--- a/src/terminal.c +++ b/src/terminal.c @@ -137,6 +137,7 @@ struct terminal_S { #if defined(FEAT_SESSION) char_u *tl_command; #endif + char_u *tl_kill; /* last known vterm size */ int tl_rows; @@ -535,6 +536,13 @@ term_start(typval_T *argvar, jobopt_T *o } #endif + if (opt->jo_term_kill != NULL) + { + char_u *p = skiptowhite(opt->jo_term_kill); + + term->tl_kill = vim_strnsave(opt->jo_term_kill, p - opt->jo_term_kill); + } + /* System dependent: setup the vterm and maybe start the job in it. */ if (argvar->v_type == VAR_STRING && argvar->vval.v_string != NULL @@ -611,6 +619,13 @@ ex_terminal(exarg_T *eap) opt.jo_hidden = 1; else if ((int)(p - cmd) == 9 && STRNICMP(cmd, "norestore", 9) == 0) opt.jo_term_norestore = 1; + else if ((int)(p - cmd) == 4 && STRNICMP(cmd, "kill", 4) == 0 + && ep != NULL) + { + opt.jo_set2 |= JO2_TERM_KILL; + opt.jo_term_kill = ep + 1; + p = skiptowhite(cmd); + } else if ((int)(p - cmd) == 4 && STRNICMP(cmd, "rows", 4) == 0 && ep != NULL && isdigit(ep[1])) { @@ -644,7 +659,7 @@ ex_terminal(exarg_T *eap) if (*p) *p = NUL; EMSG2(_("E181: Invalid attribute: %s"), cmd); - return; + goto theend; } cmd = skipwhite(p); } @@ -667,6 +682,8 @@ ex_terminal(exarg_T *eap) argvar[1].v_type = VAR_UNKNOWN; term_start(argvar, &opt, FALSE, eap->forceit); vim_free(tofree); + +theend: vim_free(opt.jo_eof_chars); } @@ -758,6 +775,7 @@ free_terminal(buf_T *buf) #ifdef FEAT_SESSION vim_free(term->tl_command); #endif + vim_free(term->tl_kill); vim_free(term->tl_status_text); vim_free(term->tl_opencmd); vim_free(term->tl_eof_chars); @@ -1081,6 +1099,56 @@ term_none_open(term_T *term) } /* + * Used when exiting: kill the job in "buf" if so desired. + * Return OK when the job finished. + * Return FAIL when the job is still running. + */ + int +term_try_stop_job(buf_T *buf) +{ + int count; + char *how = (char *)buf->b_term->tl_kill; + +#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) + if ((how == NULL || *how == NUL) && (p_confirm || cmdmod.confirm)) + { + char_u buff[DIALOG_MSG_SIZE]; + int ret; + + dialog_msg(buff, _("Kill job in \"%s\"?"), buf->b_fname); + ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1); + if (ret == VIM_YES) + how = "kill"; + else if (ret == VIM_CANCEL) + return FAIL; + } +#endif + if (how == NULL || *how == NUL) + return FAIL; + + job_stop(buf->b_term->tl_job, NULL, how); + + /* wait for up to a second for the job to die */ + for (count = 0; count < 100; ++count) + { + /* buffer, terminal and job may be cleaned up while waiting */ + if (!buf_valid(buf) + || buf->b_term == NULL + || buf->b_term->tl_job == NULL) + return OK; + + /* call job_status() to update jv_status */ + job_status(buf->b_term->tl_job); + if (buf->b_term->tl_job->jv_status >= JOB_ENDED) + return OK; + ui_delay(10L, FALSE); + mch_check_messages(); + parse_queued_messages(); + } + return FAIL; +} + +/* * Add the last line of the scrollback buffer to the buffer in the window. */ static void @@ -2922,10 +2990,11 @@ set_terminal_default_colors(int cterm_fg /* * Get the buffer from the first argument in "argvars". - * Returns NULL when the buffer is not for a terminal window. + * Returns NULL when the buffer is not for a terminal window and logs a message + * with "where". */ static buf_T * -term_get_buf(typval_T *argvars) +term_get_buf(typval_T *argvars, char *where) { buf_T *buf; @@ -2934,7 +3003,10 @@ term_get_buf(typval_T *argvars) buf = get_buf_tv(&argvars[0], FALSE); --emsg_off; if (buf == NULL || buf->b_term == NULL) + { + ch_log(NULL, "%s: invalid buffer argument", where); return NULL; + } return buf; } @@ -2980,7 +3052,7 @@ dump_term_color(FILE *fd, VTermColor *co void f_term_dumpwrite(typval_T *argvars, typval_T *rettv UNUSED) { - buf_T *buf = term_get_buf(argvars); + buf_T *buf = term_get_buf(argvars, "term_dumpwrite()"); term_T *term; char_u *fname; int max_height = 0; @@ -3719,7 +3791,7 @@ f_term_dumpload(typval_T *argvars, typva void f_term_getaltscreen(typval_T *argvars, typval_T *rettv) { - buf_T *buf = term_get_buf(argvars); + buf_T *buf = term_get_buf(argvars, "term_getaltscreen()"); if (buf == NULL) return; @@ -3766,7 +3838,7 @@ f_term_getattr(typval_T *argvars, typval void f_term_getcursor(typval_T *argvars, typval_T *rettv) { - buf_T *buf = term_get_buf(argvars); + buf_T *buf = term_get_buf(argvars, "term_getcursor()"); term_T *term; list_T *l; dict_T *d; @@ -3800,7 +3872,7 @@ f_term_getcursor(typval_T *argvars, typv void f_term_getjob(typval_T *argvars, typval_T *rettv) { - buf_T *buf = term_get_buf(argvars); + buf_T *buf = term_get_buf(argvars, "term_getjob()"); rettv->v_type = VAR_JOB; rettv->vval.v_job = NULL; @@ -3828,7 +3900,7 @@ get_row_number(typval_T *tv, term_T *ter void f_term_getline(typval_T *argvars, typval_T *rettv) { - buf_T *buf = term_get_buf(argvars); + buf_T *buf = term_get_buf(argvars, "term_getline()"); term_T *term; int row; @@ -3875,7 +3947,7 @@ f_term_getline(typval_T *argvars, typval void f_term_getscrolled(typval_T *argvars, typval_T *rettv) { - buf_T *buf = term_get_buf(argvars); + buf_T *buf = term_get_buf(argvars, "term_getscrolled()"); if (buf == NULL) return; @@ -3888,7 +3960,7 @@ f_term_getscrolled(typval_T *argvars, ty void f_term_getsize(typval_T *argvars, typval_T *rettv) { - buf_T *buf = term_get_buf(argvars); + buf_T *buf = term_get_buf(argvars, "term_getsize()"); list_T *l; if (rettv_list_alloc(rettv) == FAIL) @@ -3907,7 +3979,7 @@ f_term_getsize(typval_T *argvars, typval void f_term_getstatus(typval_T *argvars, typval_T *rettv) { - buf_T *buf = term_get_buf(argvars); + buf_T *buf = term_get_buf(argvars, "term_getstatus()"); term_T *term; char_u val[100]; @@ -3931,7 +4003,7 @@ f_term_getstatus(typval_T *argvars, typv void f_term_gettitle(typval_T *argvars, typval_T *rettv) { - buf_T *buf = term_get_buf(argvars); + buf_T *buf = term_get_buf(argvars, "term_gettitle()"); rettv->v_type = VAR_STRING; if (buf == NULL) @@ -3947,7 +4019,7 @@ f_term_gettitle(typval_T *argvars, typva void f_term_gettty(typval_T *argvars, typval_T *rettv) { - buf_T *buf = term_get_buf(argvars); + buf_T *buf = term_get_buf(argvars, "term_gettty()"); char_u *p; int num = 0; @@ -4005,7 +4077,7 @@ f_term_list(typval_T *argvars UNUSED, ty void f_term_scrape(typval_T *argvars, typval_T *rettv) { - buf_T *buf = term_get_buf(argvars); + buf_T *buf = term_get_buf(argvars, "term_scrape()"); VTermScreen *screen = NULL; VTermPos pos; list_T *l; @@ -4114,7 +4186,7 @@ f_term_scrape(typval_T *argvars, typval_ void f_term_sendkeys(typval_T *argvars, typval_T *rettv) { - buf_T *buf = term_get_buf(argvars); + buf_T *buf = term_get_buf(argvars, "term_sendkeys()"); char_u *msg; term_T *term; @@ -4143,7 +4215,7 @@ f_term_sendkeys(typval_T *argvars, typva f_term_setrestore(typval_T *argvars UNUSED, typval_T *rettv UNUSED) { #if defined(FEAT_SESSION) - buf_T *buf = term_get_buf(argvars); + buf_T *buf = term_get_buf(argvars, "term_setrestore()"); term_T *term; char_u *cmd; @@ -4160,6 +4232,27 @@ f_term_setrestore(typval_T *argvars UNUS } /* + * "term_setkill(buf, how)" function + */ + void +f_term_setkill(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ + buf_T *buf = term_get_buf(argvars, "term_setkill()"); + term_T *term; + char_u *how; + + if (buf == NULL) + return; + term = buf->b_term; + vim_free(term->tl_kill); + how = get_tv_string_chk(&argvars[1]); + if (how != NULL) + term->tl_kill = vim_strsave(how); + else + term->tl_kill = NULL; +} + +/* * "term_start(command, options)" function */ void @@ -4177,7 +4270,7 @@ f_term_start(typval_T *argvars, typval_T JO2_TERM_NAME + JO2_TERM_FINISH + JO2_HIDDEN + JO2_TERM_OPENCMD + JO2_TERM_COLS + JO2_TERM_ROWS + JO2_VERTICAL + JO2_CURWIN + JO2_CWD + JO2_ENV + JO2_EOF_CHARS - + JO2_NORESTORE) == FAIL) + + JO2_NORESTORE + JO2_TERM_KILL) == FAIL) return; if (opt.jo_vertical) @@ -4194,13 +4287,10 @@ f_term_start(typval_T *argvars, typval_T void f_term_wait(typval_T *argvars, typval_T *rettv UNUSED) { - buf_T *buf = term_get_buf(argvars); + buf_T *buf = term_get_buf(argvars, "term_wait()"); if (buf == NULL) - { - ch_log(NULL, "term_wait(): invalid argument"); return; - } if (buf->b_term->tl_job == NULL) { ch_log(NULL, "term_wait(): no job to wait for");