aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/channel.c')
-rw-r--r--src/nvim/channel.c67
1 files changed, 38 insertions, 29 deletions
diff --git a/src/nvim/channel.c b/src/nvim/channel.c
index 37cbfb968b..22eb31513d 100644
--- a/src/nvim/channel.c
+++ b/src/nvim/channel.c
@@ -161,7 +161,7 @@ void channel_init(void)
///
/// Channel is allocated with refcount 1, which should be decreased
/// when the underlying stream closes.
-static Channel *channel_alloc(ChannelStreamType type)
+Channel *channel_alloc(ChannelStreamType type)
{
Channel *chan = xcalloc(1, sizeof(*chan));
if (type == kChannelStreamStdio) {
@@ -292,7 +292,6 @@ static void close_cb(Stream *stream, void *data)
/// directory if `cwd` is NULL
/// @param[in] pty_width Width of the pty, ignored if `pty` is false
/// @param[in] pty_height Height of the pty, ignored if `pty` is false
-/// @param[in] term_name `$TERM` for the pty
/// @param[in] env Nvim's configured environment is used if this is NULL,
/// otherwise defines all environment variables
/// @param[out] status_out 0 for invalid arguments, > 0 for the channel id,
@@ -304,7 +303,7 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout,
bool pty, bool rpc, bool overlapped, bool detach,
const char *cwd,
uint16_t pty_width, uint16_t pty_height,
- char *term_name, char **env, varnumber_T *status_out)
+ dict_T *env, varnumber_T *status_out)
{
assert(cwd == NULL || os_isdir_executable(cwd));
@@ -317,7 +316,9 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout,
if (detach) {
EMSG2(_(e_invarg2), "terminal/pty job cannot be detached");
shell_free_argv(argv);
- xfree(term_name);
+ if (env) {
+ tv_dict_free(env);
+ }
channel_destroy_early(chan);
*status_out = 0;
return NULL;
@@ -329,9 +330,6 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout,
if (pty_height > 0) {
chan->stream.pty.height = pty_height;
}
- if (term_name) {
- chan->stream.pty.term_name = term_name;
- }
} else {
chan->stream.uv = libuv_process_init(&main_loop, chan);
}
@@ -358,17 +356,17 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout,
if (status) {
EMSG3(_(e_jobspawn), os_strerror(status), cmd);
xfree(cmd);
- os_free_fullenv(proc->env);
- if (proc->type == kProcessTypePty) {
- xfree(chan->stream.pty.term_name);
+ if (proc->env) {
+ tv_dict_free(proc->env);
}
channel_destroy_early(chan);
*status_out = proc->status;
return NULL;
}
xfree(cmd);
- os_free_fullenv(proc->env);
-
+ if (proc->env) {
+ tv_dict_free(proc->env);
+ }
wstream_init(&proc->in, 0);
if (has_out) {
@@ -501,43 +499,54 @@ uint64_t channel_from_stdio(bool rpc, CallbackReader on_output,
}
/// @param data will be consumed
-size_t channel_send(uint64_t id, char *data, size_t len, const char **error)
+size_t channel_send(uint64_t id, char *data, size_t len,
+ bool data_owned, const char **error)
{
Channel *chan = find_channel(id);
+ size_t written = 0;
if (!chan) {
- EMSG(_(e_invchan));
- goto err;
+ *error = _(e_invchan);
+ goto retfree;
}
if (chan->streamtype == kChannelStreamStderr) {
if (chan->stream.err.closed) {
*error = _("Can't send data to closed stream");
- goto err;
+ goto retfree;
}
// unbuffered write
- size_t written = fwrite(data, len, 1, stderr);
- xfree(data);
- return len * written;
+ written = len * fwrite(data, len, 1, stderr);
+ goto retfree;
+ }
+
+ if (chan->streamtype == kChannelStreamInternal && chan->term) {
+ terminal_receive(chan->term, data, len);
+ written = len;
+ goto retfree;
}
Stream *in = channel_instream(chan);
if (in->closed) {
*error = _("Can't send data to closed stream");
- goto err;
+ goto retfree;
}
if (chan->is_rpc) {
*error = _("Can't send raw data to rpc channel");
- goto err;
+ goto retfree;
}
- WBuffer *buf = wstream_new_buffer(data, len, 1, xfree);
+ // write can be delayed indefinitely, so always use an allocated buffer
+ WBuffer *buf = wstream_new_buffer(data_owned ? data : xmemdup(data, len),
+ len, 1, xfree);
return wstream_write(in, buf) ? len : 0;
-err:
- xfree(data);
- return 0;
+retfree:
+ if (data_owned) {
+ xfree(data);
+ }
+ return written;
}
/// Convert binary byte array to a readfile()-style list
@@ -726,8 +735,8 @@ static void channel_callback_call(Channel *chan, CallbackReader *reader)
/// Open terminal for channel
///
/// Channel `chan` is assumed to be an open pty channel,
-/// and curbuf is assumed to be a new, unmodified buffer.
-void channel_terminal_open(Channel *chan)
+/// and `buf` is assumed to be a new, unmodified buffer.
+void channel_terminal_open(buf_T *buf, Channel *chan)
{
TerminalOptions topts;
topts.data = chan;
@@ -736,8 +745,8 @@ void channel_terminal_open(Channel *chan)
topts.write_cb = term_write;
topts.resize_cb = term_resize;
topts.close_cb = term_close;
- curbuf->b_p_channel = (long)chan->id; // 'channel' option
- Terminal *term = terminal_open(topts);
+ buf->b_p_channel = (long)chan->id; // 'channel' option
+ Terminal *term = terminal_open(buf, topts);
chan->term = term;
channel_incref(chan);
}