To: vim_dev@googlegroups.com Subject: Patch 8.1.2195 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.2195 Problem: Vim does not exit when closing a terminal window and it is the last window. Solution: Exit Vim if the closed terminal window is the last one. (closes #4539) Files: runtime/doc/terminal.txt, src/terminal.c, src/ex_docmd.c, src/proto/ex_docmd.pro, src/testdir/test_terminal.vim *** ../vim-8.1.2194/runtime/doc/terminal.txt 2019-09-26 23:08:10.501926883 +0200 --- runtime/doc/terminal.txt 2019-10-20 20:48:49.546100837 +0200 *************** *** 193,198 **** --- 193,199 ---- Supported [options] are: ++close The terminal window will close automatically when the job terminates. + |terminal-close| ++noclose The terminal window will NOT close automatically when the job terminates. ++open When the job terminates and no window *************** *** 267,272 **** --- 268,279 ---- current window into a terminal window. If there are unsaved changes this fails, use ! to force, as usual. + *terminal-close* + When the terminal window is closed, e.g. when the shell exits and "++close" + argument was used, and this is the last normal Vim window, then Vim will exit. + This is like using |:quit| in a normal window. Help and preview windows are + not counted. + To have a background job run without a window, and open the window when it's done, use options like this: > :term ++hidden ++open make *** ../vim-8.1.2194/src/terminal.c 2019-10-13 16:43:35.960359646 +0200 --- src/terminal.c 2019-10-20 21:14:37.018062727 +0200 *************** *** 3073,3078 **** --- 3073,3088 ---- aco_save_T aco; int do_set_w_closing = term->tl_buffer->b_nwindows == 0; + // If this is the last normal window: exit Vim. + if (term->tl_buffer->b_nwindows > 0 && only_one_window()) + { + exarg_T ea; + + vim_memset(&ea, 0, sizeof(ea)); + ex_quit(&ea); + return TRUE; + } + // ++close or term_finish == "close" ch_log(NULL, "terminal job finished, closing window"); aucmd_prepbuf(&aco, term->tl_buffer); *** ../vim-8.1.2194/src/ex_docmd.c 2019-10-19 21:01:01.607226710 +0200 --- src/ex_docmd.c 2019-10-20 20:45:14.927240120 +0200 *************** *** 87,93 **** static char_u *repl_cmdline(exarg_T *eap, char_u *src, int srclen, char_u *repl, char_u **cmdlinep); static void ex_highlight(exarg_T *eap); static void ex_colorscheme(exarg_T *eap); - static void ex_quit(exarg_T *eap); static void ex_cquit(exarg_T *eap); static void ex_quit_all(exarg_T *eap); static void ex_close(exarg_T *eap); --- 87,92 ---- *************** *** 4842,4849 **** /* * ":quit": quit current window, quit Vim if the last window is closed. * ":{nr}quit": quit window {nr} */ ! static void ex_quit(exarg_T *eap) { win_T *wp; --- 4841,4849 ---- /* * ":quit": quit current window, quit Vim if the last window is closed. * ":{nr}quit": quit window {nr} + * Also used when closing a terminal window that's the last one. */ ! void ex_quit(exarg_T *eap) { win_T *wp; *** ../vim-8.1.2194/src/proto/ex_docmd.pro 2019-08-23 21:17:30.651058449 +0200 --- src/proto/ex_docmd.pro 2019-10-20 20:44:12.023576986 +0200 *************** *** 15,27 **** void ex_ni(exarg_T *eap); int expand_filename(exarg_T *eap, char_u **cmdlinep, char **errormsgp); void separate_nextcmd(exarg_T *eap); ! char_u *skip_cmd_arg( char_u *p, int rembs); int get_bad_opt(char_u *p, exarg_T *eap); int ends_excmd(int c); char_u *find_nextcmd(char_u *p); char_u *check_nextcmd(char_u *p); char_u *get_command_name(expand_T *xp, int idx); void not_exiting(void); void tabpage_close(int forceit); void tabpage_close_other(tabpage_T *tp, int forceit); void handle_drop(int filec, char_u **filev, int split, void (*callback)(void *), void *cookie); --- 15,28 ---- void ex_ni(exarg_T *eap); int expand_filename(exarg_T *eap, char_u **cmdlinep, char **errormsgp); void separate_nextcmd(exarg_T *eap); ! char_u *skip_cmd_arg(char_u *p, int rembs); int get_bad_opt(char_u *p, exarg_T *eap); int ends_excmd(int c); char_u *find_nextcmd(char_u *p); char_u *check_nextcmd(char_u *p); char_u *get_command_name(expand_T *xp, int idx); void not_exiting(void); + void ex_quit(exarg_T *eap); void tabpage_close(int forceit); void tabpage_close_other(tabpage_T *tp, int forceit); void handle_drop(int filec, char_u **filev, int split, void (*callback)(void *), void *cookie); *************** *** 30,37 **** void tabpage_new(void); void do_exedit(exarg_T *eap, win_T *old_curwin); void free_cd_dir(void); ! void post_chdir(cdscope_T cdscope); ! int changedir_func(char_u *new_dir, int forceit, cdscope_T cdscope); void ex_cd(exarg_T *eap); void do_sleep(long msec); void ex_may_print(exarg_T *eap); --- 31,38 ---- void tabpage_new(void); void do_exedit(exarg_T *eap, win_T *old_curwin); void free_cd_dir(void); ! void post_chdir(cdscope_T scope); ! int changedir_func(char_u *new_dir, int forceit, cdscope_T scope); void ex_cd(exarg_T *eap); void do_sleep(long msec); void ex_may_print(exarg_T *eap); *************** *** 47,54 **** int find_cmdline_var(char_u *src, int *usedlen); char_u *eval_vars(char_u *src, char_u *srcstart, int *usedlen, linenr_T *lnump, char **errormsg, int *escaped); char_u *expand_sfile(char_u *arg); - int put_eol(FILE *fd); - int put_line(FILE *fd, char *s); void dialog_msg(char_u *buff, char *format, char_u *fname); void set_no_hlsearch(int flag); int is_loclist_cmd(int cmdidx); --- 48,53 ---- *** ../vim-8.1.2194/src/testdir/test_terminal.vim 2019-10-16 18:11:13.706363954 +0200 --- src/testdir/test_terminal.vim 2019-10-20 21:05:06.777009081 +0200 *************** *** 1051,1056 **** --- 1051,1082 ---- quit endfunc + " Run Vim in a terminal, then start a terminal window with a shell and check + " that Vim exits if it is closed. + func Test_terminal_exit() + CheckRunVimInTerminal + + let lines =<< trim END + let winid = win_getid() + help + term + let termid = win_getid() + call win_gotoid(winid) + close + call win_gotoid(termid) + END + call writefile(lines, 'XtermExit') + let buf = RunVimInTerminal('-S XtermExit', #{rows: 10}) + let job = term_getjob(buf) + call WaitForAssert({-> assert_equal("run", job_status(job))}) + + " quit the shell, it will make Vim exit + call term_sendkeys(buf, "exit\") + call WaitForAssert({-> assert_equal("dead", job_status(job))}) + + call delete('XtermExit') + endfunc + func Test_terminal_open_autocmd() augroup repro au! *** ../vim-8.1.2194/src/version.c 2019-10-20 19:53:19.042101570 +0200 --- src/version.c 2019-10-20 20:50:53.001450879 +0200 *************** *** 743,744 **** --- 743,746 ---- { /* Add new patch number below this line */ + /**/ + 2195, /**/ -- Looking at Perl through Lisp glasses, Perl looks atrocious. /// 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 ///