Mercurial > vim
comparison src/channel.c @ 7864:6b0891de44a9 v7.4.1229
commit https://github.com/vim/vim/commit/fb1f62691eae7c79a28b3b17a60e72ce198c71a2
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Jan 31 20:24:32 2016 +0100
patch 7.4.1229
Problem: "eval" and "expr" channel commands don't work yet.
Solution: Implement them. Update the error numbers. Also add "redraw".
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sun, 31 Jan 2016 20:30:04 +0100 |
parents | 28f569c7dab9 |
children | 17e6ff1a74f1 |
comparison
equal
deleted
inserted
replaced
7863:e18a688b2e3b | 7864:6b0891de44a9 |
---|---|
291 | 291 |
292 idx = add_channel(); | 292 idx = add_channel(); |
293 if (idx < 0) | 293 if (idx < 0) |
294 { | 294 { |
295 CHERROR("All channels are in use\n", ""); | 295 CHERROR("All channels are in use\n", ""); |
296 EMSG(_("E999: All channels are in use")); | 296 EMSG(_("E897: All channels are in use")); |
297 return -1; | 297 return -1; |
298 } | 298 } |
299 | 299 |
300 if ((sd = (sock_T)socket(AF_INET, SOCK_STREAM, 0)) == (sock_T)-1) | 300 if ((sd = (sock_T)socket(AF_INET, SOCK_STREAM, 0)) == (sock_T)-1) |
301 { | 301 { |
302 CHERROR("error in socket() in channel_open()\n", ""); | 302 CHERROR("error in socket() in channel_open()\n", ""); |
303 PERROR("E999: socket() in channel_open()"); | 303 PERROR("E898: socket() in channel_open()"); |
304 return -1; | 304 return -1; |
305 } | 305 } |
306 | 306 |
307 /* Get the server internet address and put into addr structure */ | 307 /* Get the server internet address and put into addr structure */ |
308 /* fill in the socket address structure and connect to server */ | 308 /* fill in the socket address structure and connect to server */ |
310 server.sin_family = AF_INET; | 310 server.sin_family = AF_INET; |
311 server.sin_port = htons(port); | 311 server.sin_port = htons(port); |
312 if ((host = gethostbyname(hostname)) == NULL) | 312 if ((host = gethostbyname(hostname)) == NULL) |
313 { | 313 { |
314 CHERROR("error in gethostbyname() in channel_open()\n", ""); | 314 CHERROR("error in gethostbyname() in channel_open()\n", ""); |
315 PERROR("E999: gethostbyname() in channel_open()"); | 315 PERROR("E901: gethostbyname() in channel_open()"); |
316 sock_close(sd); | 316 sock_close(sd); |
317 return -1; | 317 return -1; |
318 } | 318 } |
319 memcpy((char *)&server.sin_addr, host->h_addr, host->h_length); | 319 memcpy((char *)&server.sin_addr, host->h_addr, host->h_length); |
320 | 320 |
328 sock_close(sd); | 328 sock_close(sd); |
329 if ((sd = (sock_T)socket(AF_INET, SOCK_STREAM, 0)) == (sock_T)-1) | 329 if ((sd = (sock_T)socket(AF_INET, SOCK_STREAM, 0)) == (sock_T)-1) |
330 { | 330 { |
331 SOCK_ERRNO; | 331 SOCK_ERRNO; |
332 CHERROR("socket() retry in channel_open()\n", ""); | 332 CHERROR("socket() retry in channel_open()\n", ""); |
333 PERROR("E999: socket() retry in channel_open()"); | 333 PERROR("E900: socket() retry in channel_open()"); |
334 return -1; | 334 return -1; |
335 } | 335 } |
336 if (connect(sd, (struct sockaddr *)&server, sizeof(server))) | 336 if (connect(sd, (struct sockaddr *)&server, sizeof(server))) |
337 { | 337 { |
338 int retries = 36; | 338 int retries = 36; |
360 } | 360 } |
361 if (!success) | 361 if (!success) |
362 { | 362 { |
363 /* Get here when the server can't be found. */ | 363 /* Get here when the server can't be found. */ |
364 CHERROR("Cannot connect to port after retry\n", ""); | 364 CHERROR("Cannot connect to port after retry\n", ""); |
365 PERROR(_("E999: Cannot connect to port after retry2")); | 365 PERROR(_("E899: Cannot connect to port after retry2")); |
366 sock_close(sd); | 366 sock_close(sd); |
367 return -1; | 367 return -1; |
368 } | 368 } |
369 } | 369 } |
370 } | 370 } |
371 else | 371 else |
372 { | 372 { |
373 CHERROR("Cannot connect to port\n", ""); | 373 CHERROR("Cannot connect to port\n", ""); |
374 PERROR(_("E999: Cannot connect to port")); | 374 PERROR(_("E902: Cannot connect to port")); |
375 sock_close(sd); | 375 sock_close(sd); |
376 return -1; | 376 return -1; |
377 } | 377 } |
378 } | 378 } |
379 | 379 |
416 channels[idx].ch_req_callback = callback == NULL | 416 channels[idx].ch_req_callback = callback == NULL |
417 ? NULL : vim_strsave(callback); | 417 ? NULL : vim_strsave(callback); |
418 } | 418 } |
419 | 419 |
420 /* | 420 /* |
421 * Decode JSON "msg", which must have the form "[expr1, expr2]". | 421 * Decode JSON "msg", which must have the form "[expr1, expr2, expr3]". |
422 * Put "expr1" in "tv1". | 422 * Put "expr1" in "tv1". |
423 * Put "expr2" in "tv2". | 423 * Put "expr2" in "tv2". |
424 * Put "expr3" in "tv3". If "tv3" is NULL there is no "expr3". | |
425 * | |
424 * Return OK or FAIL. | 426 * Return OK or FAIL. |
425 */ | 427 */ |
426 int | 428 int |
427 channel_decode_json(char_u *msg, typval_T *tv1, typval_T *tv2) | 429 channel_decode_json(char_u *msg, typval_T *tv1, typval_T *tv2, typval_T *tv3) |
428 { | 430 { |
429 js_read_T reader; | 431 js_read_T reader; |
430 typval_T listtv; | 432 typval_T listtv; |
431 | 433 |
432 reader.js_buf = msg; | 434 reader.js_buf = msg; |
433 reader.js_eof = TRUE; | 435 reader.js_eof = TRUE; |
434 reader.js_used = 0; | 436 reader.js_used = 0; |
435 json_decode(&reader, &listtv); | 437 json_decode(&reader, &listtv); |
436 | 438 |
437 if (listtv.v_type == VAR_LIST && listtv.vval.v_list->lv_len == 2) | 439 if (listtv.v_type == VAR_LIST) |
438 { | 440 { |
439 /* Move the item from the list and then change the type to avoid the | 441 list_T *list = listtv.vval.v_list; |
440 * item being freed. */ | 442 |
441 *tv1 = listtv.vval.v_list->lv_first->li_tv; | 443 if (list->lv_len == 2 || (tv3 != NULL && list->lv_len == 3)) |
442 listtv.vval.v_list->lv_first->li_tv.v_type = VAR_NUMBER; | 444 { |
443 *tv2 = listtv.vval.v_list->lv_last->li_tv; | 445 /* Move the item from the list and then change the type to avoid the |
444 listtv.vval.v_list->lv_last->li_tv.v_type = VAR_NUMBER; | 446 * item being freed. */ |
445 list_unref(listtv.vval.v_list); | 447 *tv1 = list->lv_first->li_tv; |
446 return OK; | 448 list->lv_first->li_tv.v_type = VAR_NUMBER; |
449 *tv2 = list->lv_first->li_next->li_tv; | |
450 list->lv_first->li_next->li_tv.v_type = VAR_NUMBER; | |
451 if (tv3 != NULL) | |
452 { | |
453 if (list->lv_len == 3) | |
454 { | |
455 *tv3 = list->lv_last->li_tv; | |
456 list->lv_last->li_tv.v_type = VAR_NUMBER; | |
457 } | |
458 else | |
459 tv3->v_type = VAR_UNKNOWN; | |
460 } | |
461 list_unref(list); | |
462 return OK; | |
463 } | |
447 } | 464 } |
448 | 465 |
449 /* give error message? */ | 466 /* give error message? */ |
450 clear_tv(&listtv); | 467 clear_tv(&listtv); |
451 return FAIL; | 468 return FAIL; |
470 setcursor(); | 487 setcursor(); |
471 cursor_on(); | 488 cursor_on(); |
472 out_flush(); | 489 out_flush(); |
473 } | 490 } |
474 | 491 |
492 /* | |
493 * Execute a command received over channel "idx". | |
494 * "cmd" is the command string, "arg2" the second argument. | |
495 * "arg3" is the third argument, NULL if missing. | |
496 */ | |
475 static void | 497 static void |
476 channel_exe_cmd(char_u *cmd, typval_T *arg) | 498 channel_exe_cmd(int idx, char_u *cmd, typval_T *arg2, typval_T *arg3) |
477 { | 499 { |
500 char_u *arg; | |
501 | |
502 if (arg2->v_type != VAR_STRING) | |
503 { | |
504 if (p_verbose > 2) | |
505 EMSG("E903: received ex command with non-string argument"); | |
506 return; | |
507 } | |
508 arg = arg2->vval.v_string; | |
509 | |
478 if (STRCMP(cmd, "ex") == 0) | 510 if (STRCMP(cmd, "ex") == 0) |
479 { | 511 { |
480 if (arg->v_type == VAR_STRING) | 512 do_cmdline_cmd(arg); |
481 do_cmdline_cmd(arg->vval.v_string); | |
482 else if (p_verbose > 2) | |
483 EMSG("E999: received ex command with non-string argument"); | |
484 } | 513 } |
485 else if (STRCMP(cmd, "normal") == 0) | 514 else if (STRCMP(cmd, "normal") == 0) |
486 { | 515 { |
487 if (arg->v_type == VAR_STRING) | 516 exarg_T ea; |
488 { | 517 |
489 exarg_T ea; | 518 ea.arg = arg; |
490 | 519 ea.addr_count = 0; |
491 ea.arg = arg->vval.v_string; | 520 ea.forceit = TRUE; /* no mapping */ |
492 ea.addr_count = 0; | 521 ex_normal(&ea); |
493 ea.forceit = TRUE; /* no mapping */ | 522 } |
494 ex_normal(&ea); | 523 else if (STRCMP(cmd, "redraw") == 0) |
495 | 524 { |
496 update_screen(0); | 525 exarg_T ea; |
497 showruler(FALSE); | 526 |
498 setcursor(); | 527 ea.forceit = *arg != NUL; |
499 out_flush(); | 528 ex_redraw(&ea); |
529 showruler(FALSE); | |
530 setcursor(); | |
531 out_flush(); | |
500 #ifdef FEAT_GUI | 532 #ifdef FEAT_GUI |
501 if (gui.in_use) | 533 if (gui.in_use) |
534 { | |
535 gui_update_cursor(FALSE, FALSE); | |
536 gui_mch_flush(); | |
537 } | |
538 #endif | |
539 } | |
540 else if (STRCMP(cmd, "expr") == 0 || STRCMP(cmd, "eval") == 0) | |
541 { | |
542 int is_eval = cmd[1] == 'v'; | |
543 | |
544 if (is_eval && arg3->v_type != VAR_NUMBER) | |
545 { | |
546 if (p_verbose > 2) | |
547 EMSG("E904: third argument for eval must be a number"); | |
548 } | |
549 else | |
550 { | |
551 typval_T *tv = eval_expr(arg, NULL); | |
552 typval_T err_tv; | |
553 char_u *json; | |
554 | |
555 if (is_eval) | |
502 { | 556 { |
503 gui_update_cursor(FALSE, FALSE); | 557 if (tv == NULL) |
504 gui_mch_flush(); | 558 { |
559 err_tv.v_type = VAR_STRING; | |
560 err_tv.vval.v_string = (char_u *)"ERROR"; | |
561 tv = &err_tv; | |
562 } | |
563 json = json_encode_nr_expr(arg3->vval.v_number, tv); | |
564 channel_send(idx, json, "eval"); | |
565 vim_free(json); | |
505 } | 566 } |
506 #endif | 567 free_tv(tv); |
507 } | 568 } |
508 else if (p_verbose > 2) | |
509 EMSG("E999: received normal command with non-string argument"); | |
510 } | 569 } |
511 else if (p_verbose > 2) | 570 else if (p_verbose > 2) |
512 EMSG2("E999: received unknown command: %s", cmd); | 571 EMSG2("E905: received unknown command: %s", cmd); |
513 } | 572 } |
514 | 573 |
515 /* | 574 /* |
516 * Invoke a callback for channel "idx" if needed. | 575 * Invoke a callback for channel "idx" if needed. |
517 */ | 576 */ |
519 may_invoke_callback(int idx) | 578 may_invoke_callback(int idx) |
520 { | 579 { |
521 char_u *msg; | 580 char_u *msg; |
522 typval_T typetv; | 581 typval_T typetv; |
523 typval_T argv[3]; | 582 typval_T argv[3]; |
583 typval_T arg3; | |
524 char_u *cmd = NULL; | 584 char_u *cmd = NULL; |
525 int seq_nr = -1; | 585 int seq_nr = -1; |
526 int ret = OK; | 586 int ret = OK; |
527 | 587 |
528 if (channel_peek(idx) == NULL) | 588 if (channel_peek(idx) == NULL) |
535 ; | 595 ; |
536 msg = channel_get(idx); | 596 msg = channel_get(idx); |
537 | 597 |
538 if (channels[idx].ch_json_mode) | 598 if (channels[idx].ch_json_mode) |
539 { | 599 { |
540 ret = channel_decode_json(msg, &typetv, &argv[1]); | 600 ret = channel_decode_json(msg, &typetv, &argv[1], &arg3); |
541 if (ret == OK) | 601 if (ret == OK) |
542 { | 602 { |
603 /* TODO: error if arg3 is set when it shouldn't? */ | |
543 if (typetv.v_type == VAR_STRING) | 604 if (typetv.v_type == VAR_STRING) |
544 cmd = typetv.vval.v_string; | 605 cmd = typetv.vval.v_string; |
545 else if (typetv.v_type == VAR_NUMBER) | 606 else if (typetv.v_type == VAR_NUMBER) |
546 seq_nr = typetv.vval.v_number; | 607 seq_nr = typetv.vval.v_number; |
547 } | 608 } |
554 | 615 |
555 if (ret == OK) | 616 if (ret == OK) |
556 { | 617 { |
557 if (cmd != NULL) | 618 if (cmd != NULL) |
558 { | 619 { |
559 channel_exe_cmd(cmd, &argv[1]); | 620 channel_exe_cmd(idx, cmd, &argv[1], &arg3); |
560 } | 621 } |
561 else if (channels[idx].ch_req_callback != NULL && seq_nr != 0) | 622 else if (channels[idx].ch_req_callback != NULL && seq_nr != 0) |
562 { | 623 { |
563 /* TODO: check the sequence number */ | 624 /* TODO: check the sequence number */ |
564 /* invoke the one-time callback */ | 625 /* invoke the one-time callback */ |
574 | 635 |
575 if (channels[idx].ch_json_mode) | 636 if (channels[idx].ch_json_mode) |
576 { | 637 { |
577 clear_tv(&typetv); | 638 clear_tv(&typetv); |
578 clear_tv(&argv[1]); | 639 clear_tv(&argv[1]); |
640 clear_tv(&arg3); | |
579 } | 641 } |
580 } | 642 } |
581 | 643 |
582 vim_free(msg); | 644 vim_free(msg); |
583 } | 645 } |
872 | 934 |
873 if (len < 0) | 935 if (len < 0) |
874 { | 936 { |
875 /* Todo: which channel? */ | 937 /* Todo: which channel? */ |
876 CHERROR("%s(): cannot from channel\n", "channel_read"); | 938 CHERROR("%s(): cannot from channel\n", "channel_read"); |
877 PERROR(_("E999: read from channel")); | 939 PERROR(_("E896: read from channel")); |
878 } | 940 } |
879 } | 941 } |
880 | 942 |
881 #if defined(CH_HAS_GUI) && defined(FEAT_GUI_GTK) | 943 #if defined(CH_HAS_GUI) && defined(FEAT_GUI_GTK) |
882 if (CH_HAS_GUI && gtk_main_level() > 0) | 944 if (CH_HAS_GUI && gtk_main_level() > 0) |