Skip to content

Commit 20fb9f3

Browse files
committed
patch 7.4.1217
Problem: Execution of command on channel doesn't work yet. Solution: Implement the "ex" and "normal" commands.
1 parent ba4ef27 commit 20fb9f3

8 files changed

Lines changed: 135 additions & 68 deletions

File tree

src/channel.c

Lines changed: 120 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ typedef struct {
9999

100100
char_u *ch_callback; /* function to call when a msg is not handled */
101101
char_u *ch_req_callback; /* function to call for current request */
102-
int ch_will_block; /* do not use callback right now */
103102

104103
int ch_json_mode;
105104
} channel_T;
@@ -419,21 +418,13 @@ channel_set_req_callback(int idx, char_u *callback)
419418
}
420419

421420
/*
422-
* Set the flag that the callback for channel "idx" should not be used now.
423-
*/
424-
void
425-
channel_will_block(int idx)
426-
{
427-
channels[idx].ch_will_block = TRUE;
428-
}
429-
430-
/*
431-
* Decode JSON "msg", which must have the form "[nr, expr]".
432-
* Put "expr" in "tv".
421+
* Decode JSON "msg", which must have the form "[expr1, expr2]".
422+
* Put "expr1" in "tv1".
423+
* Put "expr2" in "tv2".
433424
* Return OK or FAIL.
434425
*/
435426
int
436-
channel_decode_json(char_u *msg, typval_T *tv)
427+
channel_decode_json(char_u *msg, typval_T *tv1, typval_T *tv2)
437428
{
438429
js_read_T reader;
439430
typval_T listtv;
@@ -442,14 +433,14 @@ channel_decode_json(char_u *msg, typval_T *tv)
442433
reader.js_eof = TRUE;
443434
reader.js_used = 0;
444435
json_decode(&reader, &listtv);
445-
/* TODO: use the sequence number */
446-
if (listtv.v_type == VAR_LIST
447-
&& listtv.vval.v_list->lv_len == 2
448-
&& listtv.vval.v_list->lv_first->li_tv.v_type == VAR_NUMBER)
436+
437+
if (listtv.v_type == VAR_LIST && listtv.vval.v_list->lv_len == 2)
449438
{
450439
/* Move the item from the list and then change the type to avoid the
451440
* item being freed. */
452-
*tv = listtv.vval.v_list->lv_last->li_tv;
441+
*tv1 = listtv.vval.v_list->lv_first->li_tv;
442+
listtv.vval.v_list->lv_first->li_tv.v_type = VAR_NUMBER;
443+
*tv2 = listtv.vval.v_list->lv_last->li_tv;
453444
listtv.vval.v_list->lv_last->li_tv.v_type = VAR_NUMBER;
454445
list_unref(listtv.vval.v_list);
455446
return OK;
@@ -464,43 +455,61 @@ channel_decode_json(char_u *msg, typval_T *tv)
464455
* Invoke the "callback" on channel "idx".
465456
*/
466457
static void
467-
invoke_callback(int idx, char_u *callback)
458+
invoke_callback(int idx, char_u *callback, typval_T *argv)
468459
{
469-
typval_T argv[3];
470460
typval_T rettv;
471461
int dummy;
472-
char_u *msg;
473-
int ret = OK;
474462

475463
argv[0].v_type = VAR_NUMBER;
476464
argv[0].vval.v_number = idx;
477465

478-
/* Concatenate everything into one buffer.
479-
* TODO: only read what the callback will use.
480-
* TODO: avoid multiple allocations. */
481-
while (channel_collapse(idx) == OK)
482-
;
483-
msg = channel_get(idx);
466+
call_func(callback, (int)STRLEN(callback),
467+
&rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL);
468+
/* If an echo command was used the cursor needs to be put back where
469+
* it belongs. */
470+
setcursor();
471+
cursor_on();
472+
out_flush();
473+
}
484474

485-
if (channels[idx].ch_json_mode)
486-
ret = channel_decode_json(msg, &argv[1]);
487-
else
475+
static void
476+
channel_exe_cmd(char_u *cmd, typval_T *arg)
477+
{
478+
if (STRCMP(cmd, "ex") == 0)
488479
{
489-
argv[1].v_type = VAR_STRING;
490-
argv[1].vval.v_string = msg;
480+
if (arg->v_type == VAR_STRING)
481+
do_cmdline_cmd(arg->vval.v_string);
482+
else if (p_verbose > 2)
483+
EMSG("E999: received ex command with non-string argument");
491484
}
492-
493-
if (ret == OK)
485+
else if (STRCMP(cmd, "normal") == 0)
494486
{
495-
call_func(callback, (int)STRLEN(callback),
496-
&rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL);
497-
/* If an echo command was used the cursor needs to be put back where
498-
* it belongs. */
499-
setcursor();
500-
cursor_on();
501-
out_flush();
487+
if (arg->v_type == VAR_STRING)
488+
{
489+
exarg_T ea;
490+
491+
ea.arg = arg->vval.v_string;
492+
ea.addr_count = 0;
493+
ea.forceit = TRUE; /* no mapping */
494+
ex_normal(&ea);
495+
496+
update_screen(0);
497+
showruler(FALSE);
498+
setcursor();
499+
out_flush();
500+
#ifdef FEAT_GUI
501+
if (gui.in_use)
502+
{
503+
gui_update_cursor(FALSE, FALSE);
504+
gui_mch_flush();
505+
}
506+
#endif
507+
}
508+
else if (p_verbose > 2)
509+
EMSG("E999: received normal command with non-string argument");
502510
}
503-
vim_free(msg);
511+
else if (p_verbose > 2)
512+
EMSG2("E999: received unknown command: %s", cmd);
504513
}
505514

506515
/*
@@ -509,22 +518,68 @@ invoke_callback(int idx, char_u *callback)
509518
static void
510519
may_invoke_callback(int idx)
511520
{
512-
if (channels[idx].ch_will_block)
513-
return;
521+
char_u *msg;
522+
typval_T typetv;
523+
typval_T argv[3];
524+
char_u *cmd = NULL;
525+
int seq_nr = -1;
526+
int ret = OK;
527+
514528
if (channel_peek(idx) == NULL)
515529
return;
516530

517-
if (channels[idx].ch_req_callback != NULL)
531+
/* Concatenate everything into one buffer.
532+
* TODO: only read what the callback will use.
533+
* TODO: avoid multiple allocations. */
534+
while (channel_collapse(idx) == OK)
535+
;
536+
msg = channel_get(idx);
537+
538+
if (channels[idx].ch_json_mode)
518539
{
519-
/* invoke the one-time callback */
520-
invoke_callback(idx, channels[idx].ch_req_callback);
521-
channels[idx].ch_req_callback = NULL;
522-
return;
540+
ret = channel_decode_json(msg, &typetv, &argv[1]);
541+
if (ret == OK)
542+
{
543+
if (typetv.v_type == VAR_STRING)
544+
cmd = typetv.vval.v_string;
545+
else if (typetv.v_type == VAR_NUMBER)
546+
seq_nr = typetv.vval.v_number;
547+
}
548+
}
549+
else
550+
{
551+
argv[1].v_type = VAR_STRING;
552+
argv[1].vval.v_string = msg;
553+
}
554+
555+
if (ret == OK)
556+
{
557+
if (cmd != NULL)
558+
{
559+
channel_exe_cmd(cmd, &argv[1]);
560+
}
561+
else if (channels[idx].ch_req_callback != NULL && seq_nr != 0)
562+
{
563+
/* TODO: check the sequence number */
564+
/* invoke the one-time callback */
565+
invoke_callback(idx, channels[idx].ch_req_callback, argv);
566+
channels[idx].ch_req_callback = NULL;
567+
}
568+
else if (channels[idx].ch_callback != NULL)
569+
{
570+
/* invoke the channel callback */
571+
invoke_callback(idx, channels[idx].ch_callback, argv);
572+
}
573+
/* else: drop the message */
574+
575+
if (channels[idx].ch_json_mode)
576+
{
577+
clear_tv(&typetv);
578+
clear_tv(&argv[1]);
579+
}
523580
}
524581

525-
if (channels[idx].ch_callback != NULL)
526-
/* invoke the channel callback */
527-
invoke_callback(idx, channels[idx].ch_callback);
582+
vim_free(msg);
528583
}
529584

530585
/*
@@ -823,8 +878,6 @@ channel_read(int idx)
823878
}
824879
}
825880

826-
may_invoke_callback(idx);
827-
828881
#if defined(CH_HAS_GUI) && defined(FEAT_GUI_GTK)
829882
if (CH_HAS_GUI && gtk_main_level() > 0)
830883
gtk_main_quit();
@@ -845,10 +898,7 @@ channel_read_block(int idx)
845898
/* Wait for up to 2 seconds.
846899
* TODO: use timeout set on the channel. */
847900
if (channel_wait(channels[idx].ch_fd, 2000) == FAIL)
848-
{
849-
channels[idx].ch_will_block = FALSE;
850901
return NULL;
851-
}
852902
channel_read(idx);
853903
}
854904

@@ -857,7 +907,6 @@ channel_read_block(int idx)
857907
while (channel_collapse(idx) == OK)
858908
;
859909

860-
channels[idx].ch_will_block = FALSE;
861910
return channel_get(idx);
862911
}
863912

@@ -1009,4 +1058,16 @@ channel_select_check(int ret_in, void *rfds_in)
10091058
}
10101059
# endif /* !FEAT_GUI_W32 && HAVE_SELECT */
10111060

1061+
/*
1062+
* Invoked from the main loop when it's save to execute received commands.
1063+
*/
1064+
void
1065+
channel_parse_messages(void)
1066+
{
1067+
int i;
1068+
1069+
for (i = 0; i < channel_count; ++i)
1070+
may_invoke_callback(i);
1071+
}
1072+
10121073
#endif /* FEAT_CHANNEL */

src/eval.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16889,8 +16889,6 @@ send_common(typval_T *argvars, char_u *text, char *fun)
1688916889
* not reading the response. */
1689016890
channel_set_req_callback(ch_idx,
1689116891
callback != NULL && *callback == NUL ? NULL : callback);
16892-
if (callback == NULL)
16893-
channel_will_block(ch_idx);
1689416892

1689516893
if (channel_send(ch_idx, text, fun) == OK && callback == NULL)
1689616894
return ch_idx;
@@ -16907,6 +16905,7 @@ f_sendexpr(typval_T *argvars, typval_T *rettv)
1690716905
char_u *resp;
1690816906
typval_T nrtv;
1690916907
typval_T listtv;
16908+
typval_T typetv;
1691016909
int ch_idx;
1691116910

1691216911
/* return an empty string by default */
@@ -16932,10 +16931,11 @@ f_sendexpr(typval_T *argvars, typval_T *rettv)
1693216931
{
1693316932
/* TODO: read until the whole JSON message is received */
1693416933
/* TODO: only use the message with the right message ID */
16934+
/* TODO: check sequence number */
1693516935
resp = channel_read_block(ch_idx);
1693616936
if (resp != NULL)
1693716937
{
16938-
channel_decode_json(resp, rettv);
16938+
channel_decode_json(resp, &typetv, rettv);
1693916939
vim_free(resp);
1694016940
}
1694116941
}

src/ex_docmd.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,6 @@ static char_u *uc_fun_cmd(void);
345345
static char_u *find_ucmd(exarg_T *eap, char_u *p, int *full, expand_T *xp, int *compl);
346346
#endif
347347
#ifdef FEAT_EX_EXTRA
348-
static void ex_normal(exarg_T *eap);
349348
static void ex_startinsert(exarg_T *eap);
350349
static void ex_stopinsert(exarg_T *eap);
351350
#else
@@ -9861,11 +9860,11 @@ update_topline_cursor(void)
98619860
update_curswant();
98629861
}
98639862

9864-
#ifdef FEAT_EX_EXTRA
9863+
#if defined(FEAT_EX_EXTRA) || defined(PROTO)
98659864
/*
98669865
* ":normal[!] {commands}": Execute normal mode commands.
98679866
*/
9868-
static void
9867+
void
98699868
ex_normal(exarg_T *eap)
98709869
{
98719870
int save_msg_scroll = msg_scroll;

src/feature.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@
256256
/*
257257
* +ex_extra ":retab", ":right", ":left", ":center", ":normal".
258258
*/
259-
#ifdef FEAT_NORMAL
259+
#if defined(FEAT_NORMAL) || defined(FEAT_CHANNEL)
260260
# define FEAT_EX_EXTRA
261261
#endif
262262

src/misc2.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6240,6 +6240,10 @@ parse_queued_messages(void)
62406240
/* Process the queued netbeans messages. */
62416241
netbeans_parse_messages();
62426242
# endif
6243+
# ifdef FEAT_CHANNEL
6244+
/* Process the messages queued on channels. */
6245+
channel_parse_messages();
6246+
# endif
62436247
# if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
62446248
/* Process the queued clientserver messages. */
62456249
server_parse_messages();

src/proto/channel.pro

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ int channel_open(char *hostname, int port_in, void (*close_cb)(void));
44
void channel_set_json_mode(int idx, int json_mode);
55
void channel_set_callback(int idx, char_u *callback);
66
void channel_set_req_callback(int idx, char_u *callback);
7-
void channel_will_block(int idx);
8-
int channel_decode_json(char_u *msg, typval_T *tv);
7+
int channel_decode_json(char_u *msg, typval_T *tv1, typval_T *tv2);
98
int channel_is_open(int idx);
109
void channel_close(int idx);
1110
int channel_save(int idx, char_u *buf, int len);
@@ -22,4 +21,5 @@ int channel_poll_setup(int nfd_in, void *fds_in);
2221
int channel_poll_check(int ret_in, void *fds_in);
2322
int channel_select_setup(int maxfd_in, void *rfds_in);
2423
int channel_select_check(int ret_in, void *rfds_in);
24+
void channel_parse_messages(void);
2525
/* vim: set ft=c : */

src/proto/ex_docmd.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ void ex_may_print(exarg_T *eap);
4949
int vim_mkdir_emsg(char_u *name, int prot);
5050
FILE *open_exfile(char_u *fname, int forceit, char *mode);
5151
void update_topline_cursor(void);
52+
void ex_normal(exarg_T *eap);
5253
void exec_normal_cmd(char_u *cmd, int remap, int silent);
5354
void exec_normal(int was_typed);
5455
int find_cmdline_var(char_u *src, int *usedlen);

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,8 @@ static char *(features[]) =
746746

747747
static int included_patches[] =
748748
{ /* Add new patch number below this line */
749+
/**/
750+
1217,
749751
/**/
750752
1216,
751753
/**/

0 commit comments

Comments
 (0)