# HG changeset patch # User Christian Brabandt # Date 1489857304 -3600 # Node ID 76fb679a310eb1c9093670c69193d3d9e279736e # Parent 93853f45b9c1d607543d4694c646a3fbdcb7778c patch 8.0.0475: not enough testing for the client-server feature commit https://github.com/vim/vim/commit/7416f3e73ab2c4e7ae3adc2ff6e70234f7d40d2e Author: Bram Moolenaar Date: Sat Mar 18 18:10:13 2017 +0100 patch 8.0.0475: not enough testing for the client-server feature Problem: Not enough testing for the client-server feature. Solution: Add more tests. Add the remote_startserver() function. Fix that a locally evaluated expression uses function-local variables. diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2262,6 +2262,8 @@ remote_peek({serverid} [, {retvar}]) remote_read({serverid}) 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} @@ -6372,6 +6374,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: > @@ -6383,6 +6386,12 @@ remote_send({server}, {string} [, {idvar :echo remote_send("gvim", ":sleep 10 | echo ". \ 'server2client(expand(""), "HELLO")') < + *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/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -307,6 +307,7 @@ static void f_remote_foreground(typval_T static void f_remote_peek(typval_T *argvars, typval_T *rettv); static void f_remote_read(typval_T *argvars, typval_T *rettv); static void f_remote_send(typval_T *argvars, typval_T *rettv); +static void f_remote_startserver(typval_T *argvars, typval_T *rettv); static void f_remove(typval_T *argvars, typval_T *rettv); static void f_rename(typval_T *argvars, typval_T *rettv); static void f_repeat(typval_T *argvars, typval_T *rettv); @@ -741,6 +742,7 @@ static struct fst {"remote_peek", 1, 2, f_remote_peek}, {"remote_read", 1, 1, f_remote_read}, {"remote_send", 2, 3, f_remote_send}, + {"remote_startserver", 1, 1, f_remote_startserver}, {"remove", 2, 3, f_remove}, {"rename", 2, 2, f_rename}, {"repeat", 2, 2, f_repeat}, @@ -8487,7 +8489,7 @@ check_connection(void) make_connection(); if (X_DISPLAY == NULL) { - EMSG(_("E240: No connection to Vim server")); + EMSG(_("E240: No connection to the X server")); return FAIL; } return OK; @@ -8690,6 +8692,33 @@ f_remote_send(typval_T *argvars UNUSED, } /* + * "remote_startserver()" function + */ + static void +f_remote_startserver(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ +#ifdef FEAT_CLIENTSERVER + char_u *server = get_tv_string_chk(&argvars[0]); + + if (server == NULL) + return; /* type error; errmsg already given */ + if (serverName != NULL) + EMSG(_("E941: already started a server")); + else + { +# ifdef FEAT_X11 + if (check_connection() == OK) + serverRegisterName(X_DISPLAY, server); +# else + serverSetName(server); +# endif + } +#else + EMSG(_("E942: +clientserver feature not available")); +#endif +} + +/* * "remove()" function */ static void diff --git a/src/if_xcmdsrv.c b/src/if_xcmdsrv.c --- a/src/if_xcmdsrv.c +++ b/src/if_xcmdsrv.c @@ -399,27 +399,7 @@ serverSendToVim( /* Execute locally if no display or target is ourselves */ if (dpy == NULL || (serverName != NULL && STRICMP(name, serverName) == 0)) - { - if (asExpr) - { - char_u *ret; - - ret = eval_client_expr_to_string(cmd); - if (result != NULL) - { - if (ret == NULL) - *result = vim_strsave((char_u *)_(e_invexprmsg)); - else - *result = ret; - } - else - vim_free(ret); - return ret == NULL ? -1 : 0; - } - else - server_to_input_buf(cmd); - return 0; - } + return sendToLocalVim(cmd, asExpr, result); /* * Bind the server name to a communication window. @@ -800,6 +780,7 @@ serverSendReply(char_u *name, char_u *st WaitForReply(void *p) { Window *w = (Window *) p; + return ServerReplyFind(*w, SROP_Find) != NULL; } diff --git a/src/os_mswin.c b/src/os_mswin.c --- a/src/os_mswin.c +++ b/src/os_mswin.c @@ -2409,6 +2409,10 @@ serverSendToVim( int retcode = 0; char_u altname_buf[MAX_PATH]; + /* Execute locally if no display or target is ourselves */ + if (serverName != NULL && STRICMP(name, serverName) == 0) + return sendToLocalVim(cmd, asExpr, result); + /* If the server name does not end in a digit then we look for an * alternate name. e.g. when "name" is GVIM the we may find GVIM2. */ if (STRLEN(name) > 1 && !vim_isdigit(name[STRLEN(name) - 1])) diff --git a/src/proto/main.pro b/src/proto/main.pro --- a/src/proto/main.pro +++ b/src/proto/main.pro @@ -11,5 +11,6 @@ void time_pop(void *tp); void time_msg(char *mesg, void *tv_start); void server_to_input_buf(char_u *str); char_u *eval_client_expr_to_string(char_u *expr); +int sendToLocalVim(char_u *cmd, int asExpr, char_u **result); char_u *serverConvert(char_u *client_enc, char_u *data, char_u **tofree); /* vim: set ft=c : */ diff --git a/src/testdir/test_clientserver.vim b/src/testdir/test_clientserver.vim --- a/src/testdir/test_clientserver.vim +++ b/src/testdir/test_clientserver.vim @@ -30,6 +30,31 @@ func Test_client_server() call WaitFor('remote_expr("' . name . '", "testvar") == "yes"') call assert_equal('yes', remote_expr(name, "testvar")) + if has('unix') && has('gui') && !has('gui_running') + " Running in a terminal and the GUI is avaiable: 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. + call remote_send(name, ":gui -f\") + sleep 500m + call remote_send(name, ":let testvar = 'maybe'\") + call WaitFor('remote_expr("' . name . '", "testvar") == "maybe"') + call assert_equal('maybe', remote_expr(name, "testvar")) + endif + + call assert_fails('call remote_send("XXX", ":let testvar = ''yes''\")', 'E241') + + " Expression evaluated locally. + if v:servername == '' + call remote_startserver('MYSELF') + call assert_equal('MYSELF', v:servername) + endif + let g:testvar = 'myself' + call assert_equal('myself', remote_expr(v:servername, 'testvar')) + + call remote_send(name, ":call server2client(expand(''), 'got it')\", 'g:myserverid') + call assert_equal('got it', remote_read(g:myserverid)) + call remote_send(name, ":qa!\") call WaitFor('job_status(g:job) == "dead"') if job_status(g:job) != 'dead' diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -765,6 +765,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 475, +/**/ 474, /**/ 473,