mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
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.
This commit is contained in:
parent
4a66c48d8b
commit
296719428a
@ -5373,13 +5373,25 @@ server2client( {clientid}, {string}) *server2client()*
|
||||
:echo server2client(expand("<client>"), "HELLO")
|
||||
<
|
||||
serverlist() *serverlist()*
|
||||
Return a list of available server names, one per line.
|
||||
When there are no servers or the information is not available
|
||||
an empty string is returned. See also |clientserver|.
|
||||
{only available when compiled with the |+clientserver| feature}
|
||||
Returns a list of available server names in a list.
|
||||
When there are no servers an empty string is returned.
|
||||
Example: >
|
||||
:echo serverlist()
|
||||
<
|
||||
serverlisten([{address}]) *serverlisten()*
|
||||
Opens a Unix or TCP socket at {address} for clients to connect
|
||||
to and returns {address}. If no address is given, it is
|
||||
equivalent to >
|
||||
:call serverlisten(tempname())
|
||||
< If |$NVIM_LISTEN_ADDRESS| is not set, it will be set to
|
||||
{address}.
|
||||
|
||||
serverstop({address}) *serverstop()*
|
||||
Closes the Unix or TCP socket at {address}. Does nothing if
|
||||
{address} is empty, or does not refer to a server. If
|
||||
{address} equals |$NVIM_LISTEN_ADDRESS|, the listen address
|
||||
will be unset.
|
||||
|
||||
setbufvar({expr}, {varname}, {val}) *setbufvar()*
|
||||
Set option or local variable {varname} in buffer {expr} to
|
||||
{val}.
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user