To: vim_dev@googlegroups.com Subject: Patch 7.4.1217 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.1217 Problem: Execution of command on channel doesn't work yet. Solution: Implement the "ex" and "normal" commands. Files: src/channel.c, src/proto/channel.pro, src/misc2.c, src/eval.c, src/ex_docmd.c, src/proto/ex_docmd.pro, src/feature.h *** ../vim-7.4.1216/src/channel.c 2016-01-30 15:14:02.531448995 +0100 --- src/channel.c 2016-01-30 23:15:14.938436609 +0100 *************** *** 99,105 **** char_u *ch_callback; /* function to call when a msg is not handled */ char_u *ch_req_callback; /* function to call for current request */ - int ch_will_block; /* do not use callback right now */ int ch_json_mode; } channel_T; --- 99,104 ---- *************** *** 419,439 **** } /* ! * Set the flag that the callback for channel "idx" should not be used now. ! */ ! void ! channel_will_block(int idx) ! { ! channels[idx].ch_will_block = TRUE; ! } ! ! /* ! * Decode JSON "msg", which must have the form "[nr, expr]". ! * Put "expr" in "tv". * Return OK or FAIL. */ int ! channel_decode_json(char_u *msg, typval_T *tv) { js_read_T reader; typval_T listtv; --- 418,430 ---- } /* ! * Decode JSON "msg", which must have the form "[expr1, expr2]". ! * Put "expr1" in "tv1". ! * Put "expr2" in "tv2". * Return OK or FAIL. */ int ! channel_decode_json(char_u *msg, typval_T *tv1, typval_T *tv2) { js_read_T reader; typval_T listtv; *************** *** 442,455 **** reader.js_eof = TRUE; reader.js_used = 0; json_decode(&reader, &listtv); ! /* TODO: use the sequence number */ ! if (listtv.v_type == VAR_LIST ! && listtv.vval.v_list->lv_len == 2 ! && listtv.vval.v_list->lv_first->li_tv.v_type == VAR_NUMBER) { /* Move the item from the list and then change the type to avoid the * item being freed. */ ! *tv = listtv.vval.v_list->lv_last->li_tv; listtv.vval.v_list->lv_last->li_tv.v_type = VAR_NUMBER; list_unref(listtv.vval.v_list); return OK; --- 433,446 ---- reader.js_eof = TRUE; reader.js_used = 0; json_decode(&reader, &listtv); ! ! if (listtv.v_type == VAR_LIST && listtv.vval.v_list->lv_len == 2) { /* Move the item from the list and then change the type to avoid the * item being freed. */ ! *tv1 = listtv.vval.v_list->lv_first->li_tv; ! listtv.vval.v_list->lv_first->li_tv.v_type = VAR_NUMBER; ! *tv2 = listtv.vval.v_list->lv_last->li_tv; listtv.vval.v_list->lv_last->li_tv.v_type = VAR_NUMBER; list_unref(listtv.vval.v_list); return OK; *************** *** 464,506 **** * Invoke the "callback" on channel "idx". */ static void ! invoke_callback(int idx, char_u *callback) { - typval_T argv[3]; typval_T rettv; int dummy; - char_u *msg; - int ret = OK; argv[0].v_type = VAR_NUMBER; argv[0].vval.v_number = idx; ! /* Concatenate everything into one buffer. ! * TODO: only read what the callback will use. ! * TODO: avoid multiple allocations. */ ! while (channel_collapse(idx) == OK) ! ; ! msg = channel_get(idx); ! if (channels[idx].ch_json_mode) ! ret = channel_decode_json(msg, &argv[1]); ! else { ! argv[1].v_type = VAR_STRING; ! argv[1].vval.v_string = msg; } ! ! if (ret == OK) { ! call_func(callback, (int)STRLEN(callback), ! &rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL); ! /* If an echo command was used the cursor needs to be put back where ! * it belongs. */ ! setcursor(); ! cursor_on(); ! out_flush(); } ! vim_free(msg); } /* --- 455,515 ---- * Invoke the "callback" on channel "idx". */ static void ! invoke_callback(int idx, char_u *callback, typval_T *argv) { typval_T rettv; int dummy; argv[0].v_type = VAR_NUMBER; argv[0].vval.v_number = idx; ! call_func(callback, (int)STRLEN(callback), ! &rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL); ! /* If an echo command was used the cursor needs to be put back where ! * it belongs. */ ! setcursor(); ! cursor_on(); ! out_flush(); ! } ! static void ! channel_exe_cmd(char_u *cmd, typval_T *arg) ! { ! if (STRCMP(cmd, "ex") == 0) { ! if (arg->v_type == VAR_STRING) ! do_cmdline_cmd(arg->vval.v_string); ! else if (p_verbose > 2) ! EMSG("E999: received ex command with non-string argument"); } ! else if (STRCMP(cmd, "normal") == 0) { ! if (arg->v_type == VAR_STRING) ! { ! exarg_T ea; ! ! ea.arg = arg->vval.v_string; ! ea.addr_count = 0; ! ea.forceit = TRUE; /* no mapping */ ! ex_normal(&ea); ! ! update_screen(0); ! showruler(FALSE); ! setcursor(); ! out_flush(); ! #ifdef FEAT_GUI ! if (gui.in_use) ! { ! gui_update_cursor(FALSE, FALSE); ! gui_mch_flush(); ! } ! #endif ! } ! else if (p_verbose > 2) ! EMSG("E999: received normal command with non-string argument"); } ! else if (p_verbose > 2) ! EMSG2("E999: received unknown command: %s", cmd); } /* *************** *** 509,530 **** static void may_invoke_callback(int idx) { ! if (channels[idx].ch_will_block) ! return; if (channel_peek(idx) == NULL) return; ! if (channels[idx].ch_req_callback != NULL) { ! /* invoke the one-time callback */ ! invoke_callback(idx, channels[idx].ch_req_callback); ! channels[idx].ch_req_callback = NULL; ! return; } ! if (channels[idx].ch_callback != NULL) ! /* invoke the channel callback */ ! invoke_callback(idx, channels[idx].ch_callback); } /* --- 518,585 ---- static void may_invoke_callback(int idx) { ! char_u *msg; ! typval_T typetv; ! typval_T argv[3]; ! char_u *cmd = NULL; ! int seq_nr = -1; ! int ret = OK; ! if (channel_peek(idx) == NULL) return; ! /* Concatenate everything into one buffer. ! * TODO: only read what the callback will use. ! * TODO: avoid multiple allocations. */ ! while (channel_collapse(idx) == OK) ! ; ! msg = channel_get(idx); ! ! if (channels[idx].ch_json_mode) { ! ret = channel_decode_json(msg, &typetv, &argv[1]); ! if (ret == OK) ! { ! if (typetv.v_type == VAR_STRING) ! cmd = typetv.vval.v_string; ! else if (typetv.v_type == VAR_NUMBER) ! seq_nr = typetv.vval.v_number; ! } ! } ! else ! { ! argv[1].v_type = VAR_STRING; ! argv[1].vval.v_string = msg; ! } ! ! if (ret == OK) ! { ! if (cmd != NULL) ! { ! channel_exe_cmd(cmd, &argv[1]); ! } ! else if (channels[idx].ch_req_callback != NULL && seq_nr != 0) ! { ! /* TODO: check the sequence number */ ! /* invoke the one-time callback */ ! invoke_callback(idx, channels[idx].ch_req_callback, argv); ! channels[idx].ch_req_callback = NULL; ! } ! else if (channels[idx].ch_callback != NULL) ! { ! /* invoke the channel callback */ ! invoke_callback(idx, channels[idx].ch_callback, argv); ! } ! /* else: drop the message */ ! ! if (channels[idx].ch_json_mode) ! { ! clear_tv(&typetv); ! clear_tv(&argv[1]); ! } } ! vim_free(msg); } /* *************** *** 823,830 **** } } - may_invoke_callback(idx); - #if defined(CH_HAS_GUI) && defined(FEAT_GUI_GTK) if (CH_HAS_GUI && gtk_main_level() > 0) gtk_main_quit(); --- 878,883 ---- *************** *** 845,854 **** /* Wait for up to 2 seconds. * TODO: use timeout set on the channel. */ if (channel_wait(channels[idx].ch_fd, 2000) == FAIL) - { - channels[idx].ch_will_block = FALSE; return NULL; - } channel_read(idx); } --- 898,904 ---- *************** *** 857,863 **** while (channel_collapse(idx) == OK) ; - channels[idx].ch_will_block = FALSE; return channel_get(idx); } --- 907,912 ---- *************** *** 1009,1012 **** --- 1058,1073 ---- } # endif /* !FEAT_GUI_W32 && HAVE_SELECT */ + /* + * Invoked from the main loop when it's save to execute received commands. + */ + void + channel_parse_messages(void) + { + int i; + + for (i = 0; i < channel_count; ++i) + may_invoke_callback(i); + } + #endif /* FEAT_CHANNEL */ *** ../vim-7.4.1216/src/proto/channel.pro 2016-01-28 23:10:03.222681092 +0100 --- src/proto/channel.pro 2016-01-30 22:40:03.888643308 +0100 *************** *** 4,11 **** void channel_set_json_mode(int idx, int json_mode); void channel_set_callback(int idx, char_u *callback); void channel_set_req_callback(int idx, char_u *callback); ! void channel_will_block(int idx); ! int channel_decode_json(char_u *msg, typval_T *tv); int channel_is_open(int idx); void channel_close(int idx); int channel_save(int idx, char_u *buf, int len); --- 4,10 ---- void channel_set_json_mode(int idx, int json_mode); void channel_set_callback(int idx, char_u *callback); void channel_set_req_callback(int idx, char_u *callback); ! int channel_decode_json(char_u *msg, typval_T *tv1, typval_T *tv2); int channel_is_open(int idx); void channel_close(int idx); int channel_save(int idx, char_u *buf, int len); *************** *** 22,25 **** --- 21,25 ---- int channel_poll_check(int ret_in, void *fds_in); int channel_select_setup(int maxfd_in, void *rfds_in); int channel_select_check(int ret_in, void *rfds_in); + void channel_parse_messages(void); /* vim: set ft=c : */ *** ../vim-7.4.1216/src/misc2.c 2016-01-30 21:48:44.325034448 +0100 --- src/misc2.c 2016-01-30 23:19:59.087450391 +0100 *************** *** 6240,6245 **** --- 6240,6249 ---- /* Process the queued netbeans messages. */ netbeans_parse_messages(); # endif + # ifdef FEAT_CHANNEL + /* Process the messages queued on channels. */ + channel_parse_messages(); + # endif # if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11) /* Process the queued clientserver messages. */ server_parse_messages(); *** ../vim-7.4.1216/src/eval.c 2016-01-30 21:48:44.325034448 +0100 --- src/eval.c 2016-01-30 22:39:37.324922720 +0100 *************** *** 16889,16896 **** * not reading the response. */ channel_set_req_callback(ch_idx, callback != NULL && *callback == NUL ? NULL : callback); - if (callback == NULL) - channel_will_block(ch_idx); if (channel_send(ch_idx, text, fun) == OK && callback == NULL) return ch_idx; --- 16889,16894 ---- *************** *** 16907,16912 **** --- 16905,16911 ---- char_u *resp; typval_T nrtv; typval_T listtv; + typval_T typetv; int ch_idx; /* return an empty string by default */ *************** *** 16932,16941 **** { /* TODO: read until the whole JSON message is received */ /* TODO: only use the message with the right message ID */ resp = channel_read_block(ch_idx); if (resp != NULL) { ! channel_decode_json(resp, rettv); vim_free(resp); } } --- 16931,16941 ---- { /* TODO: read until the whole JSON message is received */ /* TODO: only use the message with the right message ID */ + /* TODO: check sequence number */ resp = channel_read_block(ch_idx); if (resp != NULL) { ! channel_decode_json(resp, &typetv, rettv); vim_free(resp); } } *** ../vim-7.4.1216/src/ex_docmd.c 2016-01-30 15:52:42.571439521 +0100 --- src/ex_docmd.c 2016-01-30 23:00:16.915878734 +0100 *************** *** 345,351 **** static char_u *find_ucmd(exarg_T *eap, char_u *p, int *full, expand_T *xp, int *compl); #endif #ifdef FEAT_EX_EXTRA - static void ex_normal(exarg_T *eap); static void ex_startinsert(exarg_T *eap); static void ex_stopinsert(exarg_T *eap); #else --- 345,350 ---- *************** *** 9861,9871 **** update_curswant(); } ! #ifdef FEAT_EX_EXTRA /* * ":normal[!] {commands}": Execute normal mode commands. */ ! static void ex_normal(exarg_T *eap) { int save_msg_scroll = msg_scroll; --- 9860,9870 ---- update_curswant(); } ! #if defined(FEAT_EX_EXTRA) || defined(PROTO) /* * ":normal[!] {commands}": Execute normal mode commands. */ ! void ex_normal(exarg_T *eap) { int save_msg_scroll = msg_scroll; *** ../vim-7.4.1216/src/proto/ex_docmd.pro 2016-01-21 23:32:14.154035915 +0100 --- src/proto/ex_docmd.pro 2016-01-30 23:00:19.575850748 +0100 *************** *** 49,54 **** --- 49,55 ---- int vim_mkdir_emsg(char_u *name, int prot); FILE *open_exfile(char_u *fname, int forceit, char *mode); void update_topline_cursor(void); + void ex_normal(exarg_T *eap); void exec_normal_cmd(char_u *cmd, int remap, int silent); void exec_normal(int was_typed); int find_cmdline_var(char_u *src, int *usedlen); *** ../vim-7.4.1216/src/feature.h 2016-01-24 20:36:18.862082391 +0100 --- src/feature.h 2016-01-30 22:55:37.378820167 +0100 *************** *** 256,262 **** /* * +ex_extra ":retab", ":right", ":left", ":center", ":normal". */ ! #ifdef FEAT_NORMAL # define FEAT_EX_EXTRA #endif --- 256,262 ---- /* * +ex_extra ":retab", ":right", ":left", ":center", ":normal". */ ! #if defined(FEAT_NORMAL) || defined(FEAT_CHANNEL) # define FEAT_EX_EXTRA #endif *** ../vim-7.4.1216/src/version.c 2016-01-30 21:48:44.329034406 +0100 --- src/version.c 2016-01-30 22:35:23.823589506 +0100 *************** *** 748,749 **** --- 748,751 ---- { /* Add new patch number below this line */ + /**/ + 1217, /**/ -- From "know your smileys": (:-# Said something he shouldn't have /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///