aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorScott Prager <splinterofchaos@gmail.com>2015-04-01 23:07:41 -0400
committerScott Prager <splinterofchaos@gmail.com>2015-04-14 15:31:04 -0400
commit296719428a5adc7c4f00a7f1778771c5ec9af9d0 (patch)
treea6842605c77eeddca41a35d5ecd14d414ea0d48c /src
parent4a66c48d8b6e7f74b64f06d176a10d8b6d38491b (diff)
downloadrneovim-296719428a5adc7c4f00a7f1778771c5ec9af9d0.tar.gz
rneovim-296719428a5adc7c4f00a7f1778771c5ec9af9d0.tar.bz2
rneovim-296719428a5adc7c4f00a7f1778771c5ec9af9d0.zip
eval: learn serverstart, list, and close().
Implement functions for spawning, destroying, and listing active servers, and add server_address_list() to msgpack_rpc/server.c for the serverlist() vimL function.
Diffstat (limited to 'src')
-rw-r--r--src/nvim/eval.c67
-rw-r--r--src/nvim/msgpack_rpc/server.c43
2 files changed, 105 insertions, 5 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 1616bf60e2..1dab9df9cb 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -87,6 +87,7 @@
#include "nvim/os/rstream_defs.h"
#include "nvim/os/time.h"
#include "nvim/msgpack_rpc/channel.h"
+#include "nvim/msgpack_rpc/server.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/vim.h"
#include "nvim/os/dl.h"
@@ -6605,6 +6606,9 @@ static struct fst {
{"searchpair", 3, 7, f_searchpair},
{"searchpairpos", 3, 7, f_searchpairpos},
{"searchpos", 1, 4, f_searchpos},
+ {"serverlist", 0, 0, f_serverlist},
+ {"serverstart", 0, 1, f_serverstart},
+ {"serverstop", 1, 1, f_serverstop},
{"setbufvar", 3, 3, f_setbufvar},
{"setcmdpos", 1, 1, f_setcmdpos},
{"setline", 2, 2, f_setline},
@@ -13292,6 +13296,69 @@ static void f_searchpos(typval_T *argvars, typval_T *rettv)
list_append_number(rettv->vval.v_list, (varnumber_T)n);
}
+/// "serverlist()" function
+static void f_serverlist(typval_T *argvars, typval_T *rettv)
+{
+ size_t n;
+ char **addrs = server_address_list(&n);
+
+ // Copy addrs into a linked list.
+ list_T *l = rettv_list_alloc(rettv);
+ for (size_t i = 0; i < n; i++) {
+ listitem_T *li = listitem_alloc();
+ li->li_tv.v_type = VAR_STRING;
+ li->li_tv.v_lock = 0;
+ li->li_tv.vval.v_string = (char_u *) addrs[i];
+ list_append(l, li);
+ }
+ xfree(addrs);
+}
+
+/// "serverstart()" function
+static void f_serverstart(typval_T *argvars, typval_T *rettv)
+{
+ rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = NULL; // Will hold the address of the new server.
+
+ if (check_restricted() || check_secure()) {
+ return;
+ }
+
+ // If the user supplied an address, use it, otherwise use a temp.
+ if (argvars[0].v_type != VAR_UNKNOWN) {
+ if (argvars[0].v_type != VAR_STRING) {
+ EMSG(_(e_invarg));
+ return;
+ } else {
+ rettv->vval.v_string = vim_strsave(get_tv_string(argvars));
+ }
+ } else {
+ rettv->vval.v_string = vim_tempname();
+ }
+
+ int result = server_start((char *) rettv->vval.v_string);
+ if (result != 0) {
+ EMSG2("Failed to start server: %s", uv_strerror(result));
+ }
+}
+
+/// "serverstop()" function
+static void f_serverstop(typval_T *argvars, typval_T *rettv)
+{
+ if (check_restricted() || check_secure()) {
+ return;
+ }
+
+ if (argvars[0].v_type == VAR_UNKNOWN || argvars[0].v_type != VAR_STRING) {
+ EMSG(_(e_invarg));
+ return;
+ }
+
+ if (argvars[0].vval.v_string) {
+ server_stop((char *) argvars[0].vval.v_string);
+ }
+}
+
/*
* "setbufvar()" function
*/
diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c
index 5469347db0..8fb2902b0b 100644
--- a/src/nvim/msgpack_rpc/server.c
+++ b/src/nvim/msgpack_rpc/server.c
@@ -56,13 +56,18 @@ bool server_init(void)
{
ga_init(&servers, sizeof(Server *), 1);
- if (!os_getenv(LISTEN_ADDRESS_ENV_VAR)) {
- char *listen_address = (char *)vim_tempname();
- os_setenv(LISTEN_ADDRESS_ENV_VAR, listen_address, 1);
- xfree(listen_address);
+ bool must_free = false;
+ const char *listen_address = os_getenv(LISTEN_ADDRESS_ENV_VAR);
+ if (listen_address == NULL || *listen_address == NUL) {
+ must_free = true;
+ listen_address = (char *)vim_tempname();
}
- return server_start((char *)os_getenv(LISTEN_ADDRESS_ENV_VAR)) == 0;
+ bool ok = (server_start(listen_address) == 0);
+ if (must_free) {
+ xfree((char *) listen_address);
+ }
+ return ok;
}
/// Retrieve the file handle from a server.
@@ -199,6 +204,12 @@ int server_start(const char *endpoint)
return result;
}
+ // Update $NVIM_LISTEN_ADDRESS, if not set.
+ const char *listen_address = os_getenv(LISTEN_ADDRESS_ENV_VAR);
+ if (listen_address == NULL || *listen_address == NUL) {
+ os_setenv(LISTEN_ADDRESS_ENV_VAR, addr, 1);
+ }
+
server->type = server_type;
// Add the server to the list.
@@ -232,6 +243,12 @@ void server_stop(char *endpoint)
return;
}
+ // If we are invalidating the listen address, unset it.
+ const char *listen_address = os_getenv(LISTEN_ADDRESS_ENV_VAR);
+ if (listen_address && strcmp(addr, listen_address) == 0) {
+ os_unsetenv(LISTEN_ADDRESS_ENV_VAR);
+ }
+
uv_close(server_handle(server), free_server);
// Remove this server from the list by swapping it with the last item.
@@ -242,6 +259,22 @@ void server_stop(char *endpoint)
servers.ga_len--;
}
+/// Returns an allocated array of server addresses.
+/// @param[out] size The size of the returned array.
+char **server_address_list(size_t *size)
+ FUNC_ATTR_NONNULL_ALL
+{
+ if ((*size = (size_t) servers.ga_len) == 0) {
+ return NULL;
+ }
+
+ char **addrs = xcalloc((size_t) servers.ga_len, sizeof(const char **));
+ for (int i = 0; i < servers.ga_len; i++) {
+ addrs[i] = xstrdup(((Server **)servers.ga_data)[i]->addr);
+ }
+ return addrs;
+}
+
static void connection_cb(uv_stream_t *server, int status)
{
int result;