@@ -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
510519may_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 */
0 commit comments