aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/eval.txt22
-rw-r--r--src/nvim/testdir/Makefile1
-rw-r--r--src/nvim/testdir/test_clientserver.vim107
3 files changed, 125 insertions, 5 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 635c08556b..d71bbf2528 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2222,6 +2222,8 @@ remote_read({serverid} [, {timeout}])
String read reply string
remote_send({server}, {string} [, {idvar}])
String send key sequence
+remote_startserver({name}) none become server {name}
+ String send key sequence
remove({list}, {idx} [, {end}]) any remove items {idx}-{end} from {list}
remove({dict}, {key}) any remove entry {key} from {dict}
rename({from}, {to}) Number rename (move) file from {from} to {to}
@@ -6196,15 +6198,17 @@ reltimestr({time}) *reltimestr()*
< Also see |profiling|.
*remote_expr()* *E449*
-remote_expr({server}, {string} [, {idvar}])
+remote_expr({server}, {string} [, {idvar} [, {timeout}]])
Send the {string} to {server}. The string is sent as an
expression and the result is returned after evaluation.
The result must be a String or a |List|. A |List| is turned
into a String by joining the items with a line break in
between (not at the end), like with join(expr, "\n").
- If {idvar} is present, it is taken as the name of a
- variable and a {serverid} for later use with
+ If {idvar} is present and not empty, it is taken as the name
+ of a variable and a {serverid} for later use with
remote_read() is stored there.
+ If {timeout} is given the read times out after this many
+ seconds. Otherwise a timeout of 600 seconds is used.
See also |clientserver| |RemoteReply|.
This function is not available in the |sandbox|.
{only available when compiled with the |+clientserver| feature}
@@ -6248,9 +6252,10 @@ remote_peek({serverid} [, {retvar}]) *remote_peek()*
:let repl = ""
:echo "PEEK: ".remote_peek(id, "repl").": ".repl
-remote_read({serverid}) *remote_read()*
+remote_read({serverid}, [{timeout}]) *remote_read()*
Return the oldest available reply from {serverid} and consume
- it. It blocks until a reply is available.
+ it. Unless a {timeout} in seconds is given, it blocks until a
+ reply is available.
See also |clientserver|.
This function is not available in the |sandbox|.
{only available when compiled with the |+clientserver| feature}
@@ -6268,6 +6273,7 @@ remote_send({server}, {string} [, {idvar}])
See also |clientserver| |RemoteReply|.
This function is not available in the |sandbox|.
{only available when compiled with the |+clientserver| feature}
+
Note: Any errors will be reported in the server and may mess
up the display.
Examples: >
@@ -6279,6 +6285,12 @@ remote_send({server}, {string} [, {idvar}])
:echo remote_send("gvim", ":sleep 10 | echo ".
\ 'server2client(expand("<client>"), "HELLO")<CR>')
<
+ *remote_startserver()* *E941* *E942*
+remote_startserver({name})
+ Become the server {name}. This fails if already running as a
+ server, when |v:servername| is not empty.
+ {only available when compiled with the |+clientserver| feature}
+
remove({list}, {idx} [, {end}]) *remove()*
Without {end}: Remove the item at {idx} from |List| {list} and
return the item.
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index 651ab3db2b..e3b717989e 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -40,6 +40,7 @@ NEW_TESTS ?= \
test_changedtick.res \
test_charsearch.res \
test_cindent.res \
+ test_clientserver.res \
test_close_count.res \
test_cmdline.res \
test_command_count.res \
diff --git a/src/nvim/testdir/test_clientserver.vim b/src/nvim/testdir/test_clientserver.vim
new file mode 100644
index 0000000000..60ef20e0b2
--- /dev/null
+++ b/src/nvim/testdir/test_clientserver.vim
@@ -0,0 +1,107 @@
+" Tests for the +clientserver feature.
+
+if !has('job') || !has('clientserver')
+ finish
+endif
+
+source shared.vim
+
+func Test_client_server()
+ let cmd = GetVimCommand()
+ if cmd == ''
+ return
+ endif
+ if has('x11')
+ if empty($DISPLAY)
+ throw 'Skipped: $DISPLAY is not set'
+ endif
+ try
+ call remote_send('xxx', '')
+ catch
+ if v:exception =~ 'E240:'
+ throw 'Skipped: no connection to the X server'
+ endif
+ " ignore other errors
+ endtry
+ endif
+
+ let name = 'XVIMTEST'
+ let cmd .= ' --servername ' . name
+ let g:job = job_start(cmd, {'stoponexit': 'kill', 'out_io': 'null'})
+ call WaitFor('job_status(g:job) == "run"')
+ if job_status(g:job) != 'run'
+ call assert_report('Cannot run the Vim server')
+ return
+ endif
+
+ " Takes a short while for the server to be active.
+ call WaitFor('serverlist() =~ "' . name . '"')
+ call assert_match(name, serverlist())
+
+ call remote_foreground(name)
+
+ call remote_send(name, ":let testvar = 'yes'\<CR>")
+ call WaitFor('remote_expr("' . name . '", "exists(\"testvar\") ? testvar : \"\"", "", 1) == "yes"')
+ call assert_equal('yes', remote_expr(name, "testvar", "", 2))
+
+ if has('unix') && has('gui') && !has('gui_running')
+ " Running in a terminal and the GUI is available: Tell the server to open
+ " the GUI and check that the remote command still works.
+ " Need to wait for the GUI to start up, otherwise the send hangs in trying
+ " to send to the terminal window.
+ if has('gui_athena') || has('gui_motif')
+ " For those GUIs, ignore the 'failed to create input context' error.
+ call remote_send(name, ":call test_ignore_error('E285') | gui -f\<CR>")
+ else
+ call remote_send(name, ":gui -f\<CR>")
+ endif
+ " Wait for the server to be up and answering requests.
+ sleep 100m
+ call WaitFor('remote_expr("' . name . '", "v:version", "", 1) != ""')
+ call assert_true(remote_expr(name, "v:version", "", 1) != "")
+
+ call remote_send(name, ":let testvar = 'maybe'\<CR>")
+ call WaitFor('remote_expr("' . name . '", "testvar", "", 1) == "maybe"')
+ call assert_equal('maybe', remote_expr(name, "testvar", "", 2))
+ endif
+
+ call assert_fails('call remote_send("XXX", ":let testvar = ''yes''\<CR>")', 'E241')
+
+ " Expression evaluated locally.
+ if v:servername == ''
+ call remote_startserver('MYSELF')
+ " May get MYSELF1 when running the test again.
+ call assert_match('MYSELF', v:servername)
+ endif
+ let g:testvar = 'myself'
+ call assert_equal('myself', remote_expr(v:servername, 'testvar'))
+
+ call remote_send(name, ":call server2client(expand('<client>'), 'got it')\<CR>", 'g:myserverid')
+ call assert_equal('got it', remote_read(g:myserverid, 2))
+
+ call remote_send(name, ":call server2client(expand('<client>'), 'another')\<CR>", 'g:myserverid')
+ let peek_result = 'nothing'
+ let r = remote_peek(g:myserverid, 'peek_result')
+ " unpredictable whether the result is already avaialble.
+ if r > 0
+ call assert_equal('another', peek_result)
+ elseif r == 0
+ call assert_equal('nothing', peek_result)
+ else
+ call assert_report('remote_peek() failed')
+ endif
+ let g:peek_result = 'empty'
+ call WaitFor('remote_peek(g:myserverid, "g:peek_result") > 0')
+ call assert_equal('another', g:peek_result)
+ call assert_equal('another', remote_read(g:myserverid, 2))
+
+ call remote_send(name, ":qa!\<CR>")
+ call WaitFor('job_status(g:job) == "dead"')
+ if job_status(g:job) != 'dead'
+ call assert_report('Server did not exit')
+ call job_stop(g:job, 'kill')
+ endif
+endfunc
+
+" Uncomment this line to get a debugging log
+" call ch_logfile('channellog', 'w')