mirror of
https://github.com/vim/vim.git
synced 2025-07-04 23:07:33 -04:00
patch 7.4.1336
Problem: Channel NL mode is not supported yet. Solution: Add NL mode support to channels.
This commit is contained in:
parent
5d54a04598
commit
9a6e33a19b
129
src/channel.c
129
src/channel.c
@ -669,12 +669,12 @@ channel_set_job(channel_T *channel, job_T *job)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the json mode of channel "channel" to "ch_mode".
|
* Set the mode of channel "channel" to "mode".
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
channel_set_json_mode(channel_T *channel, ch_mode_T ch_mode)
|
channel_set_mode(channel_T *channel, ch_mode_T mode)
|
||||||
{
|
{
|
||||||
channel->ch_mode = ch_mode;
|
channel->ch_mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1057,7 +1057,8 @@ channel_exe_cmd(channel_T *channel, char_u *cmd, typval_T *arg2, typval_T *arg3)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Invoke a callback for channel "channel" if needed.
|
* Invoke a callback for channel "channel" if needed.
|
||||||
* Return OK when a message was handled, there might be another one.
|
* TODO: add "which" argument, read stderr.
|
||||||
|
* Return TRUE when a message was handled, there might be another one.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
may_invoke_callback(channel_T *channel)
|
may_invoke_callback(channel_T *channel)
|
||||||
@ -1074,7 +1075,7 @@ may_invoke_callback(channel_T *channel)
|
|||||||
/* this channel is handled elsewhere (netbeans) */
|
/* this channel is handled elsewhere (netbeans) */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (ch_mode != MODE_RAW)
|
if (ch_mode == MODE_JSON || ch_mode == MODE_JS)
|
||||||
{
|
{
|
||||||
/* Get any json message in the queue. */
|
/* Get any json message in the queue. */
|
||||||
if (channel_get_json(channel, -1, &listtv) == FAIL)
|
if (channel_get_json(channel, -1, &listtv) == FAIL)
|
||||||
@ -1113,18 +1114,51 @@ may_invoke_callback(channel_T *channel)
|
|||||||
}
|
}
|
||||||
else if (channel_peek(channel) == NULL)
|
else if (channel_peek(channel) == NULL)
|
||||||
{
|
{
|
||||||
/* nothing to read on raw channel */
|
/* nothing to read on RAW or NL channel */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* If there is no callback, don't do anything. */
|
/* If there is no callback drop the message. */
|
||||||
if (channel->ch_callback == NULL)
|
if (channel->ch_callback == NULL)
|
||||||
|
{
|
||||||
|
while ((msg = channel_get(channel)) != NULL)
|
||||||
|
vim_free(msg);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch_mode == MODE_NL)
|
||||||
|
{
|
||||||
|
char_u *nl;
|
||||||
|
char_u *buf;
|
||||||
|
|
||||||
|
/* See if we have a message ending in NL in the first buffer. If
|
||||||
|
* not try to concatenate the first and the second buffer. */
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
buf = channel_peek(channel);
|
||||||
|
nl = vim_strchr(buf, NL);
|
||||||
|
if (nl != NULL)
|
||||||
|
break;
|
||||||
|
if (channel_collapse(channel) == FAIL)
|
||||||
|
return FALSE; /* incomplete message */
|
||||||
|
}
|
||||||
|
if (nl[1] == NUL)
|
||||||
|
/* get the whole buffer */
|
||||||
|
msg = channel_get(channel);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Copy the message into allocated memory and remove it from
|
||||||
|
* the buffer. */
|
||||||
|
msg = vim_strnsave(buf, (int)(nl - buf));
|
||||||
|
mch_memmove(buf, nl + 1, STRLEN(nl + 1) + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* For a raw channel we don't know where the message ends, just
|
||||||
|
* get everything we have. */
|
||||||
|
msg = channel_get_all(channel);
|
||||||
|
|
||||||
/* For a raw channel we don't know where the message ends, just get
|
|
||||||
* everything. */
|
|
||||||
msg = channel_get_all(channel);
|
|
||||||
argv[1].v_type = VAR_STRING;
|
argv[1].v_type = VAR_STRING;
|
||||||
argv[1].vval.v_string = msg;
|
argv[1].vval.v_string = msg;
|
||||||
}
|
}
|
||||||
@ -1276,12 +1310,20 @@ channel_save(channel_T *channel, char_u *buf, int len)
|
|||||||
return FAIL; /* out of memory */
|
return FAIL; /* out of memory */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: don't strip CR when channel is in raw mode */
|
if (channel->ch_mode == MODE_NL)
|
||||||
p = node->rq_buffer;
|
{
|
||||||
for (i = 0; i < len; ++i)
|
/* Drop any CR before a NL. */
|
||||||
if (buf[i] != CAR || i + 1 >= len || buf[i + 1] != NL)
|
p = node->rq_buffer;
|
||||||
*p++ = buf[i];
|
for (i = 0; i < len; ++i)
|
||||||
*p = NUL;
|
if (buf[i] != CAR || i + 1 >= len || buf[i + 1] != NL)
|
||||||
|
*p++ = buf[i];
|
||||||
|
*p = NUL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mch_memmove(node->rq_buffer, buf, len);
|
||||||
|
node->rq_buffer[len] = NUL;
|
||||||
|
}
|
||||||
|
|
||||||
/* append node to the tail of the queue */
|
/* append node to the tail of the queue */
|
||||||
node->rq_next = NULL;
|
node->rq_next = NULL;
|
||||||
@ -1570,21 +1612,33 @@ channel_read(channel_T *channel, int which, char *func)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read from raw channel "channel". Blocks until there is something to read or
|
* Read from RAW or NL channel "channel". Blocks until there is something to
|
||||||
* the timeout expires.
|
* read or the timeout expires.
|
||||||
|
* TODO: add "which" argument and read from stderr.
|
||||||
* Returns what was read in allocated memory.
|
* Returns what was read in allocated memory.
|
||||||
* Returns NULL in case of error or timeout.
|
* Returns NULL in case of error or timeout.
|
||||||
*/
|
*/
|
||||||
char_u *
|
char_u *
|
||||||
channel_read_block(channel_T *channel)
|
channel_read_block(channel_T *channel)
|
||||||
{
|
{
|
||||||
ch_log(channel, "Reading raw\n");
|
char_u *buf;
|
||||||
if (channel_peek(channel) == NULL)
|
char_u *msg;
|
||||||
{
|
ch_mode_T mode = channel->ch_mode;
|
||||||
sock_T fd = get_read_fd(channel);
|
sock_T fd = get_read_fd(channel);
|
||||||
|
char_u *nl;
|
||||||
|
|
||||||
|
ch_logsn(channel, "Blocking %s read, timeout: %d msec\n",
|
||||||
|
mode == MODE_RAW ? "RAW" : "NL", channel->ch_timeout);
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
buf = channel_peek(channel);
|
||||||
|
if (buf != NULL && (mode == MODE_RAW
|
||||||
|
|| (mode == MODE_NL && vim_strchr(buf, NL) != NULL)))
|
||||||
|
break;
|
||||||
|
if (buf != NULL && channel_collapse(channel) == OK)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* TODO: read both out and err if they are different */
|
|
||||||
ch_log(channel, "No readahead\n");
|
|
||||||
/* Wait for up to the channel timeout. */
|
/* Wait for up to the channel timeout. */
|
||||||
if (fd == CHAN_FD_INVALID
|
if (fd == CHAN_FD_INVALID
|
||||||
|| channel_wait(channel, fd, channel->ch_timeout) == FAIL)
|
|| channel_wait(channel, fd, channel->ch_timeout) == FAIL)
|
||||||
@ -1592,9 +1646,30 @@ channel_read_block(channel_T *channel)
|
|||||||
channel_read(channel, -1, "channel_read_block");
|
channel_read(channel, -1, "channel_read_block");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: only get the first message */
|
if (mode == MODE_RAW)
|
||||||
ch_log(channel, "Returning readahead\n");
|
{
|
||||||
return channel_get_all(channel);
|
msg = channel_get_all(channel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nl = vim_strchr(buf, NL);
|
||||||
|
if (nl[1] == NUL)
|
||||||
|
{
|
||||||
|
/* get the whole buffer */
|
||||||
|
msg = channel_get(channel);
|
||||||
|
*nl = NUL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Copy the message into allocated memory and remove it from the
|
||||||
|
* buffer. */
|
||||||
|
msg = vim_strnsave(buf, (int)(nl - buf));
|
||||||
|
mch_memmove(buf, nl + 1, STRLEN(nl + 1) + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (log_fd != NULL)
|
||||||
|
ch_logn(channel, "Returning %d bytes\n", (int)STRLEN(msg));
|
||||||
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -5034,7 +5034,7 @@ mch_call_shell(
|
|||||||
|
|
||||||
#if defined(FEAT_JOB) || defined(PROTO)
|
#if defined(FEAT_JOB) || defined(PROTO)
|
||||||
void
|
void
|
||||||
mch_start_job(char *cmd, job_T *job)
|
mch_start_job(char *cmd, job_T *job, jobopt_T *options)
|
||||||
{
|
{
|
||||||
STARTUPINFO si;
|
STARTUPINFO si;
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
@ -5121,6 +5121,7 @@ mch_start_job(char *cmd, job_T *job)
|
|||||||
job->jv_channel = channel;
|
job->jv_channel = channel;
|
||||||
channel_set_pipes(channel, (sock_T)ifd[1], (sock_T)ofd[0], (sock_T)efd[0]);
|
channel_set_pipes(channel, (sock_T)ifd[1], (sock_T)ofd[0], (sock_T)efd[0]);
|
||||||
channel_set_job(channel, job);
|
channel_set_job(channel, job);
|
||||||
|
channel_set_mode(channel, options->jo_mode);
|
||||||
|
|
||||||
# ifdef FEAT_GUI
|
# ifdef FEAT_GUI
|
||||||
channel_gui_register(channel);
|
channel_gui_register(channel);
|
||||||
|
@ -7,7 +7,7 @@ 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 (*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_json_mode(channel_T *channel, ch_mode_T ch_mode);
|
void channel_set_mode(channel_T *channel, ch_mode_T ch_mode);
|
||||||
void channel_set_timeout(channel_T *channel, int timeout);
|
void channel_set_timeout(channel_T *channel, int timeout);
|
||||||
void channel_set_callback(channel_T *channel, char_u *callback);
|
void channel_set_callback(channel_T *channel, char_u *callback);
|
||||||
void channel_set_req_callback(channel_T *channel, char_u *callback, int id);
|
void channel_set_req_callback(channel_T *channel, char_u *callback, int id);
|
||||||
|
@ -57,7 +57,7 @@ void mch_set_shellsize(void);
|
|||||||
void mch_new_shellsize(void);
|
void mch_new_shellsize(void);
|
||||||
int mch_parse_cmd(char_u *cmd, int use_shcf, char ***argv, int *argc);
|
int mch_parse_cmd(char_u *cmd, int use_shcf, char ***argv, int *argc);
|
||||||
int mch_call_shell(char_u *cmd, int options);
|
int mch_call_shell(char_u *cmd, int options);
|
||||||
void mch_start_job(char **argv, job_T *job);
|
void mch_start_job(char **argv, job_T *job, jobopt_T *options);
|
||||||
char *mch_job_status(job_T *job);
|
char *mch_job_status(job_T *job);
|
||||||
int mch_stop_job(job_T *job, char_u *how);
|
int mch_stop_job(job_T *job, char_u *how);
|
||||||
void mch_clear_job(job_T *job);
|
void mch_clear_job(job_T *job);
|
||||||
|
@ -40,7 +40,7 @@ void mch_set_shellsize(void);
|
|||||||
void mch_new_shellsize(void);
|
void mch_new_shellsize(void);
|
||||||
void mch_set_winsize_now(void);
|
void mch_set_winsize_now(void);
|
||||||
int mch_call_shell(char_u *cmd, int options);
|
int mch_call_shell(char_u *cmd, int options);
|
||||||
void mch_start_job(char *cmd, job_T *job);
|
void mch_start_job(char *cmd, job_T *job, jobopt_T *options);
|
||||||
char *mch_job_status(job_T *job);
|
char *mch_job_status(job_T *job);
|
||||||
int mch_stop_job(job_T *job, char_u *how);
|
int mch_stop_job(job_T *job, char_u *how);
|
||||||
void mch_clear_job(job_T *job);
|
void mch_clear_job(job_T *job);
|
||||||
|
@ -1372,6 +1372,14 @@ struct channel_S {
|
|||||||
int ch_refcount; /* reference count */
|
int ch_refcount; /* reference count */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Options for job commands.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ch_mode_T jo_mode;
|
||||||
|
} jobopt_T;
|
||||||
|
|
||||||
|
|
||||||
/* structure used for explicit stack while garbage collecting hash tables */
|
/* structure used for explicit stack while garbage collecting hash tables */
|
||||||
typedef struct ht_stack_S
|
typedef struct ht_stack_S
|
||||||
|
@ -284,7 +284,30 @@ func Test_connect_waittime()
|
|||||||
endif
|
endif
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_pipe()
|
func Test_raw_pipe()
|
||||||
|
if !has('job')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
let job = job_start(s:python . " test_channel_pipe.py", {'mode': 'raw'})
|
||||||
|
call assert_equal("run", job_status(job))
|
||||||
|
try
|
||||||
|
let handle = job_getchannel(job)
|
||||||
|
call ch_sendraw(handle, "echo something\n", 0)
|
||||||
|
let msg = ch_readraw(handle)
|
||||||
|
call assert_equal("something\n", substitute(msg, "\r", "", 'g'))
|
||||||
|
|
||||||
|
call ch_sendraw(handle, "double this\n", 0)
|
||||||
|
let msg = ch_readraw(handle)
|
||||||
|
call assert_equal("this\nAND this\n", substitute(msg, "\r", "", 'g'))
|
||||||
|
|
||||||
|
let reply = ch_sendraw(handle, "quit\n")
|
||||||
|
call assert_equal("Goodbye!\n", substitute(reply, "\r", "", 'g'))
|
||||||
|
finally
|
||||||
|
call job_stop(job)
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_nl_pipe()
|
||||||
if !has('job')
|
if !has('job')
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
@ -293,9 +316,14 @@ func Test_pipe()
|
|||||||
try
|
try
|
||||||
let handle = job_getchannel(job)
|
let handle = job_getchannel(job)
|
||||||
call ch_sendraw(handle, "echo something\n", 0)
|
call ch_sendraw(handle, "echo something\n", 0)
|
||||||
call assert_equal("something\n", ch_readraw(handle))
|
call assert_equal("something", ch_readraw(handle))
|
||||||
|
|
||||||
|
call ch_sendraw(handle, "double this\n", 0)
|
||||||
|
call assert_equal("this", ch_readraw(handle))
|
||||||
|
call assert_equal("AND this", ch_readraw(handle))
|
||||||
|
|
||||||
let reply = ch_sendraw(handle, "quit\n")
|
let reply = ch_sendraw(handle, "quit\n")
|
||||||
call assert_equal("Goodbye!\n", reply)
|
call assert_equal("Goodbye!", reply)
|
||||||
finally
|
finally
|
||||||
call job_stop(job)
|
call job_stop(job)
|
||||||
endtry
|
endtry
|
||||||
|
@ -21,4 +21,7 @@ if __name__ == "__main__":
|
|||||||
if typed.startswith("echo"):
|
if typed.startswith("echo"):
|
||||||
print(typed[5:-1])
|
print(typed[5:-1])
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
if typed.startswith("double"):
|
||||||
|
print(typed[7:-1] + "\nAND " + typed[7:-1])
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
@ -747,6 +747,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 */
|
||||||
|
/**/
|
||||||
|
1336,
|
||||||
/**/
|
/**/
|
||||||
1335,
|
1335,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user