@@ -2103,6 +2103,18 @@ append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel)
21032103 }
21042104}
21052105
2106+ static void
2107+ drop_messages (channel_T * channel , int part )
2108+ {
2109+ char_u * msg ;
2110+
2111+ while ((msg = channel_get (channel , part )) != NULL )
2112+ {
2113+ ch_logs (channel , "Dropping message '%s'" , (char * )msg );
2114+ vim_free (msg );
2115+ }
2116+ }
2117+
21062118/*
21072119 * Invoke a callback for "channel"/"part" if needed.
21082120 * This does not redraw but sets channel_need_redraw when redraw is needed.
@@ -2202,11 +2214,10 @@ may_invoke_callback(channel_T *channel, int part)
22022214 /* If there is no callback or buffer drop the message. */
22032215 if (callback == NULL && buffer == NULL )
22042216 {
2205- while ((msg = channel_get (channel , part )) != NULL )
2206- {
2207- ch_logs (channel , "Dropping message '%s'" , (char * )msg );
2208- vim_free (msg );
2209- }
2217+ /* If there is a close callback it may use ch_read() to get the
2218+ * messages. */
2219+ if (channel -> ch_close_cb == NULL )
2220+ drop_messages (channel , part );
22102221 return FALSE;
22112222 }
22122223
@@ -2325,16 +2336,46 @@ channel_is_open(channel_T *channel)
23252336 || channel -> CH_ERR_FD != INVALID_FD );
23262337}
23272338
2339+ /*
2340+ * Return TRUE if "channel" has JSON or other typeahead.
2341+ */
2342+ static int
2343+ channel_has_readahead (channel_T * channel , int part )
2344+ {
2345+ ch_mode_T ch_mode = channel -> ch_part [part ].ch_mode ;
2346+
2347+ if (ch_mode == MODE_JSON || ch_mode == MODE_JS )
2348+ {
2349+ jsonq_T * head = & channel -> ch_part [part ].ch_json_head ;
2350+ jsonq_T * item = head -> jq_next ;
2351+
2352+ return item != NULL ;
2353+ }
2354+ return channel_peek (channel , part ) != NULL ;
2355+ }
2356+
23282357/*
23292358 * Return a string indicating the status of the channel.
23302359 */
23312360 char *
23322361channel_status (channel_T * channel )
23332362{
2363+ int part ;
2364+ int has_readahead = FALSE;
2365+
23342366 if (channel == NULL )
23352367 return "fail" ;
23362368 if (channel_is_open (channel ))
23372369 return "open" ;
2370+ for (part = PART_SOCK ; part <= PART_ERR ; ++ part )
2371+ if (channel_has_readahead (channel , part ))
2372+ {
2373+ has_readahead = TRUE;
2374+ break ;
2375+ }
2376+
2377+ if (has_readahead )
2378+ return "buffered" ;
23382379 return "closed" ;
23392380}
23402381
@@ -2458,6 +2499,10 @@ channel_close(channel_T *channel, int invoke_close_cb)
24582499 channel -> ch_close_cb = NULL ;
24592500 partial_unref (channel -> ch_close_partial );
24602501 channel -> ch_close_partial = NULL ;
2502+
2503+ /* any remaining messages are useless now */
2504+ for (part = PART_SOCK ; part <= PART_ERR ; ++ part )
2505+ drop_messages (channel , part );
24612506 }
24622507
24632508 channel -> ch_nb_close_cb = NULL ;
@@ -2967,7 +3012,7 @@ channel_read_json_block(
29673012common_channel_read (typval_T * argvars , typval_T * rettv , int raw )
29683013{
29693014 channel_T * channel ;
2970- int part ;
3015+ int part = -1 ;
29713016 jobopt_T opt ;
29723017 int mode ;
29733018 int timeout ;
@@ -2983,12 +3028,12 @@ common_channel_read(typval_T *argvars, typval_T *rettv, int raw)
29833028 == FAIL )
29843029 goto theend ;
29853030
2986- channel = get_channel_arg (& argvars [0 ], TRUE);
3031+ if (opt .jo_set & JO_PART )
3032+ part = opt .jo_part ;
3033+ channel = get_channel_arg (& argvars [0 ], TRUE, TRUE, part );
29873034 if (channel != NULL )
29883035 {
2989- if (opt .jo_set & JO_PART )
2990- part = opt .jo_part ;
2991- else
3036+ if (part < 0 )
29923037 part = channel_part_read (channel );
29933038 mode = channel_get_mode (channel , part );
29943039 timeout = channel_get_timeout (channel , part );
@@ -3152,7 +3197,7 @@ send_common(
31523197 int part_send ;
31533198
31543199 clear_job_options (opt );
3155- channel = get_channel_arg (& argvars [0 ], TRUE);
3200+ channel = get_channel_arg (& argvars [0 ], TRUE, FALSE, 0 );
31563201 if (channel == NULL )
31573202 return NULL ;
31583203 part_send = channel_part_send (channel );
@@ -3201,7 +3246,7 @@ ch_expr_common(typval_T *argvars, typval_T *rettv, int eval)
32013246 rettv -> v_type = VAR_STRING ;
32023247 rettv -> vval .v_string = NULL ;
32033248
3204- channel = get_channel_arg (& argvars [0 ], TRUE);
3249+ channel = get_channel_arg (& argvars [0 ], TRUE, FALSE, 0 );
32053250 if (channel == NULL )
32063251 return ;
32073252 part_send = channel_part_send (channel );
@@ -3434,24 +3479,6 @@ channel_select_check(int ret_in, void *rfds_in, void *wfds_in)
34343479}
34353480# endif /* !WIN32 && HAVE_SELECT */
34363481
3437- /*
3438- * Return TRUE if "channel" has JSON or other typeahead.
3439- */
3440- static int
3441- channel_has_readahead (channel_T * channel , int part )
3442- {
3443- ch_mode_T ch_mode = channel -> ch_part [part ].ch_mode ;
3444-
3445- if (ch_mode == MODE_JSON || ch_mode == MODE_JS )
3446- {
3447- jsonq_T * head = & channel -> ch_part [part ].ch_json_head ;
3448- jsonq_T * item = head -> jq_next ;
3449-
3450- return item != NULL ;
3451- }
3452- return channel_peek (channel , part ) != NULL ;
3453- }
3454-
34553482/*
34563483 * Execute queued up commands.
34573484 * Invoked from the main loop when it's safe to execute received commands.
@@ -3968,11 +3995,15 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported)
39683995/*
39693996 * Get the channel from the argument.
39703997 * Returns NULL if the handle is invalid.
3998+ * When "check_open" is TRUE check that the channel can be used.
3999+ * When "reading" is TRUE "check_open" considers typeahead useful.
4000+ * "part" is used to check typeahead, when -1 use the default part.
39714001 */
39724002 channel_T *
3973- get_channel_arg (typval_T * tv , int check_open )
4003+ get_channel_arg (typval_T * tv , int check_open , int reading , int part )
39744004{
3975- channel_T * channel = NULL ;
4005+ channel_T * channel = NULL ;
4006+ int has_readahead = FALSE;
39764007
39774008 if (tv -> v_type == VAR_JOB )
39784009 {
@@ -3988,8 +4019,12 @@ get_channel_arg(typval_T *tv, int check_open)
39884019 EMSG2 (_ (e_invarg2 ), get_tv_string (tv ));
39894020 return NULL ;
39904021 }
4022+ if (channel != NULL && reading )
4023+ has_readahead = channel_has_readahead (channel ,
4024+ part >= 0 ? part : channel_part_read (channel ));
39914025
3992- if (check_open && (channel == NULL || !channel_is_open (channel )))
4026+ if (check_open && (channel == NULL || (!channel_is_open (channel )
4027+ && !(reading && has_readahead ))))
39934028 {
39944029 EMSG (_ ("E906: not an open channel" ));
39954030 return NULL ;
0 commit comments