comparison src/eval.c @ 7788:192ae655ac91 v7.4.1191

commit https://github.com/vim/vim/commit/3b5f929b18492fec291d1ec95a91f54e5912c03b Author: Bram Moolenaar <Bram@vim.org> Date: Thu Jan 28 22:37:01 2016 +0100 patch 7.4.1191 Problem: The channel feature isn't working yet. Solution: Add the connect(), disconnect(), sendexpr() and sendraw() functions. Add initial documentation. Add a demo server.
author Christian Brabandt <cb@256bit.org>
date Thu, 28 Jan 2016 22:45:04 +0100
parents 3d8e4e0d7127
children 83861277e6a3
comparison
equal deleted inserted replaced
7787:a0ae64e7006f 7788:192ae655ac91
456 static char_u *string_quote(char_u *str, int function); 456 static char_u *string_quote(char_u *str, int function);
457 static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate); 457 static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate);
458 static int find_internal_func(char_u *name); 458 static int find_internal_func(char_u *name);
459 static char_u *deref_func_name(char_u *name, int *lenp, int no_autoload); 459 static char_u *deref_func_name(char_u *name, int *lenp, int no_autoload);
460 static int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict); 460 static int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict);
461 static int call_func(char_u *funcname, int len, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict);
462 static void emsg_funcname(char *ermsg, char_u *name); 461 static void emsg_funcname(char *ermsg, char_u *name);
463 static int non_zero_arg(typval_T *argvars); 462 static int non_zero_arg(typval_T *argvars);
464 463
465 #ifdef FEAT_FLOAT 464 #ifdef FEAT_FLOAT
466 static void f_abs(typval_T *argvars, typval_T *rettv); 465 static void f_abs(typval_T *argvars, typval_T *rettv);
514 static void f_copy(typval_T *argvars, typval_T *rettv); 513 static void f_copy(typval_T *argvars, typval_T *rettv);
515 #ifdef FEAT_FLOAT 514 #ifdef FEAT_FLOAT
516 static void f_cos(typval_T *argvars, typval_T *rettv); 515 static void f_cos(typval_T *argvars, typval_T *rettv);
517 static void f_cosh(typval_T *argvars, typval_T *rettv); 516 static void f_cosh(typval_T *argvars, typval_T *rettv);
518 #endif 517 #endif
518 #ifdef FEAT_CHANNEL
519 static void f_connect(typval_T *argvars, typval_T *rettv);
520 #endif
519 static void f_count(typval_T *argvars, typval_T *rettv); 521 static void f_count(typval_T *argvars, typval_T *rettv);
520 static void f_cscope_connection(typval_T *argvars, typval_T *rettv); 522 static void f_cscope_connection(typval_T *argvars, typval_T *rettv);
521 static void f_cursor(typval_T *argsvars, typval_T *rettv); 523 static void f_cursor(typval_T *argsvars, typval_T *rettv);
522 static void f_deepcopy(typval_T *argvars, typval_T *rettv); 524 static void f_deepcopy(typval_T *argvars, typval_T *rettv);
523 static void f_delete(typval_T *argvars, typval_T *rettv); 525 static void f_delete(typval_T *argvars, typval_T *rettv);
524 static void f_did_filetype(typval_T *argvars, typval_T *rettv); 526 static void f_did_filetype(typval_T *argvars, typval_T *rettv);
525 static void f_diff_filler(typval_T *argvars, typval_T *rettv); 527 static void f_diff_filler(typval_T *argvars, typval_T *rettv);
526 static void f_diff_hlID(typval_T *argvars, typval_T *rettv); 528 static void f_diff_hlID(typval_T *argvars, typval_T *rettv);
529 #ifdef FEAT_CHANNEL
530 static void f_disconnect(typval_T *argvars, typval_T *rettv);
531 #endif
527 static void f_empty(typval_T *argvars, typval_T *rettv); 532 static void f_empty(typval_T *argvars, typval_T *rettv);
528 static void f_escape(typval_T *argvars, typval_T *rettv); 533 static void f_escape(typval_T *argvars, typval_T *rettv);
529 static void f_eval(typval_T *argvars, typval_T *rettv); 534 static void f_eval(typval_T *argvars, typval_T *rettv);
530 static void f_eventhandler(typval_T *argvars, typval_T *rettv); 535 static void f_eventhandler(typval_T *argvars, typval_T *rettv);
531 static void f_executable(typval_T *argvars, typval_T *rettv); 536 static void f_executable(typval_T *argvars, typval_T *rettv);
696 static void f_search(typval_T *argvars, typval_T *rettv); 701 static void f_search(typval_T *argvars, typval_T *rettv);
697 static void f_searchdecl(typval_T *argvars, typval_T *rettv); 702 static void f_searchdecl(typval_T *argvars, typval_T *rettv);
698 static void f_searchpair(typval_T *argvars, typval_T *rettv); 703 static void f_searchpair(typval_T *argvars, typval_T *rettv);
699 static void f_searchpairpos(typval_T *argvars, typval_T *rettv); 704 static void f_searchpairpos(typval_T *argvars, typval_T *rettv);
700 static void f_searchpos(typval_T *argvars, typval_T *rettv); 705 static void f_searchpos(typval_T *argvars, typval_T *rettv);
706 #ifdef FEAT_CHANNEL
707 static void f_sendexpr(typval_T *argvars, typval_T *rettv);
708 static void f_sendraw(typval_T *argvars, typval_T *rettv);
709 #endif
701 static void f_server2client(typval_T *argvars, typval_T *rettv); 710 static void f_server2client(typval_T *argvars, typval_T *rettv);
702 static void f_serverlist(typval_T *argvars, typval_T *rettv); 711 static void f_serverlist(typval_T *argvars, typval_T *rettv);
703 static void f_setbufvar(typval_T *argvars, typval_T *rettv); 712 static void f_setbufvar(typval_T *argvars, typval_T *rettv);
704 static void f_setcharsearch(typval_T *argvars, typval_T *rettv); 713 static void f_setcharsearch(typval_T *argvars, typval_T *rettv);
705 static void f_setcmdpos(typval_T *argvars, typval_T *rettv); 714 static void f_setcmdpos(typval_T *argvars, typval_T *rettv);
8168 {"complete", 2, 2, f_complete}, 8177 {"complete", 2, 2, f_complete},
8169 {"complete_add", 1, 1, f_complete_add}, 8178 {"complete_add", 1, 1, f_complete_add},
8170 {"complete_check", 0, 0, f_complete_check}, 8179 {"complete_check", 0, 0, f_complete_check},
8171 #endif 8180 #endif
8172 {"confirm", 1, 4, f_confirm}, 8181 {"confirm", 1, 4, f_confirm},
8182 #ifdef FEAT_CHANNEL
8183 {"connect", 2, 3, f_connect},
8184 #endif
8173 {"copy", 1, 1, f_copy}, 8185 {"copy", 1, 1, f_copy},
8174 #ifdef FEAT_FLOAT 8186 #ifdef FEAT_FLOAT
8175 {"cos", 1, 1, f_cos}, 8187 {"cos", 1, 1, f_cos},
8176 {"cosh", 1, 1, f_cosh}, 8188 {"cosh", 1, 1, f_cosh},
8177 #endif 8189 #endif
8181 {"deepcopy", 1, 2, f_deepcopy}, 8193 {"deepcopy", 1, 2, f_deepcopy},
8182 {"delete", 1, 2, f_delete}, 8194 {"delete", 1, 2, f_delete},
8183 {"did_filetype", 0, 0, f_did_filetype}, 8195 {"did_filetype", 0, 0, f_did_filetype},
8184 {"diff_filler", 1, 1, f_diff_filler}, 8196 {"diff_filler", 1, 1, f_diff_filler},
8185 {"diff_hlID", 2, 2, f_diff_hlID}, 8197 {"diff_hlID", 2, 2, f_diff_hlID},
8198 #ifdef FEAT_CHANNEL
8199 {"disconnect", 1, 1, f_disconnect},
8200 #endif
8186 {"empty", 1, 1, f_empty}, 8201 {"empty", 1, 1, f_empty},
8187 {"escape", 2, 2, f_escape}, 8202 {"escape", 2, 2, f_escape},
8188 {"eval", 1, 1, f_eval}, 8203 {"eval", 1, 1, f_eval},
8189 {"eventhandler", 0, 0, f_eventhandler}, 8204 {"eventhandler", 0, 0, f_eventhandler},
8190 {"executable", 1, 1, f_executable}, 8205 {"executable", 1, 1, f_executable},
8359 {"search", 1, 4, f_search}, 8374 {"search", 1, 4, f_search},
8360 {"searchdecl", 1, 3, f_searchdecl}, 8375 {"searchdecl", 1, 3, f_searchdecl},
8361 {"searchpair", 3, 7, f_searchpair}, 8376 {"searchpair", 3, 7, f_searchpair},
8362 {"searchpairpos", 3, 7, f_searchpairpos}, 8377 {"searchpairpos", 3, 7, f_searchpairpos},
8363 {"searchpos", 1, 4, f_searchpos}, 8378 {"searchpos", 1, 4, f_searchpos},
8379 #ifdef FEAT_CHANNEL
8380 {"sendexpr", 2, 3, f_sendexpr},
8381 {"sendraw", 2, 3, f_sendraw},
8382 #endif
8364 {"server2client", 2, 2, f_server2client}, 8383 {"server2client", 2, 2, f_server2client},
8365 {"serverlist", 0, 0, f_serverlist}, 8384 {"serverlist", 0, 0, f_serverlist},
8366 {"setbufvar", 3, 3, f_setbufvar}, 8385 {"setbufvar", 3, 3, f_setbufvar},
8367 {"setcharsearch", 1, 1, f_setcharsearch}, 8386 {"setcharsearch", 1, 1, f_setcharsearch},
8368 {"setcmdpos", 1, 1, f_setcmdpos}, 8387 {"setcmdpos", 1, 1, f_setcmdpos},
8672 /* 8691 /*
8673 * Call a function with its resolved parameters 8692 * Call a function with its resolved parameters
8674 * Return FAIL when the function can't be called, OK otherwise. 8693 * Return FAIL when the function can't be called, OK otherwise.
8675 * Also returns OK when an error was encountered while executing the function. 8694 * Also returns OK when an error was encountered while executing the function.
8676 */ 8695 */
8677 static int 8696 int
8678 call_func(funcname, len, rettv, argcount, argvars, firstline, lastline, 8697 call_func(funcname, len, rettv, argcount, argvars, firstline, lastline,
8679 doesrange, evaluate, selfdict) 8698 doesrange, evaluate, selfdict)
8680 char_u *funcname; /* name of the function */ 8699 char_u *funcname; /* name of the function */
8681 int len; /* length of "name" */ 8700 int len; /* length of "name" */
8682 typval_T *rettv; /* return value goes here */ 8701 typval_T *rettv; /* return value goes here */
10291 else 10310 else
10292 EMSG2(_(e_listdictarg), "count()"); 10311 EMSG2(_(e_listdictarg), "count()");
10293 rettv->vval.v_number = n; 10312 rettv->vval.v_number = n;
10294 } 10313 }
10295 10314
10315 #ifdef FEAT_CHANNEL
10316 /*
10317 * Get a callback from "arg". It can be a Funcref or a function name.
10318 * When "arg" is zero return an empty string.
10319 * Return NULL for an invalid argument.
10320 */
10321 static char_u *
10322 get_callback(typval_T *arg)
10323 {
10324 if (arg->v_type == VAR_FUNC || arg->v_type == VAR_STRING)
10325 return arg->vval.v_string;
10326 if (arg->v_type == VAR_NUMBER && arg->vval.v_number == 0)
10327 return (char_u *)"";
10328 EMSG(_("E999: Invalid callback argument"));
10329 return NULL;
10330 }
10331
10332 /*
10333 * "connect()" function
10334 */
10335 static void
10336 f_connect(argvars, rettv)
10337 typval_T *argvars;
10338 typval_T *rettv;
10339 {
10340 char_u *address;
10341 char_u *mode;
10342 char_u *callback = NULL;
10343 char_u buf1[NUMBUFLEN];
10344 char_u *p;
10345 int port;
10346 int json_mode = FALSE;
10347
10348 address = get_tv_string(&argvars[0]);
10349 mode = get_tv_string_buf(&argvars[1], buf1);
10350 if (argvars[2].v_type != VAR_UNKNOWN)
10351 {
10352 callback = get_callback(&argvars[2]);
10353 if (callback == NULL)
10354 return;
10355 }
10356
10357 /* parse address */
10358 p = vim_strchr(address, ':');
10359 if (p == NULL)
10360 {
10361 EMSG2(_(e_invarg2), address);
10362 return;
10363 }
10364 *p++ = NUL;
10365 port = atoi((char *)p);
10366 if (*address == NUL || port <= 0)
10367 {
10368 p[-1] = ':';
10369 EMSG2(_(e_invarg2), address);
10370 return;
10371 }
10372
10373 /* parse mode */
10374 if (STRCMP(mode, "json") == 0)
10375 json_mode = TRUE;
10376 else if (STRCMP(mode, "raw") != 0)
10377 {
10378 EMSG2(_(e_invarg2), mode);
10379 return;
10380 }
10381
10382 rettv->vval.v_number = channel_open((char *)address, port, NULL);
10383 if (rettv->vval.v_number >= 0)
10384 {
10385 channel_set_json_mode(rettv->vval.v_number, json_mode);
10386 if (callback != NULL && *callback != NUL)
10387 channel_set_callback(rettv->vval.v_number, callback);
10388 }
10389 }
10390 #endif
10391
10296 /* 10392 /*
10297 * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function 10393 * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
10298 * 10394 *
10299 * Checks the existence of a cscope connection. 10395 * Checks the existence of a cscope connection.
10300 */ 10396 */
10542 hlID = HLF_CHD; /* changed line */ 10638 hlID = HLF_CHD; /* changed line */
10543 } 10639 }
10544 rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (int)hlID; 10640 rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (int)hlID;
10545 #endif 10641 #endif
10546 } 10642 }
10643
10644 #ifdef FEAT_CHANNEL
10645 /*
10646 * Get the channel index from the handle argument.
10647 * Returns -1 if the handle is invalid or the channel is closed.
10648 */
10649 static int
10650 get_channel_arg(typval_T *tv)
10651 {
10652 int ch_idx;
10653
10654 if (tv->v_type != VAR_NUMBER)
10655 {
10656 EMSG2(_(e_invarg2), get_tv_string(tv));
10657 return -1;
10658 }
10659 ch_idx = tv->vval.v_number;
10660
10661 if (!channel_is_open(ch_idx))
10662 {
10663 EMSGN(_("E999: not an open channel"), ch_idx);
10664 return -1;
10665 }
10666 return ch_idx;
10667 }
10668
10669 /*
10670 * "disconnect()" function
10671 */
10672 static void
10673 f_disconnect(argvars, rettv)
10674 typval_T *argvars;
10675 typval_T *rettv UNUSED;
10676 {
10677 int ch_idx = get_channel_arg(&argvars[0]);
10678
10679 if (ch_idx >= 0)
10680 channel_close(ch_idx);
10681 }
10682 #endif
10547 10683
10548 /* 10684 /*
10549 * "empty({expr})" function 10685 * "empty({expr})" function
10550 */ 10686 */
10551 static void 10687 static void
17375 list_append_number(rettv->vval.v_list, (varnumber_T)lnum); 17511 list_append_number(rettv->vval.v_list, (varnumber_T)lnum);
17376 list_append_number(rettv->vval.v_list, (varnumber_T)col); 17512 list_append_number(rettv->vval.v_list, (varnumber_T)col);
17377 if (flags & SP_SUBPAT) 17513 if (flags & SP_SUBPAT)
17378 list_append_number(rettv->vval.v_list, (varnumber_T)n); 17514 list_append_number(rettv->vval.v_list, (varnumber_T)n);
17379 } 17515 }
17516
17517 #ifdef FEAT_CHANNEL
17518 /*
17519 * common for "sendexpr()" and "sendraw()"
17520 * Returns the channel index if the caller should read the response.
17521 * Otherwise returns -1.
17522 */
17523 static int
17524 send_common(typval_T *argvars, char_u *text, char *fun)
17525 {
17526 int ch_idx;
17527 char_u *callback = NULL;
17528
17529 ch_idx = get_channel_arg(&argvars[0]);
17530 if (ch_idx < 0)
17531 return -1;
17532
17533 if (argvars[2].v_type != VAR_UNKNOWN)
17534 {
17535 callback = get_callback(&argvars[2]);
17536 if (callback == NULL)
17537 return -1;
17538 }
17539 /* Set the callback or clear it. An empty callback means no callback and
17540 * not reading the response. */
17541 channel_set_req_callback(ch_idx,
17542 callback != NULL && *callback == NUL ? NULL : callback);
17543 if (callback == NULL)
17544 channel_will_block(ch_idx);
17545
17546 if (channel_send(ch_idx, text, fun) == OK && callback == NULL)
17547 return ch_idx;
17548 return -1;
17549 }
17550
17551 /*
17552 * "sendexpr()" function
17553 */
17554 static void
17555 f_sendexpr(argvars, rettv)
17556 typval_T *argvars;
17557 typval_T *rettv;
17558 {
17559 char_u *text;
17560 char_u *resp;
17561 typval_T nrtv;
17562 typval_T listtv;
17563 int ch_idx;
17564
17565 /* return an empty string by default */
17566 rettv->v_type = VAR_STRING;
17567 rettv->vval.v_string = NULL;
17568
17569 nrtv.v_type = VAR_NUMBER;
17570 nrtv.vval.v_number = channel_get_id();
17571 if (rettv_list_alloc(&listtv) == FAIL)
17572 return;
17573 if (list_append_tv(listtv.vval.v_list, &nrtv) == FAIL
17574 || list_append_tv(listtv.vval.v_list, &argvars[1]) == FAIL)
17575 {
17576 list_unref(listtv.vval.v_list);
17577 return;
17578 }
17579
17580 text = json_encode(&listtv);
17581 list_unref(listtv.vval.v_list);
17582
17583 ch_idx = send_common(argvars, text, "sendexpr");
17584 if (ch_idx >= 0)
17585 {
17586 /* TODO: read until the whole JSON message is received */
17587 /* TODO: only use the message with the right message ID */
17588 resp = channel_read_block(ch_idx);
17589 if (resp != NULL)
17590 {
17591 channel_decode_json(resp, rettv);
17592 vim_free(resp);
17593 }
17594 }
17595 }
17596
17597 /*
17598 * "sendraw()" function
17599 */
17600 static void
17601 f_sendraw(argvars, rettv)
17602 typval_T *argvars;
17603 typval_T *rettv;
17604 {
17605 char_u buf[NUMBUFLEN];
17606 char_u *text;
17607 int ch_idx;
17608
17609 /* return an empty string by default */
17610 rettv->v_type = VAR_STRING;
17611 rettv->vval.v_string = NULL;
17612
17613 text = get_tv_string_buf(&argvars[1], buf);
17614 ch_idx = send_common(argvars, text, "sendraw");
17615 if (ch_idx >= 0)
17616 rettv->vval.v_string = channel_read_block(ch_idx);
17617 }
17618 #endif
17380 17619
17381 17620
17382 static void 17621 static void
17383 f_server2client(argvars, rettv) 17622 f_server2client(argvars, rettv)
17384 typval_T *argvars UNUSED; 17623 typval_T *argvars UNUSED;