Skip to content

Commit 25cdd9c

Browse files
committed
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.
1 parent b5b7562 commit 25cdd9c

File tree

10 files changed

+225
-39
lines changed

10 files changed

+225
-39
lines changed

runtime/doc/eval.txt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*eval.txt* For Vim version 8.0. Last change: 2018 Mar 09
1+
*eval.txt* For Vim version 8.0. Last change: 2018 Mar 10
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -2435,6 +2435,7 @@ term_gettty({buf}, [{input}]) String get the tty name of a terminal
24352435
term_list() List get the list of terminal buffers
24362436
term_scrape({buf}, {row}) List get row of a terminal screen
24372437
term_sendkeys({buf}, {keys}) none send keystrokes to a terminal
2438+
term_setkill({buf}, {how}) none set signal to stop job in terminal
24382439
term_setrestore({buf}, {command}) none set command to restore terminal
24392440
term_start({cmd}, {options}) Job open a terminal window and run a job
24402441
term_wait({buf} [, {time}]) Number wait for screen to be updated
@@ -8276,6 +8277,8 @@ term_getline({buf}, {row}) *term_getline()*
82768277
The first line has {row} one. When {row} is "." the cursor
82778278
line is used. When {row} is invalid an empty string is
82788279
returned.
8280+
8281+
To get attributes of each character use |term_scrape()|.
82798282
{only available when compiled with the |+terminal| feature}
82808283

82818284
term_getscrolled({buf}) *term_getscrolled()*
@@ -8361,6 +8364,18 @@ term_sendkeys({buf}, {keys}) *term_sendkeys()*
83618364
means the character CTRL-X.
83628365
{only available when compiled with the |+terminal| feature}
83638366

8367+
term_setkill({buf}, {how}) *term_setkill()*
8368+
When exiting Vim or trying to close the terminal window in
8369+
another way, {how} defines whether the job in the terminal can
8370+
be stopped.
8371+
When {how} is empty (the default), the job will not be
8372+
stopped, trying to exit will result in |E947|.
8373+
Otherwise, {how} specifies what signal to send to the job.
8374+
See |job_stop()| for the values.
8375+
8376+
After sending the signal Vim will wait for up to a second to
8377+
check that the job actually stopped.
8378+
83648379
term_setrestore({buf}, {command}) *term_setrestore()*
83658380
Set the command to write in a session file to restore the job
83668381
in this terminal. The line written in the session file is: >
@@ -8416,6 +8431,8 @@ term_start({cmd}, {options}) *term_start()*
84168431
"hidden" do not open a window
84178432
"norestore" do not add the terminal window to a
84188433
session file
8434+
"term_kill" what to do when trying to close the
8435+
terminal window, see |term_setkill()|
84198436
"term_finish" What to do when the job is finished:
84208437
"close": close any windows
84218438
"open": open window if needed

runtime/doc/terminal.txt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*terminal.txt* For Vim version 8.0. Last change: 2018 Mar 09
1+
*terminal.txt* For Vim version 8.0. Last change: 2018 Mar 10
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -166,6 +166,9 @@ Syntax ~
166166
no window will be used.
167167
++norestore Do not include this terminal window
168168
in a session file.
169+
++kill={how} When trying to close the terminal
170+
window kill the job with {how}. See
171+
|term_setkill()| for the values.
169172
++rows={height} Use {height} for the terminal window
170173
height. If the terminal uses the full
171174
Vim height (no window above or below
@@ -189,8 +192,12 @@ Syntax ~
189192
If you want to use more options use the |term_start()|
190193
function.
191194

192-
When the buffer associated with the terminal is unloaded or wiped out the job
193-
is killed, similar to calling `job_stop(job, "kill")`
195+
When the buffer associated with the terminal is forcibly unloaded or wiped out
196+
the job is killed, similar to calling `job_stop(job, "kill")` .
197+
Closing the window normally results in |E947|. When a kill method was set
198+
with "++kill={how}" or |term_setkill()| then closing the window will use that
199+
way to kill or interrupt the job. For example: >
200+
:term ++kill=term tail -f /tmp/log
194201
195202
So long as the job is running the window behaves like it contains a modified
196203
buffer. Trying to close the window with `CTRL-W :quit` fails. When using

src/channel.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4746,50 +4746,57 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported, int supported2)
47464746
{
47474747
if (!(supported2 & JO2_TERM_ROWS))
47484748
break;
4749-
opt->jo_set |= JO2_TERM_ROWS;
4749+
opt->jo_set2 |= JO2_TERM_ROWS;
47504750
opt->jo_term_rows = get_tv_number(item);
47514751
}
47524752
else if (STRCMP(hi->hi_key, "term_cols") == 0)
47534753
{
47544754
if (!(supported2 & JO2_TERM_COLS))
47554755
break;
4756-
opt->jo_set |= JO2_TERM_COLS;
4756+
opt->jo_set2 |= JO2_TERM_COLS;
47574757
opt->jo_term_cols = get_tv_number(item);
47584758
}
47594759
else if (STRCMP(hi->hi_key, "vertical") == 0)
47604760
{
47614761
if (!(supported2 & JO2_VERTICAL))
47624762
break;
4763-
opt->jo_set |= JO2_VERTICAL;
4763+
opt->jo_set2 |= JO2_VERTICAL;
47644764
opt->jo_vertical = get_tv_number(item);
47654765
}
47664766
else if (STRCMP(hi->hi_key, "curwin") == 0)
47674767
{
47684768
if (!(supported2 & JO2_CURWIN))
47694769
break;
4770-
opt->jo_set |= JO2_CURWIN;
4770+
opt->jo_set2 |= JO2_CURWIN;
47714771
opt->jo_curwin = get_tv_number(item);
47724772
}
47734773
else if (STRCMP(hi->hi_key, "hidden") == 0)
47744774
{
47754775
if (!(supported2 & JO2_HIDDEN))
47764776
break;
4777-
opt->jo_set |= JO2_HIDDEN;
4777+
opt->jo_set2 |= JO2_HIDDEN;
47784778
opt->jo_hidden = get_tv_number(item);
47794779
}
47804780
else if (STRCMP(hi->hi_key, "norestore") == 0)
47814781
{
47824782
if (!(supported2 & JO2_NORESTORE))
47834783
break;
4784-
opt->jo_set |= JO2_NORESTORE;
4784+
opt->jo_set2 |= JO2_NORESTORE;
47854785
opt->jo_term_norestore = get_tv_number(item);
47864786
}
4787+
else if (STRCMP(hi->hi_key, "term_kill") == 0)
4788+
{
4789+
if (!(supported2 & JO2_TERM_KILL))
4790+
break;
4791+
opt->jo_set2 |= JO2_TERM_KILL;
4792+
opt->jo_term_kill = get_tv_string_chk(item);
4793+
}
47874794
#endif
47884795
else if (STRCMP(hi->hi_key, "env") == 0)
47894796
{
47904797
if (!(supported2 & JO2_ENV))
47914798
break;
4792-
opt->jo_set |= JO2_ENV;
4799+
opt->jo_set2 |= JO2_ENV;
47934800
opt->jo_env = item->vval.v_dict;
47944801
++item->vval.v_dict->dv_refcount;
47954802
}
@@ -4803,7 +4810,7 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported, int supported2)
48034810
EMSG2(_(e_invargval), "cwd");
48044811
return FAIL;
48054812
}
4806-
opt->jo_set |= JO2_CWD;
4813+
opt->jo_set2 |= JO2_CWD;
48074814
}
48084815
else if (STRCMP(hi->hi_key, "waittime") == 0)
48094816
{

src/evalfunc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,7 @@ static struct fst
867867
{"term_list", 0, 0, f_term_list},
868868
{"term_scrape", 2, 2, f_term_scrape},
869869
{"term_sendkeys", 2, 2, f_term_sendkeys},
870+
{"term_setkill", 2, 2, f_term_setkill},
870871
{"term_setrestore", 2, 2, f_term_setrestore},
871872
{"term_start", 1, 2, f_term_start},
872873
{"term_wait", 1, 2, f_term_wait},

src/ex_cmds2.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2254,7 +2254,7 @@ add_bufnum(int *bufnrs, int *bufnump, int nr)
22542254
/*
22552255
* Return TRUE if any buffer was changed and cannot be abandoned.
22562256
* That changed buffer becomes the current buffer.
2257-
* When "unload" is true the current buffer is unloaded instead of making it
2257+
* When "unload" is TRUE the current buffer is unloaded instead of making it
22582258
* hidden. This is used for ":q!".
22592259
*/
22602260
int
@@ -2272,6 +2272,7 @@ check_changed_any(
22722272
tabpage_T *tp;
22732273
win_T *wp;
22742274

2275+
/* Make a list of all buffers, with the most important ones first. */
22752276
FOR_ALL_BUFFERS(buf)
22762277
++bufcount;
22772278

@@ -2284,17 +2285,19 @@ check_changed_any(
22842285

22852286
/* curbuf */
22862287
bufnrs[bufnum++] = curbuf->b_fnum;
2287-
/* buf in curtab */
2288+
2289+
/* buffers in current tab */
22882290
FOR_ALL_WINDOWS(wp)
22892291
if (wp->w_buffer != curbuf)
22902292
add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum);
22912293

2292-
/* buf in other tab */
2294+
/* buffers in other tabs */
22932295
FOR_ALL_TABPAGES(tp)
22942296
if (tp != curtab)
22952297
for (wp = tp->tp_firstwin; wp != NULL; wp = wp->w_next)
22962298
add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum);
2297-
/* any other buf */
2299+
2300+
/* any other buffer */
22982301
FOR_ALL_BUFFERS(buf)
22992302
add_bufnum(bufnrs, &bufnum, buf->b_fnum);
23002303

@@ -2308,6 +2311,14 @@ check_changed_any(
23082311
bufref_T bufref;
23092312

23102313
set_bufref(&bufref, buf);
2314+
#ifdef FEAT_TERMINAL
2315+
if (term_job_running(buf->b_term))
2316+
{
2317+
if (term_try_stop_job(buf) == FAIL)
2318+
break;
2319+
}
2320+
else
2321+
#endif
23112322
/* Try auto-writing the buffer. If this fails but the buffer no
23122323
* longer exists it's not changed, that's OK. */
23132324
if (check_changed(buf, (p_awa ? CCGD_AW : 0)
@@ -2320,6 +2331,7 @@ check_changed_any(
23202331
if (i >= bufnum)
23212332
goto theend;
23222333

2334+
/* Get here if "buf" cannot be abandoned. */
23232335
ret = TRUE;
23242336
exiting = FALSE;
23252337
#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)

src/proto/terminal.pro

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
void ex_terminal(exarg_T *eap);
33
int term_write_session(FILE *fd, win_T *wp);
44
int term_should_restore(buf_T *buf);
5-
void f_term_setrestore(typval_T *argvars, typval_T *rettv);
65
void free_terminal(buf_T *buf);
76
void write_to_term(buf_T *buffer, char_u *msg, channel_T *channel);
87
int term_job_running(term_T *term);
98
int term_none_open(term_T *term);
9+
int term_try_stop_job(buf_T *buf);
1010
int term_in_normal_mode(void);
1111
void term_enter_job_mode(void);
1212
int send_keys_to_term(term_T *term, int c, int typed);
@@ -41,6 +41,8 @@ void f_term_gettty(typval_T *argvars, typval_T *rettv);
4141
void f_term_list(typval_T *argvars, typval_T *rettv);
4242
void f_term_scrape(typval_T *argvars, typval_T *rettv);
4343
void f_term_sendkeys(typval_T *argvars, typval_T *rettv);
44+
void f_term_setrestore(typval_T *argvars, typval_T *rettv);
45+
void f_term_setkill(typval_T *argvars, typval_T *rettv);
4446
void f_term_start(typval_T *argvars, typval_T *rettv);
4547
void f_term_wait(typval_T *argvars, typval_T *rettv);
4648
void term_send_eof(channel_T *ch);

src/structs.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1707,7 +1707,8 @@ struct channel_S {
17071707
#define JO2_TERM_OPENCMD 0x0800 /* "term_opencmd" */
17081708
#define JO2_EOF_CHARS 0x1000 /* "eof_chars" */
17091709
#define JO2_NORESTORE 0x2000 /* "norestore" */
1710-
#define JO2_ALL 0x2FFF
1710+
#define JO2_TERM_KILL 0x4000 /* "term_kill" */
1711+
#define JO2_ALL 0x7FFF
17111712

17121713
#define JO_MODE_ALL (JO_MODE + JO_IN_MODE + JO_OUT_MODE + JO_ERR_MODE)
17131714
#define JO_CB_ALL \
@@ -1775,6 +1776,7 @@ typedef struct
17751776
char_u *jo_term_opencmd;
17761777
int jo_term_finish;
17771778
char_u *jo_eof_chars;
1779+
char_u *jo_term_kill;
17781780
#endif
17791781
} jobopt_T;
17801782

0 commit comments

Comments
 (0)