mirror of
https://github.com/vim/vim.git
synced 2026-05-28 00:21:37 +02:00
patch 9.2.0512: clientserver uses binary protocol
Problem: clientserver feature uses binary protocol and is hard
to understand
Solution: Rewrite the code based on channels and JSON messages
(Foxe Chen).
closes: #19782
Signed-off-by: Foxe Chen <chen.foxe@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
1d727b6f74
commit
e9c793bebc
@@ -145,6 +145,7 @@ SRC_ALL = \
|
||||
src/session.c \
|
||||
src/sha256.c \
|
||||
src/sign.c \
|
||||
src/socketserver.c \
|
||||
src/sound.c \
|
||||
src/spell.c \
|
||||
src/spell.h \
|
||||
@@ -344,6 +345,7 @@ SRC_ALL = \
|
||||
src/proto/session.pro \
|
||||
src/proto/sha256.pro \
|
||||
src/proto/sign.pro \
|
||||
src/proto/socketserver.pro \
|
||||
src/proto/sound.pro \
|
||||
src/proto/spell.pro \
|
||||
src/proto/spellfile.pro \
|
||||
|
||||
+47
-32
@@ -79,9 +79,10 @@ The following command line arguments are available:
|
||||
*--clientserver*
|
||||
--clientserver {method} Use the specified method {method} as the
|
||||
backend for clientserver functionality. Can
|
||||
either be "socket" or "x11".
|
||||
either be "socket", "x11", or "mswin".
|
||||
{only available when compiled with both |+X11|
|
||||
and |+socketserver| features}
|
||||
and |+socketserver| features, or
|
||||
|+socketserver| on MS-Windows}
|
||||
|
||||
|
||||
Examples ~
|
||||
@@ -220,12 +221,16 @@ When using gvim, the --remote-wait only works properly this way: >
|
||||
<
|
||||
==============================================================================
|
||||
4. Socket server specific items *socketserver-clientserver*
|
||||
*E1563* *E1564* *E1565* *E1566* *E1567*
|
||||
*E1564* *E1565* *E1566*
|
||||
|
||||
The communication between client and server is done using Unix domain sockets.
|
||||
These sockets are either placed in these directories in the following order of
|
||||
NOTE: Vim version before patch 9.2.511 use a different socketserver backend
|
||||
which is incompatible with the new one, which is based on channels and JSON.
|
||||
|
||||
The communication between client and server is done using channels internally.
|
||||
When using the traditional/generic clientserver naming (only available on
|
||||
Unix), sockets are placed in these directories in the following order of
|
||||
availability:
|
||||
1. "$XDG_RUTIME_DIR/vim" if $XDG_RUNTIME_DIR is set in the environment.
|
||||
1. "$XDG_RUNTIME_DIR/vim" if $XDG_RUNTIME_DIR is set in the environment.
|
||||
2. "$TMPDIR/vim-[uid]", where "[uid]" is the uid of the user. This
|
||||
directory will have the access permissions set to 700 so only the user
|
||||
can read or write from/to it. If $TMPDIR is not set, "/tmp" is used.
|
||||
@@ -237,45 +242,55 @@ absolute or relative path. If the server id starts with either a "/"
|
||||
Otherwise the server id will be the filename of the socket which will be
|
||||
placed in the above common directories. Note that a server id/name can only
|
||||
contain slashes "/" if it is taken as a path, so names such as "abc/dir" will
|
||||
be invalid.
|
||||
be invalid. This feature is only available on Unix.
|
||||
|
||||
Socket server functionality is available in both GTK GUI and terminal versions
|
||||
of Vim. Unless Vim is compiled with |+autoservername| feature, the socket
|
||||
server will have to started explicitly, just like X11, even in the GUI.
|
||||
*socketserver-address*
|
||||
In addition, the socketserver can also be created as a |channel-address|. To
|
||||
do this, prefix the address with "channel:" (which will be ignored). This is
|
||||
available on both Unix and MS-Windows, and is the only available naming for the
|
||||
socketserver backend on Windows. However, note that |ch_listen()|
|
||||
restrictions apply, meaning only port numbers can be used for TCP sockets.
|
||||
|
||||
If the name is prefixed with "name:", then the legacy servername behaviour is
|
||||
used, so "name:VIM" is the same as "VIM".
|
||||
|
||||
Unless Vim is compiled with |+autoservername| feature, the socket server will
|
||||
have to started explicitly, similar to X11. This is unless a X11 GUI Vim is
|
||||
being used.
|
||||
|
||||
If Vim crashes or does not exit cleanly, the socket server will not remove the
|
||||
socket file and it will be left around. This is generally not a problem,
|
||||
because if a socket name is taken, Vim checks if the socket in its place is
|
||||
dead (not attached to any process), and can replace it instead of finding a
|
||||
new name.
|
||||
|
||||
To send commands to a Vim socket server from another application, read the
|
||||
source file src/os_unix.c, there is detailed description of the protocol used.
|
||||
new name. This is only relevant for Unix.
|
||||
|
||||
*socketserver-differences*
|
||||
Most of the functionality is the same as X11, however unlike X11, where the
|
||||
client does not need to be a server in order to communicate with another
|
||||
server, the socket server requires the server to be running even as a client.
|
||||
The exception is |serverlist()| or the |--serverlist| argument, which does not
|
||||
require the server to be running.
|
||||
Most of the functionality is the same as the other clientserver backends.
|
||||
|
||||
Additionally, the server id or client id will not be a number like X11 or
|
||||
However, the server id or client id will not be a number like X11 or
|
||||
MS-Windows (shown in hex representation), instead it is the absolute path to
|
||||
the socket. This can be seen via the |v:servername| variable.
|
||||
the socket. This can be seen via the |v:servername| variable. If the name is
|
||||
a channel address, then it will be the address with the "a/" prefix as well.
|
||||
|
||||
The |--serverlist| argument will act just like X11, however it only checks the
|
||||
given common directories above. If a custom path is used for a socket, it
|
||||
will not be detected, such as a path either not in $XDG_RUNTIME_DIR or
|
||||
<$TMPDIR or /tmp>/vim of the |--serverlist| Vim process.
|
||||
Note when using |--remote-wait|, the client id will look like "t/<some
|
||||
number>". This naming is specifically for this command, and attempting to use
|
||||
it as an address will fail.
|
||||
|
||||
If you have both |+socketserver| and |+X11| compiled, you will need to add
|
||||
|--clientserver| set to "socket" in combination with |--serverlist| to list
|
||||
the available servers. You cannot list both types of backends in one command.
|
||||
If on Unix, the |--serverlist| argument will act just like X11, however it
|
||||
only checks the given common directories above. If a custom path is used for
|
||||
a socket, it will not be detected, such as a path either not in
|
||||
$XDG_RUNTIME_DIR or <$TMPDIR or /tmp>/vim of the |--serverlist| Vim process.
|
||||
If on MS-Windows, then the |--serverlist| argument will output nothing.
|
||||
|
||||
The |+socketserver| feature is automatically enabled when on Unix or
|
||||
MS-Windows, and the |+channel| feature is enabled
|
||||
|
||||
*socketserver-x11*
|
||||
If Vim is compiled with both |+X11| and |+socketserver|, then deciding which
|
||||
backend to use is done at startup time, via the |--clientserver| argument. By
|
||||
default if it is not specified, then X11 will be used. A Vim instance using a
|
||||
socket server cannot communicate with one using X11.
|
||||
If Vim is compiled with |+socketserver| and another clientserver backend, then
|
||||
deciding which backend to use is done at startup time, via the
|
||||
|--clientserver| argument. By default if it is not specified, then the native
|
||||
backend (X11 or MS-Window messages) will be used, if available. A Vim
|
||||
instance using a socket server cannot communicate with one using another
|
||||
clientserver backend.
|
||||
|
||||
vim:tw=78:sw=4:ts=8:noet:ft=help:norl:
|
||||
|
||||
+1
-2
@@ -4762,11 +4762,9 @@ E156 sign.txt /*E156*
|
||||
E1560 vim9.txt /*E1560*
|
||||
E1561 vim9.txt /*E1561*
|
||||
E1562 options.txt /*E1562*
|
||||
E1563 remote.txt /*E1563*
|
||||
E1564 remote.txt /*E1564*
|
||||
E1565 remote.txt /*E1565*
|
||||
E1566 remote.txt /*E1566*
|
||||
E1567 remote.txt /*E1567*
|
||||
E1568 options.txt /*E1568*
|
||||
E1569 builtin.txt /*E1569*
|
||||
E157 sign.txt /*E157*
|
||||
@@ -10377,6 +10375,7 @@ slow-fast-terminal term.txt /*slow-fast-terminal*
|
||||
slow-start starting.txt /*slow-start*
|
||||
slow-terminal term.txt /*slow-terminal*
|
||||
socket-interface channel.txt /*socket-interface*
|
||||
socketserver-address remote.txt /*socketserver-address*
|
||||
socketserver-clientserver remote.txt /*socketserver-clientserver*
|
||||
socketserver-differences remote.txt /*socketserver-differences*
|
||||
socketserver-name remote.txt /*socketserver-name*
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
*version9.txt* For Vim version 9.2. Last change: 2026 May 19
|
||||
*version9.txt* For Vim version 9.2. Last change: 2026 May 22
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -52665,6 +52665,7 @@ Changed ~
|
||||
if needed, see |wayland-primary-selection| for an example.
|
||||
- On Unix, filename completion for single-file Ex commands now treats embedded
|
||||
whitespace as part of the filename, like on other platforms.
|
||||
- Rewrite the clientserver socketserver backend to use channels and JSON.
|
||||
|
||||
|
||||
*added-9.3*
|
||||
|
||||
+4
-3
@@ -504,9 +504,10 @@ socketserver backend is being used, if the name starts with "/", "./", or "../",
|
||||
it is taken as either an absolute, relative or relative path to the socket.
|
||||
.TP
|
||||
\-\-clientserver {backend}
|
||||
Use {backend} as the backend for clientserver functionality, either "socket" or
|
||||
"x11" respectively. Only available when compiled with both socketserver and X11
|
||||
features present
|
||||
Use {backend} as the backend for clientserver functionality, either "socket",
|
||||
"x11", or "mswin" respectively. Only available when compiled with both
|
||||
socketserver and X11 features present, or if compiled with socketserver on
|
||||
MS-Windows.
|
||||
.TP
|
||||
\-\-socketid {id}
|
||||
GTK GUI only: Use the GtkPlug mechanism to run gVim in another window.
|
||||
|
||||
+4
-3
@@ -385,9 +385,10 @@ OPTIONS
|
||||
|
||||
--clientserver {backend}
|
||||
Use {backend} as the backend for clientserver functional‐
|
||||
ity, either "socket" or "x11" respectively. Only available
|
||||
when compiled with both socketserver and X11 features
|
||||
present
|
||||
ity, either "socket", "x11", or "mswin" respectively. Only
|
||||
available when compiled with both socketserver and X11 fea‐
|
||||
tures present, or if compiled with socketserver on MS-Win‐
|
||||
dows.
|
||||
|
||||
--socketid {id}
|
||||
GTK GUI only: Use the GtkPlug mechanism to run gVim in an‐
|
||||
|
||||
@@ -877,6 +877,7 @@ OBJ = \
|
||||
$(OUTDIR)/session.o \
|
||||
$(OUTDIR)/sha256.o \
|
||||
$(OUTDIR)/sign.o \
|
||||
$(OUTDIR)/socketserver.o \
|
||||
$(OUTDIR)/spell.o \
|
||||
$(OUTDIR)/spellfile.o \
|
||||
$(OUTDIR)/spellsuggest.o \
|
||||
|
||||
@@ -772,6 +772,7 @@ OBJ = \
|
||||
$(OUTDIR)\session.obj \
|
||||
$(OUTDIR)\sha256.obj \
|
||||
$(OUTDIR)\sign.obj \
|
||||
$(OUTDIR)\socketserver.obj \
|
||||
$(OUTDIR)\spell.obj \
|
||||
$(OUTDIR)\spellfile.obj \
|
||||
$(OUTDIR)\spellsuggest.obj \
|
||||
@@ -1767,6 +1768,8 @@ $(OUTDIR)/sha256.obj: $(OUTDIR) sha256.c $(INCL)
|
||||
|
||||
$(OUTDIR)/sign.obj: $(OUTDIR) sign.c $(INCL)
|
||||
|
||||
$(OUTDIR)/socketserver.obj: $(OUTDIR) socketserver.c $(INCL)
|
||||
|
||||
$(OUTDIR)/spell.obj: $(OUTDIR) spell.c $(INCL)
|
||||
|
||||
$(OUTDIR)/spellfile.obj: $(OUTDIR) spellfile.c $(INCL)
|
||||
@@ -2017,6 +2020,7 @@ proto.h: \
|
||||
proto/session.pro \
|
||||
proto/sha256.pro \
|
||||
proto/sign.pro \
|
||||
proto/socketserver.pro \
|
||||
proto/spell.pro \
|
||||
proto/spellfile.pro \
|
||||
proto/spellsuggest.pro \
|
||||
|
||||
@@ -1571,6 +1571,7 @@ BASIC_SRC = \
|
||||
session.c \
|
||||
sha256.c \
|
||||
sign.c \
|
||||
socketserver.c \
|
||||
sound.c \
|
||||
spell.c \
|
||||
spellfile.c \
|
||||
@@ -1749,6 +1750,7 @@ OBJ_COMMON = \
|
||||
objects/session.o \
|
||||
objects/sha256.o \
|
||||
objects/sign.o \
|
||||
objects/socketserver.o \
|
||||
objects/sound.o \
|
||||
objects/spell.o \
|
||||
objects/spellfile.o \
|
||||
@@ -3592,6 +3594,9 @@ objects/sha256.o: sha256.c
|
||||
objects/sign.o: sign.c
|
||||
$(CCC) -o $@ sign.c
|
||||
|
||||
objects/socketserver.o: socketserver.c
|
||||
$(CCC) -o $@ socketserver.c
|
||||
|
||||
objects/sound.o: sound.c
|
||||
$(CCC) -o $@ sound.c
|
||||
|
||||
@@ -4267,6 +4272,11 @@ objects/sign.o: auto/osdef.h sign.c vim.h protodef.h auto/config.h feature.h os_
|
||||
structs.h regexp.h gui.h libvterm/include/vterm.h \
|
||||
libvterm/include/vterm_keycodes.h alloc.h ex_cmds.h spell.h proto.h \
|
||||
globals.h errors.h
|
||||
objects/socketserver.o: socketserver.c vim.h protodef.h auto/config.h feature.h \
|
||||
os_unix.h auto/osdef.h ascii.h keymap.h termdefs.h macros.h option.h \
|
||||
beval.h structs.h regexp.h gui.h libvterm/include/vterm.h \
|
||||
libvterm/include/vterm_keycodes.h xdiff/xdiff.h xdiff/../vim.h alloc.h \
|
||||
ex_cmds.h spell.h proto.h globals.h errors.h
|
||||
objects/sound.o: auto/osdef.h sound.c vim.h protodef.h auto/config.h feature.h os_unix.h \
|
||||
ascii.h keymap.h termdefs.h macros.h option.h beval.h \
|
||||
structs.h regexp.h gui.h libvterm/include/vterm.h \
|
||||
@@ -4793,6 +4803,7 @@ proto/search.pro: search.c
|
||||
proto/session.pro: session.c
|
||||
proto/sha256.pro: sha256.c
|
||||
proto/sign.pro: sign.c
|
||||
proto/socketserver.pro: socketserver.c
|
||||
proto/sound.pro: sound.c
|
||||
proto/spell.pro: spell.c
|
||||
proto/spellfile.pro: spellfile.c
|
||||
|
||||
Vendored
-32
@@ -850,7 +850,6 @@ enable_netbeans
|
||||
enable_channel
|
||||
enable_terminal
|
||||
enable_autoservername
|
||||
enable_socketserver
|
||||
enable_multibyte
|
||||
enable_rightleft
|
||||
enable_arabic
|
||||
@@ -1532,7 +1531,6 @@ Optional Features:
|
||||
--disable-channel Disable process communication support.
|
||||
--enable-terminal Enable terminal emulation support.
|
||||
--enable-autoservername Automatically define servername at vim startup.
|
||||
--enable-socketserver Use sockets for clientserver communication.
|
||||
--enable-multibyte Include multibyte editing support.
|
||||
--disable-rightleft Do not include Right-to-Left language support.
|
||||
--disable-arabic Do not include Arabic language support.
|
||||
@@ -9077,36 +9075,6 @@ if test "$enable_autoservername" = "yes"; then
|
||||
|
||||
fi
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking --enable-socketserver argument" >&5
|
||||
printf %s "checking --enable-socketserver argument... " >&6; }
|
||||
# Check whether --enable-socketserver was given.
|
||||
if test ${enable_socketserver+y}
|
||||
then :
|
||||
enableval=$enable_socketserver; enable_socketserver=$enableval
|
||||
else case e in #(
|
||||
e) if test "x$features" = xtiny
|
||||
then :
|
||||
enable_socketserver=no_msg
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cannot use socketserver with tiny features" >&5
|
||||
printf "%s\n" "cannot use socketserver with tiny features" >&6; }
|
||||
else case e in #(
|
||||
e) enable_socketserver=yes ;;
|
||||
esac
|
||||
fi ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
|
||||
if test "$enable_socketserver" = "yes"; then
|
||||
printf "%s\n" "#define WANT_SOCKETSERVER 1" >>confdefs.h
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
printf "%s\n" "yes" >&6; }
|
||||
elif test "$enable_socketserver" = "no"; then
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
printf "%s\n" "no" >&6; }
|
||||
fi
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking --enable-multibyte argument" >&5
|
||||
printf %s "checking --enable-multibyte argument... " >&6; }
|
||||
# Check whether --enable-multibyte was given.
|
||||
|
||||
+111
-21
@@ -820,7 +820,7 @@ channel_connect(
|
||||
* Returns the channel for success.
|
||||
* Returns NULL for failure.
|
||||
*/
|
||||
static channel_T *
|
||||
channel_T *
|
||||
channel_open_unix(
|
||||
const char *path,
|
||||
void (*nb_close_cb)(void))
|
||||
@@ -1290,6 +1290,46 @@ channel_set_options(channel_T *channel, jobopt_T *opt)
|
||||
channel->ch_part[PART_IN].ch_io = opt->jo_io[PART_IN];
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the address for socketserver and store port in "port", or the path in
|
||||
* "unix_path" if it is a unix domain socket. Returns OK on success and FAIL on
|
||||
* failure.
|
||||
*/
|
||||
int
|
||||
channel_parse_socketserver_address(
|
||||
char_u *address,
|
||||
int *port,
|
||||
char_u **unix_path,
|
||||
bool quiet)
|
||||
{
|
||||
char *rest;
|
||||
long val;
|
||||
|
||||
if (*address == NUL)
|
||||
goto fail;
|
||||
|
||||
if (!STRNCMP(address, "unix:", 5))
|
||||
{
|
||||
*unix_path = vim_strsave(address + 5);
|
||||
return OK;
|
||||
}
|
||||
|
||||
val = strtol((char *)(address), &rest, 10);
|
||||
if (val < 0 || val >= 65536 || *rest != NUL)
|
||||
{
|
||||
if (!quiet)
|
||||
semsg(_(e_invalid_argument_str), address);
|
||||
return FAIL;
|
||||
}
|
||||
*port = (int)val;
|
||||
|
||||
return OK;
|
||||
fail:
|
||||
if (!quiet)
|
||||
semsg(_(e_invalid_argument_str), address);
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements ch_open().
|
||||
*/
|
||||
@@ -1449,7 +1489,7 @@ channel_listen_func(typval_T *argvars)
|
||||
}
|
||||
|
||||
if (is_unix)
|
||||
channel = channel_listen_unix((char *)arg, NULL);
|
||||
channel = channel_listen_unix((char *)arg, NULL, true);
|
||||
else
|
||||
channel = channel_listen(port, NULL);
|
||||
if (channel != NULL)
|
||||
@@ -1571,13 +1611,15 @@ channel_listen(
|
||||
|
||||
/*
|
||||
* Listen to a Unix domain socket channel.
|
||||
* If "replace" is true, then unlink the path first beforehand.
|
||||
* Returns the channel for success.
|
||||
* Returns NULL for failure.
|
||||
*/
|
||||
channel_T *
|
||||
channel_listen_unix(
|
||||
char *path,
|
||||
void (*nb_close_cb)(void))
|
||||
void (*nb_close_cb)(void),
|
||||
bool replace)
|
||||
{
|
||||
int sd = -1;
|
||||
struct sockaddr_un server;
|
||||
@@ -1619,8 +1661,9 @@ channel_listen_unix(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Unlink the socket in case it already exists
|
||||
unlink(server.sun_path);
|
||||
if (replace)
|
||||
// Unlink the socket in case it already exists
|
||||
unlink(server.sun_path);
|
||||
|
||||
// Bind the socket to the path
|
||||
server_len = offsetof(struct sockaddr_un, sun_path) + path_len + 1;
|
||||
@@ -1983,7 +2026,7 @@ channel_buffer_free(buf_T *buf)
|
||||
/*
|
||||
* Write any lines waiting to be written to "channel".
|
||||
*/
|
||||
static void
|
||||
void
|
||||
channel_write_input(channel_T *channel)
|
||||
{
|
||||
chanpart_T *in_part = &channel->ch_part[PART_IN];
|
||||
@@ -2364,7 +2407,7 @@ channel_save(channel_T *channel, ch_part_T part, char_u *buf, int len,
|
||||
* Try to fill the buffer of "reader".
|
||||
* Returns FALSE when nothing was added.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
channel_fill(js_read_T *reader)
|
||||
{
|
||||
channel_T *channel = (channel_T *)reader->js_cookie;
|
||||
@@ -2484,11 +2527,12 @@ channel_process_lspdap_http_hdr(js_read_T *reader)
|
||||
|
||||
/*
|
||||
* Use the read buffer of "channel"/"part" and parse a JSON message that is
|
||||
* complete. The messages are added to the queue.
|
||||
* complete. The messages are added to the queue. If "socketserver" is true,
|
||||
* then ignore the channel mode.
|
||||
* Return TRUE if there is more to read.
|
||||
*/
|
||||
static int
|
||||
channel_parse_json(channel_T *channel, ch_part_T part)
|
||||
int
|
||||
channel_parse_json(channel_T *channel, ch_part_T part, bool socketserver)
|
||||
{
|
||||
js_read_T reader;
|
||||
typval_T listtv;
|
||||
@@ -2507,8 +2551,8 @@ channel_parse_json(channel_T *channel, ch_part_T part)
|
||||
reader.js_cookie = channel;
|
||||
reader.js_cookie_arg = part;
|
||||
|
||||
if (chanpart->ch_mode == CH_MODE_LSP
|
||||
|| chanpart->ch_mode == CH_MODE_DAP)
|
||||
if (!socketserver && (chanpart->ch_mode == CH_MODE_LSP
|
||||
|| chanpart->ch_mode == CH_MODE_DAP))
|
||||
status = channel_process_lspdap_http_hdr(&reader);
|
||||
|
||||
// When a message is incomplete we wait for a short while for more to
|
||||
@@ -2526,14 +2570,16 @@ channel_parse_json(channel_T *channel, ch_part_T part)
|
||||
{
|
||||
// Only accept the response when it is a list with at least two
|
||||
// items.
|
||||
if ((chanpart->ch_mode == CH_MODE_LSP || chanpart->ch_mode == CH_MODE_DAP)
|
||||
if (!socketserver && (chanpart->ch_mode == CH_MODE_LSP
|
||||
|| chanpart->ch_mode == CH_MODE_DAP)
|
||||
&& listtv.v_type != VAR_DICT)
|
||||
{
|
||||
ch_error(channel, "Did not receive a LSP dict, discarding");
|
||||
clear_tv(&listtv);
|
||||
}
|
||||
else if (chanpart->ch_mode != CH_MODE_LSP && chanpart->ch_mode != CH_MODE_DAP
|
||||
&& (listtv.v_type != VAR_LIST || listtv.vval.v_list->lv_len < 2))
|
||||
else if (!socketserver && chanpart->ch_mode != CH_MODE_LSP
|
||||
&& chanpart->ch_mode != CH_MODE_DAP
|
||||
&& (listtv.v_type != VAR_LIST || listtv.vval.v_list->lv_len < 2))
|
||||
{
|
||||
if (listtv.v_type != VAR_LIST)
|
||||
ch_error(channel, "Did not receive a list, discarding");
|
||||
@@ -2668,7 +2714,7 @@ remove_cb_node(cbq_T *head, cbq_T *node)
|
||||
* Remove "node" from the queue that it is in and free it.
|
||||
* Caller should have freed or used node->jq_value.
|
||||
*/
|
||||
static void
|
||||
void
|
||||
remove_json_node(jsonq_T *head, jsonq_T *node)
|
||||
{
|
||||
if (node->jq_prev == NULL)
|
||||
@@ -3227,8 +3273,12 @@ may_invoke_callback(channel_T *channel, ch_part_T part)
|
||||
int called_otc; // one time callbackup
|
||||
int raw_len = 0;
|
||||
|
||||
if (channel->ch_nb_close_cb != NULL)
|
||||
// this channel is handled elsewhere (netbeans)
|
||||
if (channel->ch_nb_close_cb != NULL
|
||||
#ifdef FEAT_SOCKETSERVER
|
||||
|| channel->ch_socketserver
|
||||
#endif
|
||||
)
|
||||
// this channel is handled elsewhere (netbeans or socketserver)
|
||||
return FALSE;
|
||||
|
||||
// Use a message-specific callback, part callback or channel callback
|
||||
@@ -3267,7 +3317,7 @@ may_invoke_callback(channel_T *channel, ch_part_T part)
|
||||
(void)channel_collapse(channel, part, FALSE);
|
||||
|
||||
// Parse readahead, return when there is still no message.
|
||||
channel_parse_json(channel, part);
|
||||
channel_parse_json(channel, part, false);
|
||||
if (channel_get_json(channel, part, -1, FALSE, &listtv) == FAIL)
|
||||
return FALSE;
|
||||
}
|
||||
@@ -3595,7 +3645,7 @@ channel_readahead_pointer(channel_T *channel, ch_part_T part)
|
||||
if (head->jq_next == NULL)
|
||||
// Parse json from readahead, there might be a complete message to
|
||||
// process.
|
||||
channel_parse_json(channel, part);
|
||||
channel_parse_json(channel, part, false);
|
||||
|
||||
return head->jq_next;
|
||||
}
|
||||
@@ -3842,6 +3892,11 @@ channel_close(channel_T *channel, int invoke_close_cb)
|
||||
}
|
||||
|
||||
channel->ch_nb_close_cb = NULL;
|
||||
#ifdef FEAT_SOCKETSERVER
|
||||
channel->ch_socketserver = false;
|
||||
channel->ch_ss_accept_cb = NULL;
|
||||
channel->ch_ss_close_cb = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_TERMINAL
|
||||
term_channel_closed(channel);
|
||||
@@ -4181,6 +4236,10 @@ channel_close_now(channel_T *channel)
|
||||
ch_log(channel, "Closing channel because all readable fds are closed");
|
||||
if (channel->ch_nb_close_cb != NULL)
|
||||
(*channel->ch_nb_close_cb)();
|
||||
#ifdef FEAT_SOCKETSERVER
|
||||
if (channel->ch_ss_close_cb != NULL)
|
||||
channel->ch_ss_close_cb(channel);
|
||||
#endif
|
||||
channel_close(channel, TRUE);
|
||||
}
|
||||
|
||||
@@ -4252,6 +4311,14 @@ channel_read(channel_T *channel, ch_part_T part, char *func)
|
||||
channel_gui_register_one(newchannel, PART_SOCK);
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_SOCKETSERVER
|
||||
if (channel->ch_ss_accept_cb != NULL)
|
||||
{
|
||||
channel->ch_ss_accept_cb(newchannel);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (client.ss_family == AF_INET)
|
||||
{
|
||||
#ifdef HAVE_INET_NTOP
|
||||
@@ -4323,6 +4390,16 @@ channel_read(channel_T *channel, ch_part_T part, char *func)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef FEAT_SOCKETSERVER
|
||||
|
||||
void
|
||||
channel_check(channel_T *channel, ch_part_T part)
|
||||
{
|
||||
channel_read(channel, part, "channel_check");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Read from RAW or NL "channel"/"part". Blocks until there is something to
|
||||
* read or the timeout expires.
|
||||
@@ -4465,7 +4542,7 @@ channel_read_json_block(
|
||||
// received messages.
|
||||
(void)channel_collapse(channel, part, FALSE);
|
||||
|
||||
more = channel_parse_json(channel, part);
|
||||
more = channel_parse_json(channel, part, false);
|
||||
|
||||
// search for message "id"
|
||||
if (channel_get_json(channel, part, id, TRUE, rettv) == OK)
|
||||
@@ -5915,4 +5992,17 @@ channel_to_string_buf(typval_T *varp, char_u *buf)
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the channel with the given ID. Returns NULL if not found.
|
||||
*/
|
||||
channel_T *
|
||||
channel_find(int ch_id)
|
||||
{
|
||||
channel_T *ch;
|
||||
FOR_ALL_CHANNELS(ch)
|
||||
if (ch->ch_id == ch_id)
|
||||
return ch;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif // FEAT_JOB_CHANNEL
|
||||
|
||||
+179
-187
@@ -15,11 +15,6 @@
|
||||
|
||||
#if defined(FEAT_CLIENTSERVER)
|
||||
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
# include <sys/socket.h>
|
||||
# include "sys/un.h"
|
||||
# endif
|
||||
|
||||
static void cmdsrv_main(int *argc, char **argv, char_u *serverName_arg, char_u **serverStr);
|
||||
static char_u *serverMakeName(char_u *arg, char *cmd);
|
||||
|
||||
@@ -206,23 +201,6 @@ exec_on_server(mparm_T *parmp)
|
||||
serverInitMessaging();
|
||||
# endif
|
||||
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
// If servername is specified and we are using sockets, always init the
|
||||
// sockt server. We may need to receive replies back to us. If --serverlist
|
||||
// is passed, the socket server will be uninitialized before listing
|
||||
// sockets then initialized after. This is so we don't add our own socket
|
||||
// in the list. This does not happen in serverlist().
|
||||
if ((parmp->serverArg || parmp->serverName_arg != NULL) &&
|
||||
clientserver_method == CLIENTSERVER_METHOD_SOCKET)
|
||||
{
|
||||
parmp->servername = serverMakeName(parmp->serverName_arg,
|
||||
parmp->argv[0]);
|
||||
if (socket_server_init(parmp->servername) == OK)
|
||||
TIME_MSG("initialize socket server");
|
||||
made_name = TRUE;
|
||||
}
|
||||
# endif
|
||||
|
||||
/*
|
||||
* When a command server argument was found, execute it. This may
|
||||
* exit Vim when it was successful. Otherwise it's executed further
|
||||
@@ -242,10 +220,12 @@ exec_on_server(mparm_T *parmp)
|
||||
parmp->servername = serverMakeName(parmp->serverName_arg,
|
||||
parmp->argv[0]);
|
||||
# ifdef MSWIN
|
||||
if (parmp->servername != NULL)
|
||||
if (parmp->servername != NULL && clientserver_method == CLIENTSERVER_METHOD_MSWIN)
|
||||
{
|
||||
serverSetName(parmp->servername);
|
||||
# ifndef FEAT_SOCKETSERVER
|
||||
vim_free(parmp->servername);
|
||||
# endif
|
||||
}
|
||||
# endif
|
||||
}
|
||||
@@ -262,16 +242,31 @@ prepare_server(mparm_T *parmp)
|
||||
* Only register nongui-vim's with an explicit --servername argument,
|
||||
* or when compiling with autoservername.
|
||||
* When running as root --servername is also required.
|
||||
*
|
||||
* If we are Windows and socketserver is being used, then don't use
|
||||
* autoservername, since traditional naming isn't supported.
|
||||
*/
|
||||
|
||||
if (
|
||||
# ifdef FEAT_X11
|
||||
X_DISPLAY != NULL &&
|
||||
# if defined(FEAT_X11) || (defined(FEAT_SOCKETSERVER) && !defined(MSWIN))
|
||||
(
|
||||
# ifdef FEAT_X11
|
||||
X_DISPLAY != NULL
|
||||
# endif
|
||||
# if defined(FEAT_X11) && defined(FEAT_SOCKETSERVER) && !defined(MSWIN)
|
||||
||
|
||||
# endif
|
||||
# if defined(FEAT_SOCKETSERVER) && !defined(MSWIN)
|
||||
clientserver_method == CLIENTSERVER_METHOD_SOCKET
|
||||
# endif
|
||||
) &&
|
||||
# endif
|
||||
|
||||
parmp->servername != NULL && (
|
||||
# if defined(FEAT_AUTOSERVERNAME) || defined(FEAT_GUI)
|
||||
(
|
||||
# if defined(FEAT_SOCKETSERVER) && defined(MSWIN)
|
||||
clientserver_method != CLIENTSERVER_METHOD_SOCKET &&
|
||||
# endif
|
||||
# if defined(FEAT_AUTOSERVERNAME)
|
||||
1
|
||||
# else
|
||||
@@ -284,12 +279,10 @@ prepare_server(mparm_T *parmp)
|
||||
# endif
|
||||
parmp->serverName_arg != NULL))
|
||||
{
|
||||
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_SOCKET)
|
||||
{
|
||||
if (socket_server_init(parmp->servername) == OK)
|
||||
TIME_MSG("initialize socket server");
|
||||
}
|
||||
socketserver_start(parmp->servername, false);
|
||||
# endif
|
||||
# ifdef FEAT_X11
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_X11)
|
||||
@@ -300,10 +293,15 @@ prepare_server(mparm_T *parmp)
|
||||
# endif
|
||||
vim_free(parmp->servername);
|
||||
}
|
||||
# ifdef FEAT_X11
|
||||
else
|
||||
serverDelayedStartName = parmp->servername;
|
||||
{
|
||||
# ifdef FEAT_X11
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_X11)
|
||||
serverDelayedStartName = parmp->servername;
|
||||
else
|
||||
# endif
|
||||
vim_free(parmp->servername);
|
||||
}
|
||||
# endif
|
||||
|
||||
/*
|
||||
@@ -343,9 +341,6 @@ cmdsrv_main(
|
||||
# define ARGTYPE_SEND 3
|
||||
int silent = FALSE;
|
||||
int tabs = FALSE;
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
char_u *receiver;
|
||||
# endif
|
||||
# ifdef MSWIN
|
||||
HWND srv;
|
||||
# elif defined(FEAT_X11)
|
||||
@@ -353,6 +348,9 @@ cmdsrv_main(
|
||||
|
||||
setup_term_clip();
|
||||
# endif
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
channel_T *ch = NULL;
|
||||
# endif
|
||||
|
||||
sname = serverMakeName(serverName_arg, argv[0]);
|
||||
if (sname == NULL)
|
||||
@@ -434,9 +432,8 @@ cmdsrv_main(
|
||||
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_SOCKET)
|
||||
ret = socket_server_send(
|
||||
sname, *serverStr, NULL, &receiver,
|
||||
0, -1, silent);
|
||||
ret = socketserver_send(sname, *serverStr, NULL, false, -1,
|
||||
silent, &ch);
|
||||
# endif
|
||||
# ifdef FEAT_X11
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_X11)
|
||||
@@ -452,8 +449,10 @@ cmdsrv_main(
|
||||
}
|
||||
# endif
|
||||
# ifdef MSWIN
|
||||
// Win32 always works?
|
||||
ret = serverSendToVim(sname, *serverStr, NULL, &srv, 0, 0, silent);
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_MSWIN)
|
||||
// Win32 always works?
|
||||
ret = serverSendToVim(sname, *serverStr, NULL, &srv, 0, 0,
|
||||
silent);
|
||||
# endif
|
||||
if (ret < 0)
|
||||
{
|
||||
@@ -513,23 +512,23 @@ cmdsrv_main(
|
||||
char_u *p = NULL;
|
||||
int j;
|
||||
# ifdef MSWIN
|
||||
p = serverGetReply(srv, NULL, TRUE, TRUE, 0);
|
||||
if (p == NULL)
|
||||
break;
|
||||
# else
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_MSWIN)
|
||||
p = serverGetReply(srv, NULL, TRUE, TRUE, 0);
|
||||
# endif
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_SOCKET
|
||||
&& socket_server_read_reply(receiver, &p, -1) == FAIL)
|
||||
&& (ch == NULL
|
||||
|| socketserver_read_reply(sname, &p, -1, true)
|
||||
== FAIL))
|
||||
break;
|
||||
# endif
|
||||
# ifdef FEAT_X11
|
||||
# endif
|
||||
# ifdef FEAT_X11
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_X11
|
||||
&& serverReadReply(xterm_dpy, srv, &p, TRUE, -1) < 0)
|
||||
break;
|
||||
# endif
|
||||
# endif
|
||||
if (p == NULL)
|
||||
break;
|
||||
# endif
|
||||
j = atoi((char *)p);
|
||||
vim_free(p);
|
||||
if (j >= 0 && j < numFiles)
|
||||
@@ -543,6 +542,13 @@ cmdsrv_main(
|
||||
done[j] = 1;
|
||||
}
|
||||
}
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (ch != NULL)
|
||||
{
|
||||
channel_close(ch, false);
|
||||
channel_clear(ch);
|
||||
}
|
||||
# endif
|
||||
# ifdef FEAT_GUI_MSWIN
|
||||
Shell_NotifyIcon(NIM_DELETE, &ni);
|
||||
# endif
|
||||
@@ -551,25 +557,24 @@ cmdsrv_main(
|
||||
}
|
||||
else if (STRICMP(argv[i], "--remote-expr") == 0)
|
||||
{
|
||||
int status = OK;
|
||||
|
||||
if (i == *argc - 1)
|
||||
mainerr_arg_missing((char_u *)argv[i]);
|
||||
# ifdef MSWIN
|
||||
// Win32 always works?
|
||||
if (serverSendToVim(sname, (char_u *)argv[i + 1],
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_MSWIN
|
||||
&& serverSendToVim(sname, (char_u *)argv[i + 1],
|
||||
&res, NULL, 1, 0, FALSE) < 0)
|
||||
# else
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_SOCKET)
|
||||
{
|
||||
if (!socket_server_valid())
|
||||
mch_errmsg(_("Socket server not online:"
|
||||
"Send expression failed"));
|
||||
else if (socket_server_send(sname, (char_u *)argv[i + 1],
|
||||
&res, NULL, 1, 0, FALSE) < 0)
|
||||
goto expr_fail;
|
||||
}
|
||||
# endif
|
||||
# ifdef FEAT_X11
|
||||
status = FAIL;
|
||||
# endif
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_SOCKET
|
||||
&& socketserver_send(sname, (char_u *)argv[i + 1],
|
||||
&res, 1, 0, false, NULL) < 0)
|
||||
status = FAIL;
|
||||
# endif
|
||||
# ifdef FEAT_X11
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_X11)
|
||||
{
|
||||
if (xterm_dpy == NULL)
|
||||
@@ -577,15 +582,11 @@ cmdsrv_main(
|
||||
else if (serverSendToVim(xterm_dpy, sname,
|
||||
(char_u *)argv[i + 1], &res,
|
||||
NULL, 1, 0, 1, FALSE) < 0)
|
||||
goto expr_fail;
|
||||
status = FAIL;
|
||||
}
|
||||
# endif
|
||||
if (FALSE)
|
||||
# endif
|
||||
if (status == FAIL)
|
||||
{
|
||||
# if !defined(MSWIN)
|
||||
expr_fail:
|
||||
# endif
|
||||
if (res != NULL && *res != NUL)
|
||||
{
|
||||
// Output error from remote
|
||||
@@ -598,28 +599,22 @@ expr_fail:
|
||||
else if (STRICMP(argv[i], "--serverlist") == 0)
|
||||
{
|
||||
# ifdef MSWIN
|
||||
// Win32 always works?
|
||||
res = serverGetVimNames();
|
||||
# else
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_MSWIN)
|
||||
// Win32 always works?
|
||||
res = serverGetVimNames();
|
||||
# endif
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_SOCKET)
|
||||
{
|
||||
int was_init = socket_server_valid();
|
||||
|
||||
// Don't want to add ourselves to the list. So shutdown the
|
||||
// server before listing then startup back again.
|
||||
socket_server_uninit();
|
||||
res = socket_server_list_sockets();
|
||||
|
||||
if (was_init)
|
||||
socket_server_init(NULL);
|
||||
}
|
||||
# ifdef MSWIN
|
||||
res = vim_strsave((char_u *)"");
|
||||
# else
|
||||
res = socketserver_list();
|
||||
# endif
|
||||
# ifdef FEAT_X11
|
||||
# endif
|
||||
# ifdef FEAT_X11
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_X11 &&
|
||||
xterm_dpy != NULL)
|
||||
res = serverGetVimNames(xterm_dpy);
|
||||
# endif
|
||||
# endif
|
||||
if (did_emsg)
|
||||
mch_errmsg("\n");
|
||||
@@ -648,9 +643,6 @@ expr_fail:
|
||||
|
||||
if (didone)
|
||||
{
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
socket_server_uninit();
|
||||
# endif
|
||||
display_errors(); // display any collected messages
|
||||
exit(exiterr); // Mission accomplished - get out
|
||||
}
|
||||
@@ -807,12 +799,12 @@ serverMakeName(char_u *arg, char *cmd)
|
||||
if (arg != NULL && *arg != NUL)
|
||||
{
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
// If we are using a socket server, we want to preserve the original
|
||||
// name if it is a path, else uppercase it if its just a generic name.
|
||||
// When using socketserver backend, do not change the name if path or
|
||||
// channel address.
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_SOCKET)
|
||||
{
|
||||
if (arg[0] == '/' || STRNCMP(arg, "./", 2) == 0 ||
|
||||
STRNCMP(arg, "../", 3) == 0)
|
||||
if (STRNICMP(arg, "channel:", 8) == 0 || arg[0] == '/' ||
|
||||
STRNCMP(arg, "./", 2) == 0 || STRNCMP(arg, "../", 3) == 0)
|
||||
p = vim_strsave(arg);
|
||||
else
|
||||
p = vim_strsave_up(arg);
|
||||
@@ -853,6 +845,8 @@ make_connection(void)
|
||||
static int
|
||||
check_connection(void)
|
||||
{
|
||||
if (clientserver_method != CLIENTSERVER_METHOD_X11)
|
||||
return OK;
|
||||
make_connection();
|
||||
if (X_DISPLAY == NULL)
|
||||
{
|
||||
@@ -878,10 +872,8 @@ remote_common(typval_T *argvars, typval_T *rettv, int expr)
|
||||
# ifdef FEAT_X11
|
||||
Window w;
|
||||
# endif
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
char_u *client = NULL;
|
||||
# endif
|
||||
# endif
|
||||
int ret = OK;
|
||||
|
||||
if (check_restricted() || check_secure())
|
||||
return;
|
||||
@@ -899,35 +891,29 @@ remote_common(typval_T *argvars, typval_T *rettv, int expr)
|
||||
return; // type error; errmsg already given
|
||||
keys = tv_get_string_buf(&argvars[1], buf);
|
||||
# ifdef MSWIN
|
||||
if (serverSendToVim(server_name, keys, &r, &w, expr, timeout, TRUE) < 0)
|
||||
# else
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_SOCKET)
|
||||
if (socket_server_send(server_name, keys, &r, &client, expr,
|
||||
timeout * 1000, TRUE) < 0)
|
||||
goto fail;
|
||||
# endif
|
||||
# ifdef FEAT_X11
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_MSWIN
|
||||
&& serverSendToVim(server_name, keys, &r, &w, expr,
|
||||
timeout, TRUE) < 0)
|
||||
ret = FAIL;
|
||||
# endif
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_SOCKET
|
||||
&& socketserver_send(server_name, keys, &r, expr,
|
||||
timeout * 1000, true, NULL) < 0)
|
||||
ret = FAIL;
|
||||
# endif
|
||||
# ifdef FEAT_X11
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_X11)
|
||||
if (serverSendToVim(X_DISPLAY, server_name, keys, &r, &w, expr, timeout,
|
||||
0, TRUE) < 0)
|
||||
goto fail;
|
||||
# endif
|
||||
ret = FAIL;
|
||||
# endif
|
||||
# if !defined(MSWIN)
|
||||
if (FALSE)
|
||||
if (ret == FAIL)
|
||||
{
|
||||
fail:
|
||||
# else
|
||||
{
|
||||
# endif
|
||||
if (r != NULL)
|
||||
{
|
||||
emsg((char *)r); // sending worked but evaluation failed
|
||||
vim_free(r);
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
vim_free(client);
|
||||
# endif
|
||||
}
|
||||
else
|
||||
semsg(_(e_unable_to_send_to_str), server_name);
|
||||
@@ -939,40 +925,42 @@ fail:
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
dictitem_T v;
|
||||
# if defined(FEAT_SOCKETSERVER)
|
||||
struct sockaddr_un addr;
|
||||
char_u str[sizeof(addr.sun_path)];
|
||||
# else
|
||||
char_u str[30];
|
||||
# if defined(MSWIN) || defined(FEAT_X11)
|
||||
char_u sbuf[30];
|
||||
# endif
|
||||
char_u *str = NULL;
|
||||
char_u *idvar;
|
||||
|
||||
idvar = tv_get_string_chk(&argvars[2]);
|
||||
if (idvar != NULL && *idvar != NUL)
|
||||
{
|
||||
str[0] = NUL;
|
||||
# ifdef MSWIN
|
||||
sprintf((char *)str, PRINTF_HEX_LONG_U, (long_u)w);
|
||||
# else
|
||||
# ifdef FEAT_X11
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_X11)
|
||||
sprintf((char *)str, PRINTF_HEX_LONG_U, (long_u)w);
|
||||
# endif
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_SOCKET)
|
||||
vim_snprintf((char *)str, sizeof(addr.sun_path),
|
||||
"%s", client);
|
||||
# endif
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_MSWIN)
|
||||
{
|
||||
sprintf((char *)sbuf, PRINTF_HEX_LONG_U, (long_u)w);
|
||||
str = sbuf;
|
||||
}
|
||||
# endif
|
||||
# ifdef FEAT_X11
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_X11)
|
||||
{
|
||||
sprintf((char *)sbuf, PRINTF_HEX_LONG_U, (long_u)w);
|
||||
str = sbuf;
|
||||
}
|
||||
# endif
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_SOCKET)
|
||||
str = server_name;
|
||||
# endif
|
||||
if (str == NULL)
|
||||
str = (char_u *)"";
|
||||
|
||||
v.di_tv.v_type = VAR_STRING;
|
||||
v.di_tv.vval.v_string = vim_strsave(str);
|
||||
set_var(idvar, &v.di_tv, FALSE);
|
||||
vim_free(v.di_tv.vval.v_string);
|
||||
}
|
||||
}
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
vim_free(client);
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1054,20 +1042,23 @@ f_remote_peek(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
if (serverid == NULL)
|
||||
return; // type error; errmsg already given
|
||||
# ifdef MSWIN
|
||||
sscanf((const char *)serverid, SCANF_HEX_LONG_U, &n);
|
||||
if (n == 0)
|
||||
rettv->vval.v_number = -1;
|
||||
else
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_MSWIN)
|
||||
{
|
||||
s = serverGetReply((HWND)n, FALSE, FALSE, FALSE, 0);
|
||||
rettv->vval.v_number = (s != NULL);
|
||||
sscanf((const char *)serverid, SCANF_HEX_LONG_U, &n);
|
||||
if (n == 0)
|
||||
rettv->vval.v_number = -1;
|
||||
else
|
||||
{
|
||||
s = serverGetReply((HWND)n, FALSE, FALSE, FALSE, 0);
|
||||
rettv->vval.v_number = (s != NULL);
|
||||
}
|
||||
}
|
||||
# else
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
# endif
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_SOCKET)
|
||||
rettv->vval.v_number = socket_server_peek_reply(serverid, &s);
|
||||
# endif
|
||||
# ifdef FEAT_X11
|
||||
rettv->vval.v_number = socketserver_peek_reply(serverid, &s);
|
||||
# endif
|
||||
# ifdef FEAT_X11
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_X11)
|
||||
{
|
||||
if (check_connection() == FAIL)
|
||||
@@ -1076,7 +1067,6 @@ f_remote_peek(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
rettv->vval.v_number = serverPeekReply(X_DISPLAY,
|
||||
serverStrToWin(serverid), &s);
|
||||
}
|
||||
# endif
|
||||
# endif
|
||||
|
||||
if (argvars[1].v_type != VAR_UNKNOWN && rettv->vval.v_number > 0)
|
||||
@@ -1121,24 +1111,27 @@ f_remote_read(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
timeout = tv_get_number(&argvars[1]);
|
||||
|
||||
# ifdef MSWIN
|
||||
sscanf((char *)serverid, SCANF_HEX_LONG_U, &n);
|
||||
if (n != 0)
|
||||
r = serverGetReply((HWND)n, FALSE, TRUE, TRUE, timeout);
|
||||
if (r == NULL)
|
||||
emsg(_(e_unable_to_read_server_reply));
|
||||
# else
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_MSWIN)
|
||||
{
|
||||
sscanf((char *)serverid, SCANF_HEX_LONG_U, &n);
|
||||
if (n != 0)
|
||||
r = serverGetReply((HWND)n, FALSE, TRUE, TRUE, timeout);
|
||||
if (r == NULL)
|
||||
emsg(_(e_unable_to_read_server_reply));
|
||||
}
|
||||
# endif
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_SOCKET &&
|
||||
socket_server_read_reply(serverid, &r, timeout * 1000) == FAIL)
|
||||
socketserver_read_reply(serverid, &r, timeout * 1000, false)
|
||||
== FAIL)
|
||||
emsg(_(e_unable_to_read_server_reply));
|
||||
# endif
|
||||
# ifdef FEAT_X11
|
||||
# endif
|
||||
# ifdef FEAT_X11
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_X11 &&
|
||||
(check_connection() == FAIL
|
||||
|| serverReadReply(X_DISPLAY, serverStrToWin(serverid),
|
||||
&r, FALSE, timeout) < 0))
|
||||
emsg(_(e_unable_to_read_server_reply));
|
||||
# endif
|
||||
# endif
|
||||
}
|
||||
# endif
|
||||
@@ -1184,17 +1177,17 @@ f_remote_startserver(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
|
||||
|
||||
char_u *server = tv_get_string_chk(&argvars[0]);
|
||||
# ifdef MSWIN
|
||||
serverSetName(server);
|
||||
# else
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_MSWIN)
|
||||
serverSetName(server);
|
||||
# endif
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_SOCKET)
|
||||
socket_server_init(server);
|
||||
# endif
|
||||
# ifdef FEAT_X11
|
||||
socketserver_start(server, true);
|
||||
# endif
|
||||
# ifdef FEAT_X11
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_X11 &&
|
||||
check_connection() == OK)
|
||||
serverRegisterName(X_DISPLAY, server);
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# else
|
||||
@@ -1209,6 +1202,7 @@ f_server2client(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
char_u buf[NUMBUFLEN];
|
||||
char_u *server;
|
||||
char_u *reply;
|
||||
int ret = OK;
|
||||
|
||||
rettv->vval.v_number = -1;
|
||||
if (check_restricted() || check_secure())
|
||||
@@ -1226,28 +1220,22 @@ f_server2client(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_SOCKET &&
|
||||
socket_server_send_reply(server, reply) == FAIL)
|
||||
goto fail;
|
||||
socketserver_send_reply(server, reply) == FAIL)
|
||||
ret = FAIL;
|
||||
# endif
|
||||
|
||||
# ifdef FEAT_X11
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_X11 &&
|
||||
check_connection() == FAIL)
|
||||
return;
|
||||
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_X11 &&
|
||||
serverSendReply(server, reply) < 0)
|
||||
ret = FAIL;
|
||||
# endif
|
||||
# ifdef MSWIN
|
||||
if (serverSendReply(server, reply) < 0)
|
||||
# endif
|
||||
# if defined(FEAT_SOCKETSERVER) && !defined(FEAT_X11) && !defined(MSWIN)
|
||||
if (FALSE)
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_MSWIN
|
||||
&& serverSendReply(server, reply) < 0)
|
||||
ret = FAIL;
|
||||
# endif
|
||||
|
||||
if (ret == FAIL)
|
||||
{
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
fail:
|
||||
# endif
|
||||
emsg(_(e_unable_to_send_to_client));
|
||||
return;
|
||||
}
|
||||
@@ -1264,20 +1252,24 @@ f_serverlist(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
|
||||
# ifdef FEAT_CLIENTSERVER
|
||||
# ifdef MSWIN
|
||||
r = serverGetVimNames();
|
||||
# else
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_MSWIN)
|
||||
r = serverGetVimNames();
|
||||
# endif
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_SOCKET)
|
||||
r = socket_server_list_sockets();
|
||||
# ifdef MSWIN
|
||||
r = vim_strsave((char_u *)"");
|
||||
# else
|
||||
r = socketserver_list();
|
||||
# endif
|
||||
# ifdef FEAT_X11
|
||||
# endif
|
||||
# ifdef FEAT_X11
|
||||
if (clientserver_method == CLIENTSERVER_METHOD_X11)
|
||||
{
|
||||
make_connection();
|
||||
if (X_DISPLAY != NULL)
|
||||
r = serverGetVimNames(X_DISPLAY);
|
||||
}
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
rettv->v_type = VAR_STRING;
|
||||
|
||||
@@ -2363,22 +2363,6 @@ if test "$enable_autoservername" = "yes"; then
|
||||
AC_DEFINE(FEAT_AUTOSERVERNAME)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(--enable-socketserver argument)
|
||||
AC_ARG_ENABLE(socketserver,
|
||||
[ --enable-socketserver Use sockets for clientserver communication.],
|
||||
[enable_socketserver=$enableval],
|
||||
AS_IF([test "x$features" = xtiny],
|
||||
[enable_socketserver=no_msg
|
||||
AC_MSG_RESULT([cannot use socketserver with tiny features])],
|
||||
[enable_socketserver=yes]))
|
||||
|
||||
if test "$enable_socketserver" = "yes"; then
|
||||
AC_DEFINE(WANT_SOCKETSERVER)
|
||||
AC_MSG_RESULT([yes])
|
||||
elif test "$enable_socketserver" = "no"; then
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(--enable-multibyte argument)
|
||||
AC_ARG_ENABLE(multibyte,
|
||||
[ --enable-multibyte Include multibyte editing support.], ,
|
||||
|
||||
+5
-7
@@ -1139,7 +1139,7 @@ EXTERN char e_cant_read_postscript_resource_file_str[]
|
||||
INIT(= N_("E457: Can't read PostScript resource file \"%s\""));
|
||||
#endif
|
||||
// E458 unused
|
||||
#if defined(UNIX) || defined(FEAT_SESSION)
|
||||
#if defined(UNIX) || defined(FEAT_SESSION) || defined(FEAT_SOCKETSERVER)
|
||||
EXTERN char e_cannot_go_back_to_previous_directory[]
|
||||
INIT(= N_("E459: Cannot go back to previous directory"));
|
||||
#endif
|
||||
@@ -3777,16 +3777,14 @@ EXTERN char e_diff_anchors_with_hidden_windows[]
|
||||
INIT(= N_("E1562: Diff anchors cannot be used with hidden diff windows"));
|
||||
#endif
|
||||
#ifdef FEAT_SOCKETSERVER
|
||||
EXTERN char e_socket_path_too_big[]
|
||||
INIT(= N_("E1563: Socket path is too big"));
|
||||
EXTERN char e_socket_name_no_slashes[]
|
||||
INIT(= N_("E1564: Socket name cannot have slashes in it without being a path"));
|
||||
INIT(= N_("E1564: Socket name '%s' cannot have slashes in it without being a path"));
|
||||
EXTERN char e_socket_server_not_online[]
|
||||
INIT(= N_("E1565: Socket server is not online, call remote_startserver() first"));
|
||||
EXTERN char e_socket_server_failed_connecting[]
|
||||
INIT(= N_("E1566: Failed connecting to socket %s: %s"));
|
||||
EXTERN char e_socket_server_unavailable[]
|
||||
INIT(= N_("E1567: Cannot start socket server, socket path is unavailable"));
|
||||
INIT(= N_("E1566: Failed connecting to socket '%s'"));
|
||||
EXTERN char e_socket_server_version_mismatch[]
|
||||
INIT(= N_("E1567: Socket server protocol version mismatch, check what Vim version you are using"));
|
||||
#endif
|
||||
EXTERN char e_osc_response_timed_out[]
|
||||
INIT(= N_("E1568: OSC command response timed out: %.*s"));
|
||||
|
||||
+12
-10
@@ -953,9 +953,16 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
* +socketserver Use UNIX domain sockets for clientserver communication
|
||||
* The +channel feature requires +eval.
|
||||
*/
|
||||
#if defined(UNIX) && defined(WANT_SOCKETSERVER)
|
||||
#if !defined(FEAT_EVAL) && defined(FEAT_JOB_CHANNEL)
|
||||
# undef FEAT_JOB_CHANNEL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* +socketserver Use channels for clientserver communication
|
||||
*/
|
||||
#if (defined(UNIX) || defined(MSWIN)) && defined(FEAT_JOB_CHANNEL)
|
||||
# define FEAT_SOCKETSERVER
|
||||
#endif
|
||||
|
||||
@@ -966,6 +973,9 @@
|
||||
#if (defined(MSWIN) || defined(FEAT_XCLIPBOARD) || defined(FEAT_SOCKETSERVER)) \
|
||||
&& defined(FEAT_EVAL)
|
||||
# define FEAT_CLIENTSERVER
|
||||
# if defined(FEAT_SOCKETSERVER) && (defined(FEAT_XCLIPBOARD) || defined(MSWIN))
|
||||
# define FEAT_CLIENTSERVER_BACKENDS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -1053,14 +1063,6 @@
|
||||
* +tgetent
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* The +channel feature requires +eval.
|
||||
*/
|
||||
#if !defined(FEAT_EVAL) && defined(FEAT_JOB_CHANNEL)
|
||||
# undef FEAT_JOB_CHANNEL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The Netbeans feature requires +eval and +job_channel
|
||||
*/
|
||||
|
||||
@@ -208,6 +208,9 @@ garbage_collect(int testing)
|
||||
#ifdef FEAT_NETBEANS_INTG
|
||||
abort = abort || set_ref_in_nb_channel(copyID);
|
||||
#endif
|
||||
#ifdef FEAT_SOCKETSERVER
|
||||
abort = abort || set_ref_in_socketserver_channel(copyID);
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_TIMERS
|
||||
abort = abort || set_ref_in_timer(copyID);
|
||||
|
||||
@@ -2650,6 +2650,9 @@ parse_queued_messages(void)
|
||||
// Process the queued netbeans messages.
|
||||
netbeans_parse_messages();
|
||||
# endif
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
socketserver_parse_messages();
|
||||
# endif
|
||||
# ifdef FEAT_JOB_CHANNEL
|
||||
// Write any buffer lines still to be written.
|
||||
channel_write_any_lines();
|
||||
|
||||
+11
-8
@@ -2122,25 +2122,28 @@ EXTERN int wayland_no_connect INIT(= FALSE);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(FEAT_CLIENTSERVER) && !defined(MSWIN)
|
||||
#if defined(FEAT_CLIENTSERVER)
|
||||
|
||||
// Backend for clientserver functionality
|
||||
typedef enum {
|
||||
CLIENTSERVER_METHOD_NONE,
|
||||
# ifdef FEAT_X11
|
||||
CLIENTSERVER_METHOD_X11,
|
||||
# endif
|
||||
# ifdef MSWIN
|
||||
CLIENTSERVER_METHOD_MSWIN,
|
||||
# endif
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
CLIENTSERVER_METHOD_SOCKET
|
||||
# endif
|
||||
} clientserver_method_T;
|
||||
|
||||
// Default to X11 if compiled with support for it, else use socket server.
|
||||
# if defined(FEAT_X11) && defined(FEAT_SOCKETSERVER)
|
||||
EXTERN clientserver_method_T clientserver_method
|
||||
# else
|
||||
// Since we aren't going to be changing clientserver_method, make it constant to
|
||||
// allow compiler optimizations.
|
||||
EXTERN const clientserver_method_T clientserver_method
|
||||
# endif
|
||||
|
||||
# ifdef FEAT_X11
|
||||
INIT(= CLIENTSERVER_METHOD_X11);
|
||||
# elif defined(MSWIN)
|
||||
INIT(= CLIENTSERVER_METHOD_MSWIN);
|
||||
# elif defined(FEAT_SOCKETSERVER)
|
||||
INIT(= CLIENTSERVER_METHOD_SOCKET);
|
||||
# else
|
||||
|
||||
@@ -158,12 +158,6 @@ gui_start(char_u *arg UNUSED)
|
||||
choose_clipmethod();
|
||||
#endif
|
||||
|
||||
#if defined(FEAT_SOCKETSERVER) && defined(FEAT_GUI_GTK)
|
||||
// Install socket server listening socket if we are running it
|
||||
if (socket_server_valid())
|
||||
gui_gtk_init_socket_server();
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_GUI_MSWIN
|
||||
// Enable fullscreen mode
|
||||
if (vim_strchr(p_go, GO_FULLSCREEN) != NULL)
|
||||
|
||||
@@ -80,13 +80,6 @@ extern void bonobo_dock_item_set_behavior(BonoboDockItem *dock_item, BonoboDockI
|
||||
# include <X11/Sunkeysym.h>
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_SOCKETSERVER
|
||||
# include <glib-unix.h>
|
||||
|
||||
// Used to track the source for the listening socket
|
||||
static uint socket_server_source_id = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Easy-to-use macro for multihead support.
|
||||
*/
|
||||
@@ -2690,54 +2683,6 @@ global_event_filter(GdkXEvent *xev,
|
||||
}
|
||||
#endif // !USE_GNOME_SESSION
|
||||
|
||||
#if defined(FEAT_SOCKETSERVER)
|
||||
|
||||
/*
|
||||
* Callback for new events from the socket server listening socket
|
||||
*/
|
||||
static int
|
||||
socket_server_poll_in(int fd UNUSED, GIOCondition cond, void *user_data UNUSED)
|
||||
{
|
||||
if (cond & G_IO_IN)
|
||||
socket_server_accept_client();
|
||||
else if (cond & (G_IO_ERR | G_IO_HUP))
|
||||
{
|
||||
socket_server_uninit();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize socket server for use in the GUI (does not actually initialize the
|
||||
* socket server, only attaches a source).
|
||||
*/
|
||||
void
|
||||
gui_gtk_init_socket_server(void)
|
||||
{
|
||||
if (socket_server_source_id > 0)
|
||||
return;
|
||||
// Register source for file descriptor to global default context
|
||||
socket_server_source_id = g_unix_fd_add(socket_server_get_fd(),
|
||||
G_IO_IN | G_IO_ERR | G_IO_HUP, socket_server_poll_in, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the source for the socket server listening socket.
|
||||
*/
|
||||
void
|
||||
gui_gtk_uninit_socket_server(void)
|
||||
{
|
||||
if (socket_server_source_id > 0)
|
||||
{
|
||||
g_source_remove(socket_server_source_id);
|
||||
socket_server_source_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static GdkPixbuf *
|
||||
pixbuf_new_from_png_data(const unsigned char *data, unsigned int len)
|
||||
{
|
||||
|
||||
@@ -51,6 +51,8 @@ json_encode(typval_T *val, int options)
|
||||
// Store bytes in the growarray.
|
||||
ga_init2(&ga, 1, 4000);
|
||||
json_encode_gap(&ga, val, options);
|
||||
if (options & JSON_NL)
|
||||
ga_append(&ga, NL);
|
||||
ga_append(&ga, NUL);
|
||||
return ga.ga_data;
|
||||
}
|
||||
|
||||
+14
-5
@@ -1844,6 +1844,9 @@ getout(int exitval)
|
||||
#ifdef FEAT_NETBEANS_INTG
|
||||
netbeans_end();
|
||||
#endif
|
||||
#ifdef FEAT_SOCKETSERVER
|
||||
socketserver_stop();
|
||||
#endif
|
||||
#ifdef FEAT_CSCOPE
|
||||
cs_end();
|
||||
#endif
|
||||
@@ -1910,7 +1913,7 @@ early_arg_scan(mparm_T *parmp UNUSED)
|
||||
gui.dofork = false;
|
||||
# endif
|
||||
}
|
||||
# if defined(FEAT_X11) && defined(FEAT_SOCKETSERVER)
|
||||
# ifdef FEAT_CLIENTSERVER_BACKENDS
|
||||
else if (STRNICMP(argv[i], "--clientserver", 14) == 0)
|
||||
{
|
||||
char_u *arg;
|
||||
@@ -1920,8 +1923,14 @@ early_arg_scan(mparm_T *parmp UNUSED)
|
||||
|
||||
if (STRICMP(arg, "socket") == 0)
|
||||
clientserver_method = CLIENTSERVER_METHOD_SOCKET;
|
||||
# ifdef FEAT_X11
|
||||
else if (STRICMP(arg, "x11") == 0)
|
||||
clientserver_method = CLIENTSERVER_METHOD_X11;
|
||||
# endif
|
||||
# ifdef MSWIN
|
||||
else if (STRICMP(arg, "mswin") == 0)
|
||||
clientserver_method = CLIENTSERVER_METHOD_MSWIN;
|
||||
# endif
|
||||
else
|
||||
mainerr(ME_UNKNOWN_OPTION, arg);
|
||||
}
|
||||
@@ -2247,9 +2256,9 @@ command_line_scan(mparm_T *parmp)
|
||||
; // already processed -- no arg
|
||||
else if (STRNICMP(argv[0] + argv_idx, "servername", 10) == 0
|
||||
|| STRNICMP(argv[0] + argv_idx, "serversend", 10) == 0
|
||||
# if defined(FEAT_X11) && defined(FEAT_SOCKETSERVER)
|
||||
// Don't put this under FEAT_CLIENTSERVER_BACKENDS, just
|
||||
// let it be ignored. Makes tests less complicated
|
||||
|| STRNICMP(argv[0] + argv_idx, "clientserver", 12) == 0
|
||||
# endif
|
||||
)
|
||||
{
|
||||
// already processed -- snatch the following arg
|
||||
@@ -3747,8 +3756,8 @@ usage(void)
|
||||
main_msg(_("-Y\t\t\tDo not connect to Wayland compositor"));
|
||||
# endif
|
||||
# ifdef FEAT_CLIENTSERVER
|
||||
# if defined(FEAT_X11) && defined(FEAT_SOCKETSERVER)
|
||||
main_msg(_("--clientserver <socket|x11> Backend for clientserver communication"));
|
||||
# ifdef FEAT_CLIENTSERVER_BACKENDS
|
||||
main_msg(_("--clientserver <socket|x11|mswin> Backend for clientserver communication"));
|
||||
# endif
|
||||
main_msg(_("--remote <files>\tEdit <files> in a Vim server if possible"));
|
||||
main_msg(_("--remote-silent <files> Same, don't complain if there is no server"));
|
||||
|
||||
+1
-1734
File diff suppressed because it is too large
Load Diff
Generated
+12
-14
@@ -254,9 +254,6 @@ msgstr ""
|
||||
msgid "%d of %d edited"
|
||||
msgstr ""
|
||||
|
||||
msgid "Socket server not online:Send expression failed"
|
||||
msgstr ""
|
||||
|
||||
msgid "No display: Send expression failed.\n"
|
||||
msgstr ""
|
||||
|
||||
@@ -1722,7 +1719,8 @@ msgstr ""
|
||||
msgid "-Y\t\t\tDo not connect to Wayland compositor"
|
||||
msgstr ""
|
||||
|
||||
msgid "--clientserver <socket|x11> Backend for clientserver communication"
|
||||
msgid ""
|
||||
"--clientserver <socket|x11|mswin> Backend for clientserver communication"
|
||||
msgstr ""
|
||||
|
||||
msgid "--remote <files>\tEdit <files> in a Vim server if possible"
|
||||
@@ -2531,10 +2529,6 @@ msgstr ""
|
||||
msgid "XSMP SmcOpenConnection failed: %s"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Failed creating socket directory: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "At line"
|
||||
msgstr ""
|
||||
|
||||
@@ -2806,6 +2800,10 @@ msgstr ""
|
||||
msgid " (not supported)"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Failed creating socket directory: %s"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\""
|
||||
msgstr ""
|
||||
@@ -8834,20 +8832,20 @@ msgstr ""
|
||||
msgid "E1562: Diff anchors cannot be used with hidden diff windows"
|
||||
msgstr ""
|
||||
|
||||
msgid "E1563: Socket path is too big"
|
||||
msgstr ""
|
||||
|
||||
msgid "E1564: Socket name cannot have slashes in it without being a path"
|
||||
#, c-format
|
||||
msgid "E1564: Socket name '%s' cannot have slashes in it without being a path"
|
||||
msgstr ""
|
||||
|
||||
msgid "E1565: Socket server is not online, call remote_startserver() first"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "E1566: Failed connecting to socket %s: %s"
|
||||
msgid "E1566: Failed connecting to socket '%s'"
|
||||
msgstr ""
|
||||
|
||||
msgid "E1567: Cannot start socket server, socket path is unavailable"
|
||||
msgid ""
|
||||
"E1567: Socket server protocol version mismatch, check what Vim version you "
|
||||
"are using"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
|
||||
@@ -277,6 +277,9 @@ void mbyte_im_set_active(int active_arg);
|
||||
# include "job.pro"
|
||||
# include "channel.pro"
|
||||
# endif
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
# include "socketserver.pro"
|
||||
# endif
|
||||
|
||||
# ifdef FEAT_EVAL
|
||||
// Not generated automatically so that we can add an extra attribute.
|
||||
|
||||
@@ -7,15 +7,18 @@ int channel_unref(channel_T *channel);
|
||||
int free_unused_channels_contents(int copyID, int mask);
|
||||
void free_unused_channels(int copyID, int mask);
|
||||
void channel_gui_register_all(void);
|
||||
channel_T *channel_open_unix(const char *path, void (*nb_close_cb)(void));
|
||||
channel_T *channel_open(const char *hostname, int port, int waittime, void (*nb_close_cb)(void));
|
||||
int channel_parse_socketserver_address(char_u *address, int *port, char_u **unix_path, bool quiet);
|
||||
channel_T *channel_listen_func(typval_T *argvars);
|
||||
channel_T *channel_listen(int port_in, void (*nb_close_cb)(void));
|
||||
channel_T *channel_listen_unix(char *path, void (*nb_close_cb)(void));
|
||||
channel_T *channel_listen_unix(char *path, void (*nb_close_cb)(void), bool replace);
|
||||
void ch_close_part(channel_T *channel, ch_part_T part);
|
||||
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, jobopt_T *options);
|
||||
void channel_write_in(channel_T *channel);
|
||||
void channel_buffer_free(buf_T *buf);
|
||||
void channel_write_input(channel_T *channel);
|
||||
void channel_write_any_lines(void);
|
||||
void channel_write_new_lines(buf_T *buf);
|
||||
readq_T *channel_peek(channel_T *channel, ch_part_T part);
|
||||
@@ -23,11 +26,15 @@ char_u *channel_first_nl(readq_T *node);
|
||||
char_u *channel_get(channel_T *channel, ch_part_T part, int *outlen);
|
||||
void channel_consume(channel_T *channel, ch_part_T part, int len);
|
||||
int channel_collapse(channel_T *channel, ch_part_T part, int want_nl);
|
||||
int channel_fill(js_read_T *reader);
|
||||
int channel_parse_json(channel_T *channel, ch_part_T part, bool socketserver);
|
||||
void remove_json_node(jsonq_T *head, jsonq_T *node);
|
||||
int channel_can_write_to(channel_T *channel);
|
||||
int channel_is_open(channel_T *channel);
|
||||
void channel_close(channel_T *channel, int invoke_close_cb);
|
||||
void channel_clear(channel_T *channel);
|
||||
void channel_free_all(void);
|
||||
void channel_check(channel_T *channel, ch_part_T part);
|
||||
int channel_in_blocking_wait(void);
|
||||
channel_T *get_channel_arg(typval_T *tv, int check_open, int reading, ch_part_T part);
|
||||
void channel_handle_events(int only_keep_open);
|
||||
@@ -59,4 +66,5 @@ void f_ch_sendraw(typval_T *argvars, typval_T *rettv);
|
||||
void f_ch_setoptions(typval_T *argvars, typval_T *rettv);
|
||||
void f_ch_status(typval_T *argvars, typval_T *rettv);
|
||||
char_u *channel_to_string_buf(typval_T *varp, char_u *buf);
|
||||
channel_T *channel_find(int ch_id);
|
||||
/* vim: set ft=c : */
|
||||
|
||||
@@ -8,8 +8,6 @@ void gui_mch_stop_blink(int may_call_gui_update_cursor);
|
||||
void gui_mch_start_blink(void);
|
||||
int gui_mch_early_init_check(int give_message);
|
||||
int gui_mch_init_check(void);
|
||||
void gui_gtk_init_socket_server(void);
|
||||
void gui_gtk_uninit_socket_server(void);
|
||||
void gui_mch_set_dark_theme(int dark);
|
||||
void gui_mch_show_tabline(int showit);
|
||||
int gui_mch_showing_tabline(void);
|
||||
|
||||
@@ -96,15 +96,4 @@ void stop_timeout(void);
|
||||
volatile sig_atomic_t *start_timeout(long msec);
|
||||
void delete_timer(void);
|
||||
int mch_create_anon_file(void);
|
||||
int socket_server_init(char_u *name);
|
||||
void socket_server_uninit(void);
|
||||
char_u *socket_server_list_sockets(void);
|
||||
int socket_server_accept_client(void);
|
||||
int socket_server_valid(void);
|
||||
int socket_server_send(char_u *name, char_u *str, char_u **result, char_u **receiver, int is_expr, int timeout, int silent);
|
||||
int socket_server_read_reply(char_u *client, char_u **str, int timeout);
|
||||
int socket_server_peek_reply(char_u *sender, char_u **str);
|
||||
int socket_server_send_reply(char_u *client, char_u *str);
|
||||
int socket_server_get_fd(void);
|
||||
int socket_server_waiting_accept(void);
|
||||
/* vim: set ft=c : */
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/* socketserver.c */
|
||||
int socketserver_start(char_u *name, bool quiet);
|
||||
void socketserver_stop(void);
|
||||
char_u *socketserver_list(void);
|
||||
int set_ref_in_socketserver_channel(int copyID);
|
||||
void socketserver_parse_messages(void);
|
||||
int socketserver_send(char_u *name, char_u *str, char_u **result, bool is_expr, int timeout, bool silent, channel_T **ch);
|
||||
int socketserver_send_reply(char_u *client, char_u *str);
|
||||
int socketserver_read_reply(char_u *client, char_u **str, int timeout, bool remotewait);
|
||||
int socketserver_peek_reply(char_u *sender, char_u **str);
|
||||
/* vim: set ft=c : */
|
||||
+1404
File diff suppressed because it is too large
Load Diff
@@ -2795,6 +2795,13 @@ struct channel_S {
|
||||
void (*ch_nb_close_cb)(void);
|
||||
// callback for Netbeans when channel is
|
||||
// closed
|
||||
#ifdef FEAT_SOCKETSERVER
|
||||
bool ch_socketserver; // If channel is used by socketserver
|
||||
void (*ch_ss_close_cb)(channel_T *);
|
||||
void (*ch_ss_accept_cb)(channel_T *);
|
||||
channel_T *ch_ss_next;
|
||||
channel_T *ch_ss_prev;
|
||||
#endif
|
||||
|
||||
#ifdef MSWIN
|
||||
int ch_named_pipe; // using named pipe instead of pty
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
|~+0#4040ff13#ffffff0| @73
|
||||
|~| @73
|
||||
|~| @73
|
||||
|E+0#ffffff16#e000002|1|5|6|7|:| |S|o|c|k|e|t| |s|e|r|v|e|r| |p|r|o|t|o|c|o|l| |v|e|r|s|i|o|n| |m|i|s|m|a|t|c|h|,| |c|h|e|c|k| |w|h|a|t| |V|i|m| |v|e|r|s|i|o|n| |y|o|u|
|
||||
|a|r|e| |u|s|i|n|g| +0#0000000#ffffff0@65
|
||||
|E+0#ffffff16#e000002|2|4|1|:| |U|n|a|b|l|e| |t|o| |s|e|n|d| |t|o| |c|h|a|n@1|e|l|:|2|0@2| +0#0000000#ffffff0@38
|
||||
@75
|
||||
|P+0#00e0003&|r|e|s@1| |E|N|T|E|R| |o|r| |t|y|p|e| |c|o|m@1|a|n|d| |t|o| |c|o|n|t|i|n|u|e> +0#0000000&@35
|
||||
@@ -1,5 +1,6 @@
|
||||
" Tests for the +clientserver feature.
|
||||
|
||||
source util/screendump.vim
|
||||
CheckFeature job
|
||||
|
||||
if !has('clientserver')
|
||||
@@ -10,10 +11,6 @@ CheckFeature clientserver
|
||||
|
||||
source util/shared.vim
|
||||
|
||||
" Unlike X11, we need the socket server running if we want to send commands to
|
||||
" a server via sockets.
|
||||
RunSocketServer
|
||||
|
||||
func Check_X11_Connection()
|
||||
if has('x11')
|
||||
CheckX11
|
||||
@@ -192,9 +189,9 @@ func Test_client_server()
|
||||
|
||||
" When using socket server, server id is not a number, but the path to the
|
||||
" socket.
|
||||
if has('socketserver') && !has('X11')
|
||||
call assert_fails("let x = remote_read('vim/10')", ['E573:.*vim/10'])
|
||||
call assert_fails("call server2client('a/b/c', 'xyz')", ['E573:.*a/b/c'])
|
||||
if (has('socketserver') && !has('X11') && !has('win32')) || index(v:argv, "socket") != -1
|
||||
call assert_fails("let x = remote_read('vim/10')", ['E1564:'])
|
||||
call assert_fails("call server2client('x/b/c', 'xyz')", ['E1564:'])
|
||||
else
|
||||
call assert_fails("let x = remote_read('vim10')",
|
||||
\ has('unix') ? ['E573:.*vim10'] : 'E277:')
|
||||
@@ -246,89 +243,65 @@ func Test_client_server_stopinsert()
|
||||
endtry
|
||||
endfunc
|
||||
|
||||
" Test if socket server and X11 backends can be chosen and work properly.
|
||||
func Test_client_server_x11_and_socket_server()
|
||||
CheckNotMSWindows
|
||||
CheckFeature socketserver
|
||||
CheckFeature x11
|
||||
" Test if socket server, X11, and mswin backends can be chosen and work properly.
|
||||
func Test_client_server_multiple_backends()
|
||||
CheckFeature socketserver
|
||||
|
||||
let g:test_is_flaky = 1
|
||||
let cmd = GetVimCommand()
|
||||
let g:test_is_flaky = 1
|
||||
let cmd = GetVimCommand()
|
||||
|
||||
if cmd == ''
|
||||
throw 'GetVimCommand() failed'
|
||||
endif
|
||||
call Check_X11_Connection()
|
||||
|
||||
let types = ['socket', 'x11']
|
||||
|
||||
for type in types
|
||||
let name = 'VIMTEST_' .. toupper(type)
|
||||
let actual_cmd = cmd .. ' --clientserver ' .. type
|
||||
let actual_cmd .= ' --servername ' .. name
|
||||
let job = job_start(actual_cmd, {'stoponexit': 'kill', 'out_io': 'null'})
|
||||
|
||||
call WaitForAssert({-> assert_equal("run", job_status(job))})
|
||||
call WaitForAssert({-> assert_match(name, system(cmd .. ' --clientserver ' .. type .. ' --serverlist'))})
|
||||
|
||||
call assert_match(name, system(actual_cmd .. ' --remote-expr "v:servername"'))
|
||||
|
||||
call system(actual_cmd .. " --remote-expr 'execute(\"qa!\")'")
|
||||
try
|
||||
call WaitForAssert({-> assert_equal("dead", job_status(job))})
|
||||
finally
|
||||
if job_status(job) != 'dead'
|
||||
call assert_report('Server did not exit')
|
||||
call job_stop(job, 'kill')
|
||||
endif
|
||||
endtry
|
||||
endfor
|
||||
endfunc
|
||||
|
||||
" Test if socket server works in the GUI
|
||||
func Test_client_server_socket_server_gui()
|
||||
CheckNotMSWindows
|
||||
CheckFeature socketserver
|
||||
CheckFeature gui_gtk
|
||||
|
||||
let g:test_is_flaky = 1
|
||||
let cmd = GetVimCommand()
|
||||
|
||||
if cmd == ''
|
||||
throw 'GetVimCommand() failed'
|
||||
endif
|
||||
call Check_X11_Connection()
|
||||
|
||||
let name = 'VIMTESTSOCKET'
|
||||
let cmd .= ' --clientserver socket'
|
||||
let cmd .= ' --servername ' .. name
|
||||
|
||||
let job = job_start(cmd, {'stoponexit': 'kill', 'out_io': 'null'})
|
||||
|
||||
call WaitForAssert({-> assert_equal("run", job_status(job))})
|
||||
call WaitForAssert({-> assert_match(name, system(cmd .. ' --serverlist'))})
|
||||
|
||||
call system(cmd .. " --remote-expr 'execute(\"gui\")'")
|
||||
|
||||
call assert_match('1', system(cmd .. " --remote-expr 'has(\"gui_running\")'"))
|
||||
call assert_match(name, system(cmd .. ' --remote-expr "v:servername"'))
|
||||
|
||||
call system(cmd .. " --remote-expr 'execute(\"qa!\")'")
|
||||
try
|
||||
call WaitForAssert({-> assert_equal("dead", job_status(job))})
|
||||
finally
|
||||
if job_status(job) != 'dead'
|
||||
call assert_report('Server did not exit')
|
||||
call job_stop(job, 'kill')
|
||||
if cmd == ''
|
||||
throw 'GetVimCommand() failed'
|
||||
endif
|
||||
endtry
|
||||
endfunc
|
||||
call Check_X11_Connection()
|
||||
|
||||
let types = [
|
||||
\ ['socket', "channel:2000"],
|
||||
\ ['x11', "TEST"],
|
||||
\ ['mswin', "TEST"],
|
||||
\ ]
|
||||
|
||||
for [type, expected] in types
|
||||
if (type == 'x11' && (!has('x11') || !empty($WAYLAND_DISPLAY) || empty($DISPLAY))
|
||||
\ || (type == 'mswin' && !has('win32')))
|
||||
continue
|
||||
endif
|
||||
if has('win32') && has('gui_running')
|
||||
" Windows gVim --remote-expr shows a dialog window, which blocks tests
|
||||
" from running. Using --gui-dialog-file does not seem to work either.
|
||||
continue
|
||||
endif
|
||||
|
||||
let actual_cmd = cmd .. ' --clientserver ' .. type
|
||||
let actual_cmd ..= ' --servername ' .. expected
|
||||
let job = job_start(actual_cmd, {'stoponexit': 'kill', 'out_io': 'null'})
|
||||
|
||||
call WaitForAssert({-> assert_equal("run", job_status(job))})
|
||||
call assert_match(expected, system(actual_cmd .. ' --remote-expr "v:servername"'))
|
||||
|
||||
" On Windows using --remote-expr causes E282, possibly due to some shell
|
||||
" escaping quirk? When gtk gui is running, using system() seems to cause a
|
||||
" deadlock when using the x11 backend only... don't use it for now...
|
||||
if has('win32') || has('gui_running')
|
||||
call job_stop(job, 'kill')
|
||||
else
|
||||
call system(actual_cmd .. " --remote-expr 'execute(\"qa!\")'")
|
||||
endif
|
||||
try
|
||||
call WaitForAssert({-> assert_equal("dead", job_status(job))})
|
||||
finally
|
||||
if job_status(job) != 'dead'
|
||||
call assert_report('Server did not exit')
|
||||
call job_stop(job, 'kill')
|
||||
endif
|
||||
endtry
|
||||
endfor
|
||||
endfunc
|
||||
|
||||
" Test if custom paths work for socketserver
|
||||
func Test_client_socket_server_custom_path()
|
||||
CheckNotMSWindows
|
||||
func Test_client_server_socketserver_custom_path()
|
||||
CheckFeature socketserver
|
||||
CheckNotFeature x11
|
||||
CheckNotMSWindows
|
||||
|
||||
let g:test_is_flaky = 1
|
||||
let cmd = GetVimCommand()
|
||||
@@ -342,7 +315,7 @@ func Test_client_socket_server_custom_path()
|
||||
let paths = ['./' .. name, '../testdir/' .. name, getcwd(-1) .. '/' .. name]
|
||||
|
||||
for path in paths
|
||||
let actual = cmd .. ' --servername ' .. path
|
||||
let actual = cmd .. ' --clientserver socket --servername ' .. path
|
||||
|
||||
let job = job_start(actual, {'stoponexit': 'kill', 'out_io': 'null'})
|
||||
|
||||
@@ -361,6 +334,170 @@ func Test_client_socket_server_custom_path()
|
||||
endfor
|
||||
endfunc
|
||||
|
||||
" Test if "channel:" prefix works correctly to use channel address for
|
||||
" socketserver.
|
||||
func Test_client_server_socketserver_address()
|
||||
CheckFeature socketserver
|
||||
|
||||
let g:test_is_flaky = 1
|
||||
let cmd = GetVimCommand()
|
||||
|
||||
if cmd == ''
|
||||
throw 'GetVimCommand() failed'
|
||||
endif
|
||||
|
||||
let actual = cmd .. ' --clientserver socket --servername channel:2000'
|
||||
|
||||
let job = job_start(actual, {'stoponexit': 'kill', 'out_io': 'null'})
|
||||
|
||||
call WaitForAssert({-> assert_equal("run", job_status(job))})
|
||||
|
||||
if !has('win32') || !has('gui_running')
|
||||
" Does not work with gVim on Windows because it shows an OK dialog box which
|
||||
" blocks tests from running
|
||||
call assert_match('channel:2000', system(actual .. ' --remote-expr "v:servername"'))
|
||||
endif
|
||||
|
||||
if has('win32')
|
||||
call job_stop(job, 'kill')
|
||||
else
|
||||
call system(actual .. " --remote-expr 'execute(\"qa!\")'")
|
||||
endif
|
||||
try
|
||||
call WaitForAssert({-> assert_equal("dead", job_status(job))})
|
||||
finally
|
||||
if job_status(job) != 'dead'
|
||||
call assert_report('Server did not exit')
|
||||
call job_stop(job, 'kill')
|
||||
endif
|
||||
endtry
|
||||
endfunc
|
||||
|
||||
" Test if --remote-wait works properly with multiple files
|
||||
func Test_client_server_multiple_remote_wait()
|
||||
CheckRunVimInTerminal
|
||||
|
||||
call Check_X11_Connection()
|
||||
|
||||
let buf = RunVimInTerminal('--servername TEST', {'rows': 8})
|
||||
call TermWait(buf)
|
||||
|
||||
call writefile(["1"], 'XRemoteOne', 'D')
|
||||
call writefile(["2"], 'XRemoteTwo', 'D')
|
||||
|
||||
let cmd = GetVimCommand()
|
||||
|
||||
if cmd == ''
|
||||
throw 'GetVimCommand() failed'
|
||||
endif
|
||||
|
||||
let actual = cmd .. ' -n --servername TEST --remote-wait ./XRemoteOne ./XRemoteTwo'
|
||||
let job = job_start(actual, {'stoponexit': 'kill', 'out_io': 'null'})
|
||||
|
||||
sleep 500m " Wait for server to receive request
|
||||
call assert_equal("run", job_status(job))
|
||||
|
||||
call term_sendkeys(buf, "\<Esc>:next\<CR>")
|
||||
call TermWait(buf)
|
||||
call assert_equal("run", job_status(job))
|
||||
|
||||
call term_sendkeys(buf, "\<Esc>:q!\<CR>") " Don't use qa! because we only want to quit one file
|
||||
call WaitForAssert({-> assert_equal("dead", job_status(job))})
|
||||
endfunc
|
||||
|
||||
" Check if socket is removed even if Vim changes directory
|
||||
func Test_client_server_socketserver_chdir()
|
||||
CheckFeature socketserver
|
||||
CheckRunVimInTerminal
|
||||
CheckNotMSWindows
|
||||
|
||||
let buf = RunVimInTerminal('--clientserver socket --servername ./TEST',
|
||||
\ {'rows': 8})
|
||||
call TermWait(buf)
|
||||
|
||||
call term_sendkeys(buf, "\<Esc>:cd ../\<CR>")
|
||||
call StopVimInTerminal(buf)
|
||||
|
||||
call assert_equal("", glob("./TEST"))
|
||||
endfunc
|
||||
|
||||
func DummyServerCallback(ch, addr)
|
||||
let msg = json_encode(#{type: "ver"}) .. "\n"
|
||||
call ch_sendraw(a:ch, msg)
|
||||
endfunc
|
||||
|
||||
" Test if commands with different version are ignored and handled properly.
|
||||
func Test_client_server_socketserver_version_mismatch()
|
||||
CheckFeature socketserver
|
||||
CheckRunVimInTerminal
|
||||
CheckScreendump
|
||||
|
||||
let cmd = GetVimCommand()
|
||||
|
||||
if cmd == ''
|
||||
throw 'GetVimCommand() failed'
|
||||
endif
|
||||
|
||||
let buf = RunVimInTerminal('--clientserver socket --servername
|
||||
\ channel:2000', {'rows': 8})
|
||||
call TermWait(buf)
|
||||
|
||||
let ch = ch_open('localhost:2000', #{mode: 'nl'})
|
||||
let msg = json_encode(#{
|
||||
\ type: "expr",
|
||||
\ str: "v:servername",
|
||||
\ version: 999999999
|
||||
\ }) .. "\n"
|
||||
|
||||
call ch_sendraw(ch, msg)
|
||||
let resp = ch_readraw(ch)
|
||||
|
||||
call assert_equal(#{type: "ver"}, json_decode(resp))
|
||||
|
||||
call StopVimInTerminal(buf)
|
||||
|
||||
let ch = ch_listen("2000", #{
|
||||
\ mode: 'nl',
|
||||
\ callback: function('DummyServerCallback')
|
||||
\ })
|
||||
|
||||
let buf = RunVimInTerminal('--clientserver socket --servername channel:3000', {'rows': 8})
|
||||
call TermWait(buf)
|
||||
|
||||
call term_sendkeys(buf, "\<Esc>:echo remote_expr('channel:2000', 'v:servername', '', 1)\<CR>")
|
||||
call TermWait(buf)
|
||||
|
||||
call VerifyScreenDump(buf, 'Test_clientserver_1', #{wait: 3000})
|
||||
|
||||
call StopVimInTerminal(buf)
|
||||
endfunc
|
||||
|
||||
" Test if invalid messages do not crash Vim socketserver.
|
||||
func Test_clientserver_socketserver_invalid_msg()
|
||||
CheckFeature socketserver
|
||||
CheckRunVimInTerminal
|
||||
|
||||
let cmd = GetVimCommand()
|
||||
|
||||
if cmd == ''
|
||||
throw 'GetVimCommand() failed'
|
||||
endif
|
||||
|
||||
let buf = RunVimInTerminal('--clientserver socket --servername
|
||||
\ channel:3000', {'rows': 8})
|
||||
call TermWait(buf)
|
||||
|
||||
let ch = ch_open('localhost:3000', #{mode: 'nl'})
|
||||
|
||||
call ch_sendraw(ch, "wjdaljdsjalsj\n")
|
||||
call ch_sendraw(ch, "{\"type\": \"unknown\"}\n")
|
||||
|
||||
call assert_match("channel:3000", system(cmd .. " --clientserver socket --servername channel:3000 --remote-expr 'v:servername'"))
|
||||
call assert_equal("running", term_getstatus(buf))
|
||||
|
||||
call StopVimInTerminal(buf)
|
||||
endfunc
|
||||
|
||||
" Uncomment this line to get a debugging log
|
||||
" call ch_logfile('channellog', 'w')
|
||||
|
||||
|
||||
@@ -16,18 +16,6 @@ func Verify_remote_feature_works()
|
||||
let buf = RunVimInTerminal('--servername XVIMTEST', {'rows': 8})
|
||||
call TermWait(buf)
|
||||
|
||||
" For some reason when the socket server is being used, the terminal Vim never
|
||||
" receives the `:w! XVimRemoteTest.txt` command from term_sendkeys.
|
||||
if has('socketserver') && !has('X11')
|
||||
if match(serverlist(), "XVIMTEST") == -1
|
||||
call StopVimInTerminal(buf)
|
||||
throw s:skip
|
||||
endif
|
||||
|
||||
let s:remote = 1
|
||||
return
|
||||
endif
|
||||
|
||||
let cmd = GetVimCommandCleanTerm() .. '--serverlist'
|
||||
call term_sendkeys(buf, ":r! " .. cmd .. "\<CR>")
|
||||
call TermWait(buf)
|
||||
@@ -71,6 +59,14 @@ func Test_remote_servername()
|
||||
" open XTEST.txt, if wildignore setting is not ignored, the server
|
||||
" will continue with the Xdummy.log file
|
||||
let buf2 = RunVimInTerminal('--servername XVIMTEST --remote-silent XTEST.txt', {'rows': 5, 'wait_for_ruler': 0})
|
||||
|
||||
" It may take a while for the command to be sent to XVIMTEST and be executed.
|
||||
" Do a blocking --remote-expr so that is assured the command was executed.
|
||||
botright new
|
||||
let buf3 = RunVimInTerminal('--servername XVIMTEST --remote-expr "v:servername"', {'rows': 5, 'wait_for_ruler': 0})
|
||||
call WaitForAssert({-> assert_equal("finished", term_getstatus(buf3))})
|
||||
exe buf3 .. 'bw!'
|
||||
|
||||
" job should be no-longer running, so we can just close it
|
||||
exe buf2 .. 'bw!'
|
||||
call term_sendkeys(buf, ":sil :3,$d\<CR>")
|
||||
|
||||
@@ -402,7 +402,6 @@ func Test_CmdCompletion()
|
||||
exe 'delcommand ' .. cmd
|
||||
endfor
|
||||
delcommand MissingFeature
|
||||
delcommand RunSocketServer
|
||||
|
||||
command! DoCmd1 :
|
||||
command! DoCmd2 :
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
" Test using builtin functions in the Vim9 script language.
|
||||
|
||||
source util/screendump.vim
|
||||
source util/socketserver.vim
|
||||
import './util/vim9.vim' as v9
|
||||
|
||||
" Test for passing too many or too few arguments to builtin functions
|
||||
@@ -3525,11 +3524,12 @@ enddef
|
||||
|
||||
def Test_remote_expr()
|
||||
CheckFeature clientserver
|
||||
TrySocketServer
|
||||
CheckNotMSWindows
|
||||
|
||||
if !g:socketserver_only
|
||||
if has("x11")
|
||||
CheckEnv DISPLAY
|
||||
endif
|
||||
|
||||
v9.CheckSourceDefAndScriptFailure(['remote_expr(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1'])
|
||||
v9.CheckSourceDefAndScriptFailure(['remote_expr("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2'])
|
||||
v9.CheckSourceDefAndScriptFailure(['remote_expr("a", "b", 3)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3'])
|
||||
@@ -3551,10 +3551,12 @@ enddef
|
||||
|
||||
def Test_remote_peek()
|
||||
CheckFeature clientserver
|
||||
TrySocketServer
|
||||
if !g:socketserver_only
|
||||
CheckNotMSWindows
|
||||
|
||||
if has("x11")
|
||||
CheckEnv DISPLAY
|
||||
endif
|
||||
|
||||
v9.CheckSourceDefAndScriptFailure(['remote_peek(0z10)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1174: String required for argument 1'])
|
||||
v9.CheckSourceDefAndScriptFailure(['remote_peek("a5b6c7", [1])'], ['E1013: Argument 2: type mismatch, expected string but got list<number>', 'E1174: String required for argument 2'])
|
||||
v9.CheckSourceDefExecAndScriptFailure(['remote_peek("")'], 'E573: Invalid server id used')
|
||||
@@ -3562,7 +3564,12 @@ enddef
|
||||
|
||||
def Test_remote_read()
|
||||
CheckFeature clientserver
|
||||
CheckEnv DISPLAY
|
||||
CheckNotMSWindows
|
||||
|
||||
if has("x11")
|
||||
CheckEnv DISPLAY
|
||||
endif
|
||||
|
||||
v9.CheckSourceDefAndScriptFailure(['remote_read(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1'])
|
||||
v9.CheckSourceDefAndScriptFailure(['remote_read("a", "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2'])
|
||||
v9.CheckSourceDefExecAndScriptFailure(['remote_read("")'], 'E573: Invalid server id used')
|
||||
@@ -3570,10 +3577,12 @@ enddef
|
||||
|
||||
def Test_remote_send()
|
||||
CheckFeature clientserver
|
||||
TrySocketServer
|
||||
if !g:socketserver_only
|
||||
CheckNotMSWindows
|
||||
|
||||
if has("x11")
|
||||
CheckEnv DISPLAY
|
||||
endif
|
||||
|
||||
v9.CheckSourceDefAndScriptFailure(['remote_send(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1'])
|
||||
v9.CheckSourceDefAndScriptFailure(['remote_send("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2'])
|
||||
v9.CheckSourceDefAndScriptFailure(['remote_send("a", "b", 3)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3'])
|
||||
@@ -3582,10 +3591,12 @@ enddef
|
||||
|
||||
def Test_remote_startserver()
|
||||
CheckFeature clientserver
|
||||
TrySocketServer
|
||||
if !g:socketserver_only
|
||||
CheckNotMSWindows
|
||||
|
||||
if has("x11")
|
||||
CheckEnv DISPLAY
|
||||
endif
|
||||
|
||||
v9.CheckSourceDefAndScriptFailure(['remote_startserver({})'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', 'E1174: String required for argument 1'])
|
||||
enddef
|
||||
|
||||
|
||||
@@ -348,17 +348,6 @@ func CheckGithubActions()
|
||||
endif
|
||||
endfunc
|
||||
|
||||
command RunSocketServer call RunSocketServer()
|
||||
func RunSocketServer()
|
||||
if has("socketserver") && v:servername == ""
|
||||
try
|
||||
call remote_startserver('VIMSOCKETSERVERTEST')
|
||||
catch " not possible to start a remote server
|
||||
throw 'Skipped: Cannot start remote server'
|
||||
endtry
|
||||
endif
|
||||
endfunc
|
||||
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
" Check if only the socketserver backend is available for clientserver (only on
|
||||
" Unix), and set g:socketserver_only to v:true along with starting the
|
||||
" socketserver.
|
||||
command TrySocketServer call TrySocketServer()
|
||||
func TrySocketServer()
|
||||
if has("socketserver") && !has("x11")
|
||||
let g:socketserver_only = v:true
|
||||
|
||||
if v:servername == ""
|
||||
call remote_startserver('VIMSOCKETSERVERTEST')
|
||||
endif
|
||||
else
|
||||
let g:socketserver_only = v:false
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
@@ -406,20 +406,10 @@ inchar_loop(
|
||||
# endif
|
||||
|
||||
if ((resize_func != NULL && resize_func(TRUE))
|
||||
# if defined(FEAT_CLIENTSERVER) && defined(UNIX)
|
||||
|| (
|
||||
# ifdef FEAT_X11
|
||||
(clientserver_method == CLIENTSERVER_METHOD_X11 &&
|
||||
server_waiting())
|
||||
# endif
|
||||
# if defined(FEAT_X11) && defined(FEAT_SOCKETSERVER)
|
||||
||
|
||||
# endif
|
||||
# ifdef FEAT_SOCKETSERVER
|
||||
(clientserver_method == CLIENTSERVER_METHOD_SOCKET &&
|
||||
socket_server_waiting_accept())
|
||||
# endif
|
||||
)
|
||||
# if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
|
||||
||
|
||||
(clientserver_method == CLIENTSERVER_METHOD_X11 &&
|
||||
server_waiting())
|
||||
# endif
|
||||
# ifdef MESSAGE_QUEUE
|
||||
|| interrupted
|
||||
|
||||
@@ -729,6 +729,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
512,
|
||||
/**/
|
||||
511,
|
||||
/**/
|
||||
|
||||
Reference in New Issue
Block a user