forked from aniani/vim
patch 7.4.1398
Problem: The close-cb option is not implemented yet. Solution: Implemente close-cb. (Yasuhiro Matsumoto)
This commit is contained in:
@@ -485,7 +485,11 @@ static char *e_cannot_connect = N_("E902: Cannot connect to port");
|
|||||||
* Returns NULL for failure.
|
* Returns NULL for failure.
|
||||||
*/
|
*/
|
||||||
channel_T *
|
channel_T *
|
||||||
channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
|
channel_open(
|
||||||
|
char *hostname,
|
||||||
|
int port_in,
|
||||||
|
int waittime,
|
||||||
|
void (*nb_close_cb)(void))
|
||||||
{
|
{
|
||||||
int sd = -1;
|
int sd = -1;
|
||||||
struct sockaddr_in server;
|
struct sockaddr_in server;
|
||||||
@@ -711,7 +715,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
|
|||||||
}
|
}
|
||||||
|
|
||||||
channel->CH_SOCK_FD = (sock_T)sd;
|
channel->CH_SOCK_FD = (sock_T)sd;
|
||||||
channel->ch_close_cb = close_cb;
|
channel->ch_nb_close_cb = nb_close_cb;
|
||||||
|
|
||||||
#ifdef FEAT_GUI
|
#ifdef FEAT_GUI
|
||||||
channel_gui_register(channel);
|
channel_gui_register(channel);
|
||||||
@@ -790,6 +794,15 @@ channel_set_options(channel_T *channel, jobopt_T *opt)
|
|||||||
else
|
else
|
||||||
*cbp = NULL;
|
*cbp = NULL;
|
||||||
}
|
}
|
||||||
|
if (opt->jo_set & JO_CLOSE_CALLBACK)
|
||||||
|
{
|
||||||
|
cbp = &channel->ch_close_cb;
|
||||||
|
vim_free(*cbp);
|
||||||
|
if (opt->jo_close_cb != NULL && *opt->jo_close_cb != NUL)
|
||||||
|
*cbp = vim_strsave(opt->jo_close_cb);
|
||||||
|
else
|
||||||
|
*cbp = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1255,7 +1268,7 @@ may_invoke_callback(channel_T *channel, int part)
|
|||||||
ch_mode_T ch_mode = channel->ch_part[part].ch_mode;
|
ch_mode_T ch_mode = channel->ch_part[part].ch_mode;
|
||||||
char_u *callback = NULL;
|
char_u *callback = NULL;
|
||||||
|
|
||||||
if (channel->ch_close_cb != NULL)
|
if (channel->ch_nb_close_cb != NULL)
|
||||||
/* this channel is handled elsewhere (netbeans) */
|
/* this channel is handled elsewhere (netbeans) */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@@ -1477,7 +1490,28 @@ channel_close(channel_T *channel)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (channel->ch_close_cb != NULL)
|
||||||
|
{
|
||||||
|
typval_T argv[1];
|
||||||
|
typval_T rettv;
|
||||||
|
int dummy;
|
||||||
|
|
||||||
|
/* invoke the close callback; increment the refcount to avoid it
|
||||||
|
* being freed halfway */
|
||||||
|
argv[0].v_type = VAR_CHANNEL;
|
||||||
|
argv[0].vval.v_channel = channel;
|
||||||
|
++channel->ch_refcount;
|
||||||
|
call_func(channel->ch_close_cb, (int)STRLEN(channel->ch_close_cb),
|
||||||
|
&rettv, 1, argv, 0L, 0L, &dummy, TRUE, NULL);
|
||||||
|
clear_tv(&rettv);
|
||||||
|
--channel->ch_refcount;
|
||||||
|
|
||||||
|
/* the callback is only called once */
|
||||||
|
vim_free(channel->ch_close_cb);
|
||||||
channel->ch_close_cb = NULL;
|
channel->ch_close_cb = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
channel->ch_nb_close_cb = NULL;
|
||||||
channel_clear(channel);
|
channel_clear(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1539,6 +1573,8 @@ channel_clear(channel_T *channel)
|
|||||||
#endif
|
#endif
|
||||||
vim_free(channel->ch_callback);
|
vim_free(channel->ch_callback);
|
||||||
channel->ch_callback = NULL;
|
channel->ch_callback = NULL;
|
||||||
|
vim_free(channel->ch_close_cb);
|
||||||
|
channel->ch_close_cb = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(EXITFREE) || defined(PROTO)
|
#if defined(EXITFREE) || defined(PROTO)
|
||||||
@@ -1732,8 +1768,8 @@ channel_read(channel_T *channel, int part, char *func)
|
|||||||
* keep stdin and stderr open? Probably not, assume the other side
|
* keep stdin and stderr open? Probably not, assume the other side
|
||||||
* has died. */
|
* has died. */
|
||||||
channel_close(channel);
|
channel_close(channel);
|
||||||
if (channel->ch_close_cb != NULL)
|
if (channel->ch_nb_close_cb != NULL)
|
||||||
(*channel->ch_close_cb)();
|
(*channel->ch_nb_close_cb)();
|
||||||
|
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
{
|
{
|
||||||
|
12
src/eval.c
12
src/eval.c
@@ -10067,6 +10067,18 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported)
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (STRCMP(hi->hi_key, "close-cb") == 0)
|
||||||
|
{
|
||||||
|
if (!(supported & JO_CLOSE_CALLBACK))
|
||||||
|
break;
|
||||||
|
opt->jo_set |= JO_CLOSE_CALLBACK;
|
||||||
|
opt->jo_close_cb = get_callback(item);
|
||||||
|
if (opt->jo_close_cb == NULL)
|
||||||
|
{
|
||||||
|
EMSG2(_(e_invarg2), "close-cb");
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (STRCMP(hi->hi_key, "waittime") == 0)
|
else if (STRCMP(hi->hi_key, "waittime") == 0)
|
||||||
{
|
{
|
||||||
if (!(supported & JO_WAITTIME))
|
if (!(supported & JO_WAITTIME))
|
||||||
|
@@ -7,10 +7,10 @@ channel_T *add_channel(void);
|
|||||||
void channel_free(channel_T *channel);
|
void channel_free(channel_T *channel);
|
||||||
void channel_gui_register(channel_T *channel);
|
void channel_gui_register(channel_T *channel);
|
||||||
void channel_gui_register_all(void);
|
void channel_gui_register_all(void);
|
||||||
channel_T *channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void));
|
channel_T *channel_open(char *hostname, int port_in, int waittime, void (*nb_close_cb)(void));
|
||||||
void channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err);
|
void channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err);
|
||||||
void channel_set_job(channel_T *channel, job_T *job);
|
void channel_set_job(channel_T *channel, job_T *job);
|
||||||
void channel_set_options(channel_T *channel, jobopt_T *options);
|
void channel_set_options(channel_T *channel, jobopt_T *opt);
|
||||||
void channel_set_req_callback(channel_T *channel, int part, char_u *callback, int id);
|
void channel_set_req_callback(channel_T *channel, int part, char_u *callback, int id);
|
||||||
char_u *channel_get(channel_T *channel, int part);
|
char_u *channel_get(channel_T *channel, int part);
|
||||||
int channel_collapse(channel_T *channel, int part);
|
int channel_collapse(channel_T *channel, int part);
|
||||||
|
@@ -1366,9 +1366,12 @@ struct channel_S {
|
|||||||
* first error until the connection works
|
* first error until the connection works
|
||||||
* again. */
|
* again. */
|
||||||
|
|
||||||
void (*ch_close_cb)(void); /* callback for when channel is closed */
|
void (*ch_nb_close_cb)(void);
|
||||||
|
/* callback for Netbeans when channel is
|
||||||
|
* closed */
|
||||||
|
|
||||||
char_u *ch_callback; /* call when any msg is not handled */
|
char_u *ch_callback; /* call when any msg is not handled */
|
||||||
|
char_u *ch_close_cb; /* call when channel is closed */
|
||||||
|
|
||||||
job_T *ch_job; /* Job that uses this channel; this does not
|
job_T *ch_job; /* Job that uses this channel; this does not
|
||||||
* count as a reference to avoid a circular
|
* count as a reference to avoid a circular
|
||||||
@@ -1384,18 +1387,20 @@ struct channel_S {
|
|||||||
#define JO_CALLBACK 0x0010 /* channel callback */
|
#define JO_CALLBACK 0x0010 /* channel callback */
|
||||||
#define JO_OUT_CALLBACK 0x0020 /* stdout callback */
|
#define JO_OUT_CALLBACK 0x0020 /* stdout callback */
|
||||||
#define JO_ERR_CALLBACK 0x0040 /* stderr callback */
|
#define JO_ERR_CALLBACK 0x0040 /* stderr callback */
|
||||||
#define JO_WAITTIME 0x0080 /* only for ch_open() */
|
#define JO_CLOSE_CALLBACK 0x0080 /* close callback */
|
||||||
#define JO_TIMEOUT 0x0100 /* all timeouts */
|
#define JO_WAITTIME 0x0100 /* only for ch_open() */
|
||||||
#define JO_OUT_TIMEOUT 0x0200 /* stdout timeouts */
|
#define JO_TIMEOUT 0x0200 /* all timeouts */
|
||||||
#define JO_ERR_TIMEOUT 0x0400 /* stderr timeouts */
|
#define JO_OUT_TIMEOUT 0x0400 /* stdout timeouts */
|
||||||
#define JO_PART 0x0800 /* "part" */
|
#define JO_ERR_TIMEOUT 0x0800 /* stderr timeouts */
|
||||||
#define JO_ID 0x1000 /* "id" */
|
#define JO_PART 0x1000 /* "part" */
|
||||||
#define JO_STOPONEXIT 0x2000 /* "stoponexit" */
|
#define JO_ID 0x2000 /* "id" */
|
||||||
#define JO_EXIT_CB 0x4000 /* "exit-cb" */
|
#define JO_STOPONEXIT 0x4000 /* "stoponexit" */
|
||||||
|
#define JO_EXIT_CB 0x8000 /* "exit-cb" */
|
||||||
#define JO_ALL 0xffffff
|
#define JO_ALL 0xffffff
|
||||||
|
|
||||||
#define JO_MODE_ALL (JO_MODE + JO_IN_MODE + JO_OUT_MODE + JO_ERR_MODE)
|
#define JO_MODE_ALL (JO_MODE + JO_IN_MODE + JO_OUT_MODE + JO_ERR_MODE)
|
||||||
#define JO_CB_ALL (JO_CALLBACK + JO_OUT_CALLBACK + JO_ERR_CALLBACK)
|
#define JO_CB_ALL \
|
||||||
|
(JO_CALLBACK + JO_OUT_CALLBACK + JO_ERR_CALLBACK + JO_CLOSE_CALLBACK)
|
||||||
#define JO_TIMEOUT_ALL (JO_TIMEOUT + JO_OUT_TIMEOUT + JO_ERR_TIMEOUT)
|
#define JO_TIMEOUT_ALL (JO_TIMEOUT + JO_OUT_TIMEOUT + JO_ERR_TIMEOUT)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1412,6 +1417,7 @@ typedef struct
|
|||||||
char_u *jo_callback; /* not allocated! */
|
char_u *jo_callback; /* not allocated! */
|
||||||
char_u *jo_out_cb; /* not allocated! */
|
char_u *jo_out_cb; /* not allocated! */
|
||||||
char_u *jo_err_cb; /* not allocated! */
|
char_u *jo_err_cb; /* not allocated! */
|
||||||
|
char_u *jo_close_cb; /* not allocated! */
|
||||||
int jo_waittime;
|
int jo_waittime;
|
||||||
int jo_timeout;
|
int jo_timeout;
|
||||||
int jo_out_timeout;
|
int jo_out_timeout;
|
||||||
|
@@ -140,6 +140,10 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
|
|||||||
print("sending: {}".format(cmd))
|
print("sending: {}".format(cmd))
|
||||||
self.request.sendall(cmd.encode('utf-8'))
|
self.request.sendall(cmd.encode('utf-8'))
|
||||||
response = ""
|
response = ""
|
||||||
|
elif decoded[1] == 'close me':
|
||||||
|
print("closing")
|
||||||
|
self.request.close()
|
||||||
|
response = ""
|
||||||
elif decoded[1] == 'wait a bit':
|
elif decoded[1] == 'wait a bit':
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
response = "waited"
|
response = "waited"
|
||||||
|
@@ -471,9 +471,9 @@ endfunc
|
|||||||
|
|
||||||
"""""""""
|
"""""""""
|
||||||
|
|
||||||
let s:job_ret = 'not yet'
|
let s:job_exit_ret = 'not yet'
|
||||||
function MyExitCb(job, status)
|
function MyExitCb(job, status)
|
||||||
let s:job_ret = 'done'
|
let s:job_exit_ret = 'done'
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
function s:test_exit_callback(port)
|
function s:test_exit_callback(port)
|
||||||
@@ -490,6 +490,32 @@ func Test_exit_callback()
|
|||||||
|
|
||||||
" calling job_status() triggers the callback
|
" calling job_status() triggers the callback
|
||||||
call job_status(s:exit_job)
|
call job_status(s:exit_job)
|
||||||
call assert_equal('done', s:job_ret)
|
call assert_equal('done', s:job_exit_ret)
|
||||||
endif
|
endif
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
"""""""""
|
||||||
|
|
||||||
|
let s:ch_close_ret = 'alive'
|
||||||
|
function MyCloseCb(ch)
|
||||||
|
let s:ch_close_ret = 'closed'
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
function s:test_close_callback(port)
|
||||||
|
let handle = ch_open('localhost:' . a:port, s:chopt)
|
||||||
|
if ch_status(handle) == "fail"
|
||||||
|
call assert_false(1, "Can't open channel")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
call ch_setoptions(handle, {'close-cb': 'MyCloseCb'})
|
||||||
|
|
||||||
|
call assert_equal('', ch_sendexpr(handle, 'close me'))
|
||||||
|
sleep 20m
|
||||||
|
call assert_equal('closed', s:ch_close_ret)
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_close_callback()
|
||||||
|
call ch_log('Test_close_callback()')
|
||||||
|
call s:run_server('s:test_close_callback')
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
@@ -748,6 +748,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1398,
|
||||||
/**/
|
/**/
|
||||||
1397,
|
1397,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user