Skip to content

Commit b15a5a5

Browse files
committed
Merge remote-tracking branch 'vim/master'
2 parents c5520ee + fe38664 commit b15a5a5

13 files changed

Lines changed: 460 additions & 162 deletions

File tree

Filelist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,7 @@ RT_ALL = \
638638
runtime/pack/dist/opt/matchit/doc/tags \
639639
runtime/pack/dist/opt/shellmenu/plugin/shellmenu.vim \
640640
runtime/pack/dist/opt/swapmouse/plugin/swapmouse.vim \
641+
runtime/pack/dist/opt/termdebug/plugin/termdebug.vim \
641642

642643
# runtime files for all distributions without CR-NL translation
643644
RT_ALL_BIN = \

runtime/doc/eval.txt

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2401,7 +2401,7 @@ term_getscrolled({buf}) Number get the scroll count of a terminal
24012401
term_getsize({buf}) List get the size of a terminal
24022402
term_getstatus({buf}) String get the status of a terminal
24032403
term_gettitle({buf}) String get the title of a terminal
2404-
term_gettty({buf}) String get the tty name of a terminal
2404+
term_getttty({buf}, [{input}]) String get the tty name of a terminal
24052405
term_list() List get the list of terminal buffers
24062406
term_scrape({buf}, {row}) List get row of a terminal screen
24072407
term_sendkeys({buf}, {keys}) none send keystrokes to a terminal
@@ -5245,7 +5245,8 @@ job_info({job}) *job_info()*
52455245
"status" what |job_status()| returns
52465246
"channel" what |job_getchannel()| returns
52475247
"process" process ID
5248-
"tty" controlling terminal name, empty when none
5248+
"tty_in" terminal input name, empty when none
5249+
"tty_out" terminal output name, empty when none
52495250
"exitval" only valid when "status" is "dead"
52505251
"exit_cb" function to be called on exit
52515252
"stoponexit" |job-stoponexit|
@@ -8092,10 +8093,13 @@ term_gettitle({buf}) *term_gettitle()*
80928093
string is returned.
80938094
{only available when compiled with the |+terminal| feature}
80948095

8095-
term_gettty({buf}) *term_gettty()*
8096+
term_gettty({buf} [, {input}]) *term_gettty()*
80968097
Get the name of the controlling terminal associated with
8097-
terminal window {buf}.
8098-
{buf} is used as with |term_getsize()|.
8098+
terminal window {buf}. {buf} is used as with |term_getsize()|.
8099+
8100+
When {input} is omitted or 0, return the name for writing
8101+
(stdout). When {input} is 1 return the name for reading
8102+
(stdin). On UNIX, both return same name.
80998103
{only available when compiled with the |+terminal| feature}
81008104

81018105
term_list() *term_list()*
@@ -8173,10 +8177,9 @@ term_start({cmd}, {options}) *term_start()*
81738177
specified "botright sbuf %d" is used
81748178
"eof_chars" Text to send after all buffer lines were
81758179
written to the terminal. When not set
8176-
CTRL-D is used. For Python use CTRL-Z or
8177-
"exit()". For a shell use "exit". A CR
8178-
is always added.
8179-
{only on MS-Windows}
8180+
CTRL-D is used on MS-Windows. For Python
8181+
use CTRL-Z or "exit()". For a shell use
8182+
"exit". A CR is always added.
81808183

81818184
{only available when compiled with the |+terminal| feature}
81828185

Lines changed: 101 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,128 @@
1-
" Debugger commands.
1+
" Debugger plugin using gdb.
22
"
33
" WORK IN PROGRESS - much doesn't work yet
44
"
5-
" Open two terminal windows:
5+
" Open two visible terminal windows:
66
" 1. run a pty, as with ":term NONE"
77
" 2. run gdb, passing the pty
8-
" The current window is used to edit source code and follows gdb.
8+
" The current window is used to view source code and follows gdb.
9+
"
10+
" A third terminal window is hidden, it is used for communication with gdb.
11+
"
12+
" The communication with gdb uses GDB/MI. See:
13+
" https://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI.html
914
"
1015
" Author: Bram Moolenaar
11-
" Copyright: Vim license applies
16+
" Copyright: Vim license applies, see ":help license"
1217

18+
" The command that starts debugging, e.g. ":Termdebug vim".
19+
" To end type "quit" in the gdb window.
1320
command -nargs=* -complete=file Termdebug call s:StartDebug(<q-args>)
1421

22+
" Name of the gdb command, defaults to "gdb".
1523
if !exists('debugger')
1624
let debugger = 'gdb'
1725
endif
1826

27+
" Sign used to highlight the line where the program has stopped.
28+
sign define debugPC linehl=debugPC
29+
if &background == 'light'
30+
hi debugPC term=reverse ctermbg=lightblue guibg=lightblue
31+
else
32+
hi debugPC term=reverse ctermbg=darkblue guibg=darkblue
33+
endif
34+
let s:pc_id = 12
35+
1936
func s:StartDebug(cmd)
37+
let s:startwin = win_getid(winnr())
38+
let s:startsigncolumn = &signcolumn
39+
2040
" Open a terminal window without a job, to run the debugged program
21-
let s:ptybuf = term_start('NONE', {})
22-
let pty = job_info(term_getjob(s:ptybuf))['tty']
41+
let s:ptybuf = term_start('NONE', {
42+
\ 'term_name': 'gdb program',
43+
\ })
44+
if s:ptybuf == 0
45+
echoerr 'Failed to open the program terminal window'
46+
return
47+
endif
48+
let pty = job_info(term_getjob(s:ptybuf))['tty_out']
49+
50+
" Create a hidden terminal window to communicate with gdb
51+
let s:commbuf = term_start('NONE', {
52+
\ 'term_name': 'gdb communication',
53+
\ 'out_cb': function('s:CommOutput'),
54+
\ 'hidden': 1,
55+
\ })
56+
if s:commbuf == 0
57+
echoerr 'Failed to open the communication terminal window'
58+
exe 'bwipe! ' . s:ptybuf
59+
return
60+
endif
61+
let commpty = job_info(term_getjob(s:commbuf))['tty_out']
2362

2463
" Open a terminal window to run the debugger.
2564
let cmd = [g:debugger, '-tty', pty, a:cmd]
2665
echomsg 'executing "' . join(cmd) . '"'
2766
let gdbbuf = term_start(cmd, {
2867
\ 'exit_cb': function('s:EndDebug'),
29-
\ 'term_finish': 'close'
68+
\ 'term_finish': 'close',
3069
\ })
70+
if gdbbuf == 0
71+
echoerr 'Failed to open the gdb terminal window'
72+
exe 'bwipe! ' . s:ptybuf
73+
exe 'bwipe! ' . s:commbuf
74+
return
75+
endif
76+
77+
" Connect gdb to the communication pty, using the GDB/MI interface
78+
call term_sendkeys(gdbbuf, 'new-ui mi ' . commpty . "\r")
3179
endfunc
3280

3381
func s:EndDebug(job, status)
34-
exe 'bwipe! ' . s:ptybuf
82+
exe 'bwipe! ' . s:ptybuf
83+
exe 'bwipe! ' . s:commbuf
84+
call setwinvar(s:startwin, '&signcolumn', s:startsigncolumn)
85+
endfunc
86+
87+
" Handle a message received from gdb on the GDB/MI interface.
88+
func s:CommOutput(chan, msg)
89+
let msgs = split(a:msg, "\r")
90+
91+
for msg in msgs
92+
" remove prefixed NL
93+
if msg[0] == "\n"
94+
let msg = msg[1:]
95+
endif
96+
if msg != ''
97+
if msg =~ '^\*\(stopped\|running\)'
98+
let wid = win_getid(winnr())
99+
100+
if win_gotoid(s:startwin)
101+
if msg =~ '^\*stopped'
102+
" TODO: proper parsing
103+
let fname = substitute(msg, '.*fullname="\([^"]*\)".*', '\1', '')
104+
let lnum = substitute(msg, '.*line="\([^"]*\)".*', '\1', '')
105+
if lnum =~ '^[0-9]*$'
106+
if expand('%:h') != fname
107+
if &modified
108+
" TODO: find existing window
109+
exe 'split ' . fnameescape(fname)
110+
let s:startwin = win_getid(winnr())
111+
else
112+
exe 'edit ' . fnameescape(fname)
113+
endif
114+
endif
115+
exe lnum
116+
exe 'sign place ' . s:pc_id . ' line=' . lnum . ' name=debugPC file=' . fnameescape(fname)
117+
setlocal signcolumn=yes
118+
endif
119+
else
120+
exe 'sign unplace ' . s:pc_id
121+
endif
122+
123+
call win_gotoid(wid)
124+
endif
125+
endif
126+
endif
127+
endfor
35128
endfunc

src/buffer.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3925,8 +3925,8 @@ build_stl_str_hl(
39253925
char_u *t;
39263926
int byteval;
39273927
#ifdef FEAT_EVAL
3928-
win_T *o_curwin;
3929-
buf_T *o_curbuf;
3928+
win_T *save_curwin;
3929+
buf_T *save_curbuf;
39303930
#endif
39313931
int empty_line;
39323932
colnr_T virtcol;
@@ -3968,6 +3968,9 @@ build_stl_str_hl(
39683968
char_u tmp[TMPLEN];
39693969
char_u *usefmt = fmt;
39703970
struct stl_hlrec *sp;
3971+
int save_must_redraw = must_redraw;
3972+
int save_redr_type = curwin->w_redr_type;
3973+
int save_highlight_shcnaged = need_highlight_changed;
39713974

39723975
#ifdef FEAT_EVAL
39733976
/*
@@ -4277,15 +4280,15 @@ build_stl_str_hl(
42774280
vim_snprintf((char *)tmp, sizeof(tmp), "%d", curbuf->b_fnum);
42784281
set_internal_string_var((char_u *)"actual_curbuf", tmp);
42794282

4280-
o_curbuf = curbuf;
4281-
o_curwin = curwin;
4283+
save_curbuf = curbuf;
4284+
save_curwin = curwin;
42824285
curwin = wp;
42834286
curbuf = wp->w_buffer;
42844287

42854288
str = eval_to_string_safe(p, &t, use_sandbox);
42864289

4287-
curwin = o_curwin;
4288-
curbuf = o_curbuf;
4290+
curwin = save_curwin;
4291+
curbuf = save_curbuf;
42894292
do_unlet((char_u *)"g:actual_curbuf", TRUE);
42904293

42914294
if (str != NULL && *str != 0)
@@ -4740,6 +4743,13 @@ build_stl_str_hl(
47404743
sp->userhl = 0;
47414744
}
47424745

4746+
/* We do not want redrawing a stausline, ruler, title, etc. to trigger
4747+
* another redraw, it may cause an endless loop. This happens when a
4748+
* statusline changes a highlight group. */
4749+
must_redraw = save_must_redraw;
4750+
curwin->w_redr_type = save_redr_type;
4751+
need_highlight_changed = save_highlight_shcnaged;
4752+
47434753
return width;
47444754
}
47454755
#endif /* FEAT_STL_OPT */

src/channel.c

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,13 @@ ch_close_part(channel_T *channel, ch_part_T part)
990990
if ((part == PART_IN || channel->CH_IN_FD != *fd)
991991
&& (part == PART_OUT || channel->CH_OUT_FD != *fd)
992992
&& (part == PART_ERR || channel->CH_ERR_FD != *fd))
993+
{
994+
#ifdef WIN32
995+
if (channel->ch_named_pipe)
996+
DisconnectNamedPipe((HANDLE)fd);
997+
#endif
993998
fd_close(*fd);
999+
}
9941000
}
9951001
*fd = INVALID_FD;
9961002

@@ -3107,7 +3113,20 @@ channel_wait(channel_T *channel, sock_T fd, int timeout)
31073113
if (r && nread > 0)
31083114
return CW_READY;
31093115
if (r == 0)
3110-
return CW_ERROR;
3116+
{
3117+
DWORD err = GetLastError();
3118+
3119+
if (err != ERROR_BAD_PIPE && err != ERROR_BROKEN_PIPE)
3120+
return CW_ERROR;
3121+
3122+
if (channel->ch_named_pipe)
3123+
{
3124+
DisconnectNamedPipe((HANDLE)fd);
3125+
ConnectNamedPipe((HANDLE)fd, NULL);
3126+
}
3127+
else
3128+
return CW_ERROR;
3129+
}
31113130

31123131
/* perhaps write some buffer lines */
31133132
channel_write_any_lines();
@@ -3695,7 +3714,17 @@ channel_send(
36953714
if (part == PART_SOCK)
36963715
res = sock_write(fd, (char *)buf, len);
36973716
else
3717+
{
36983718
res = fd_write(fd, (char *)buf, len);
3719+
#ifdef WIN32
3720+
if (channel->ch_named_pipe && res < 0)
3721+
{
3722+
DisconnectNamedPipe((HANDLE)fd);
3723+
ConnectNamedPipe((HANDLE)fd, NULL);
3724+
}
3725+
#endif
3726+
3727+
}
36993728
if (res < 0 && (errno == EWOULDBLOCK
37003729
#ifdef EAGAIN
37013730
|| errno == EAGAIN
@@ -4077,6 +4106,7 @@ channel_select_check(int ret_in, void *rfds_in, void *wfds_in)
40774106
if (ret > 0 && fd != INVALID_FD && FD_ISSET(fd, rfds))
40784107
{
40794108
channel_read(channel, part, "channel_select_check");
4109+
FD_CLR(fd, rfds);
40804110
--ret;
40814111
}
40824112
}
@@ -4086,6 +4116,7 @@ channel_select_check(int ret_in, void *rfds_in, void *wfds_in)
40864116
&& FD_ISSET(in_part->ch_fd, wfds))
40874117
{
40884118
channel_write_input(channel);
4119+
FD_CLR(in_part->ch_fd, wfds);
40894120
--ret;
40904121
}
40914122
}
@@ -4874,7 +4905,8 @@ job_free_contents(job_T *job)
48744905
}
48754906
mch_clear_job(job);
48764907

4877-
vim_free(job->jv_tty_name);
4908+
vim_free(job->jv_tty_in);
4909+
vim_free(job->jv_tty_out);
48784910
vim_free(job->jv_stoponexit);
48794911
free_callback(job->jv_exit_cb, job->jv_exit_partial);
48804912
}
@@ -5528,8 +5560,10 @@ job_info(job_T *job, dict_T *dict)
55285560
nr = job->jv_proc_info.dwProcessId;
55295561
#endif
55305562
dict_add_nr_str(dict, "process", nr, NULL);
5531-
dict_add_nr_str(dict, "tty", 0L,
5532-
job->jv_tty_name != NULL ? job->jv_tty_name : (char_u *)"");
5563+
dict_add_nr_str(dict, "tty_in", 0L,
5564+
job->jv_tty_in != NULL ? job->jv_tty_in : (char_u *)"");
5565+
dict_add_nr_str(dict, "tty_out", 0L,
5566+
job->jv_tty_out != NULL ? job->jv_tty_out : (char_u *)"");
55335567

55345568
dict_add_nr_str(dict, "exitval", job->jv_exitval, NULL);
55355569
dict_add_nr_str(dict, "exit_cb", 0L, job->jv_exit_cb);

src/evalfunc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -843,7 +843,7 @@ static struct fst
843843
{"term_getsize", 1, 1, f_term_getsize},
844844
{"term_getstatus", 1, 1, f_term_getstatus},
845845
{"term_gettitle", 1, 1, f_term_gettitle},
846-
{"term_gettty", 1, 1, f_term_gettty},
846+
{"term_gettty", 1, 2, f_term_gettty},
847847
{"term_list", 0, 0, f_term_list},
848848
{"term_scrape", 2, 2, f_term_scrape},
849849
{"term_sendkeys", 2, 2, f_term_sendkeys},

src/os_unix.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5285,7 +5285,11 @@ mch_job_start(char **argv, job_T *job, jobopt_T *options)
52855285
&& (!(use_file_for_in || use_null_for_in)
52865286
|| !(use_file_for_in || use_null_for_out)
52875287
|| !(use_out_for_err || use_file_for_err || use_null_for_err)))
5288-
open_pty(&pty_master_fd, &pty_slave_fd, &job->jv_tty_name);
5288+
{
5289+
open_pty(&pty_master_fd, &pty_slave_fd, &job->jv_tty_out);
5290+
if (job->jv_tty_out != NULL)
5291+
job->jv_tty_in = vim_strsave(job->jv_tty_out);
5292+
}
52895293

52905294
/* TODO: without the channel feature connect the child to /dev/null? */
52915295
/* Open pipes for stdin, stdout, stderr. */
@@ -5709,7 +5713,9 @@ mch_create_pty_channel(job_T *job, jobopt_T *options)
57095713
int pty_slave_fd = -1;
57105714
channel_T *channel;
57115715

5712-
open_pty(&pty_master_fd, &pty_slave_fd, &job->jv_tty_name);
5716+
open_pty(&pty_master_fd, &pty_slave_fd, &job->jv_tty_out);
5717+
if (job->jv_tty_out != NULL)
5718+
job->jv_tty_in = vim_strsave(job->jv_tty_out);
57135719
close(pty_slave_fd);
57145720

57155721
channel = add_channel();

src/proto/terminal.pro

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ void ex_terminal(exarg_T *eap);
33
void free_terminal(buf_T *buf);
44
void write_to_term(buf_T *buffer, char_u *msg, channel_T *channel);
55
int term_job_running(term_T *term);
6+
int term_none_open(term_T *term);
67
int term_in_normal_mode(void);
78
void term_enter_job_mode(void);
89
int send_keys_to_term(term_T *term, int c, int typed);
@@ -16,7 +17,6 @@ int term_update_window(win_T *wp);
1617
int term_is_finished(buf_T *buf);
1718
int term_show_buffer(buf_T *buf);
1819
void term_change_in_curbuf(void);
19-
void term_send_eof(channel_T *ch);
2020
int term_get_attr(buf_T *buf, linenr_T lnum, int col);
2121
char_u *term_get_status_text(term_T *term);
2222
int set_ref_in_term(int copyID);
@@ -35,5 +35,6 @@ void f_term_scrape(typval_T *argvars, typval_T *rettv);
3535
void f_term_sendkeys(typval_T *argvars, typval_T *rettv);
3636
void f_term_start(typval_T *argvars, typval_T *rettv);
3737
void f_term_wait(typval_T *argvars, typval_T *rettv);
38+
void term_send_eof(channel_T *ch);
3839
int terminal_enabled(void);
3940
/* vim: set ft=c : */

0 commit comments

Comments
 (0)