aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/os/channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/os/channel.c')
-rw-r--r--src/nvim/os/channel.c42
1 files changed, 38 insertions, 4 deletions
diff --git a/src/nvim/os/channel.c b/src/nvim/os/channel.c
index 1a2efca513..2c1928f3b3 100644
--- a/src/nvim/os/channel.c
+++ b/src/nvim/os/channel.c
@@ -20,11 +20,14 @@
#include "nvim/vim.h"
#include "nvim/ascii.h"
#include "nvim/memory.h"
+#include "nvim/os_unix.h"
#include "nvim/message.h"
#include "nvim/map.h"
#include "nvim/log.h"
#include "nvim/lib/kvec.h"
+#define CHANNEL_BUFFER_SIZE 0xffff
+
typedef struct {
uint64_t request_id;
bool errored;
@@ -64,6 +67,10 @@ void channel_init(void)
channels = pmap_new(uint64_t)();
event_strings = pmap_new(cstr_t)();
msgpack_sbuffer_init(&out_buffer);
+
+ if (embedded_mode) {
+ channel_from_stdio();
+ }
}
/// Teardown the module
@@ -117,7 +124,10 @@ void channel_from_stream(uv_stream_t *stream)
stream->data = NULL;
channel->is_job = false;
// read stream
- channel->data.streams.read = rstream_new(parse_msgpack, 1024, channel, NULL);
+ channel->data.streams.read = rstream_new(parse_msgpack,
+ CHANNEL_BUFFER_SIZE,
+ channel,
+ NULL);
rstream_set_stream(channel->data.streams.read, stream);
rstream_start(channel->data.streams.read);
// write stream
@@ -256,6 +266,25 @@ void channel_unsubscribe(uint64_t id, char *event)
unsubscribe(channel, event);
}
+/// Creates an API channel from stdin/stdout. This is used when embedding
+/// Neovim
+static void channel_from_stdio(void)
+{
+ Channel *channel = register_channel();
+ channel->is_job = false;
+ // read stream
+ channel->data.streams.read = rstream_new(parse_msgpack,
+ CHANNEL_BUFFER_SIZE,
+ channel,
+ NULL);
+ rstream_set_file(channel->data.streams.read, 0);
+ rstream_start(channel->data.streams.read);
+ // write stream
+ channel->data.streams.write = wstream_new(0);
+ wstream_set_file(channel->data.streams.write, 1);
+ channel->data.streams.uv = NULL;
+}
+
static void job_out(RStream *rstream, void *data, bool eof)
{
Job *job = data;
@@ -278,6 +307,7 @@ static void job_err(RStream *rstream, void *data, bool eof)
static void parse_msgpack(RStream *rstream, void *data, bool eof)
{
Channel *channel = data;
+ channel->rpc_call_level++;
if (eof) {
char buf[256];
@@ -287,10 +317,9 @@ static void parse_msgpack(RStream *rstream, void *data, bool eof)
"closed by the client",
channel->id);
call_set_error(channel, buf);
- return;
+ goto end;
}
- channel->rpc_call_level++;
uint32_t count = rstream_available(rstream);
DLOG("Feeding the msgpack parser with %u bytes of data from RStream(%p)",
count,
@@ -469,7 +498,12 @@ static void close_channel(Channel *channel)
} else {
rstream_free(channel->data.streams.read);
wstream_free(channel->data.streams.write);
- uv_close((uv_handle_t *)channel->data.streams.uv, close_cb);
+ if (channel->data.streams.uv) {
+ uv_close((uv_handle_t *)channel->data.streams.uv, close_cb);
+ } else {
+ // When the stdin channel closes, it's time to go
+ mch_exit(0);
+ }
}
free(channel);