Patch 7.4.1356
Problem:    Job and channel options parsing is scattered.
Solution:   Move all option value parsing to get_job_options();
Files:      src/channel.c, src/eval.c, src/structs.h, src/proto/channel.pro,
            src/testdir/test_channel.vim


*** ../vim-7.4.1355/src/channel.c       2016-02-19 21:04:57.896318285 +0100
--- src/channel.c       2016-02-19 22:05:41.829863314 +0100
***************
*** 749,772 ****
  }
  
  /*
-  * Set the mode of channel "channel" to "mode".
-  */
-     void
- channel_set_mode(channel_T *channel, ch_mode_T mode)
- {
-     channel->ch_mode = mode;
- }
- 
- /*
-  * Set the read timeout of channel "channel".
-  */
-     void
- channel_set_timeout(channel_T *channel, int timeout)
- {
-     channel->ch_timeout = timeout;
- }
- 
- /*
   * Set the callback for channel "channel".
   */
      void
--- 749,754 ----
***************
*** 782,790 ****
      void
  channel_set_options(channel_T *channel, jobopt_T *options)
  {
!     channel_set_mode(channel, options->jo_mode);
  
!     if (options->jo_callback != NULL && *options->jo_callback != NUL)
        channel_set_callback(channel, options->jo_callback);
  }
  
--- 764,776 ----
      void
  channel_set_options(channel_T *channel, jobopt_T *options)
  {
!     if (options->jo_set & JO_MODE)
!       channel->ch_mode = options->jo_mode;
!     if (options->jo_set & JO_TIMEOUT)
!       channel->ch_timeout = options->jo_timeout;
  
!     if ((options->jo_set & JO_CALLBACK)
!           && options->jo_callback != NULL && *options->jo_callback != NUL)
        channel_set_callback(channel, options->jo_callback);
  }
  
*** ../vim-7.4.1355/src/eval.c  2016-02-19 21:04:57.900318243 +0100
--- src/eval.c  2016-02-19 22:29:48.730609433 +0100
***************
*** 510,515 ****
--- 510,516 ----
  static void f_ch_readraw(typval_T *argvars, typval_T *rettv);
  static void f_ch_sendexpr(typval_T *argvars, typval_T *rettv);
  static void f_ch_sendraw(typval_T *argvars, typval_T *rettv);
+ static void f_ch_setoptions(typval_T *argvars, typval_T *rettv);
  static void f_ch_status(typval_T *argvars, typval_T *rettv);
  #endif
  static void f_changenr(typval_T *argvars, typval_T *rettv);
***************
*** 8131,8136 ****
--- 8132,8138 ----
      {"ch_readraw",    1, 2, f_ch_readraw},
      {"ch_sendexpr",   2, 3, f_ch_sendexpr},
      {"ch_sendraw",    2, 3, f_ch_sendraw},
+     {"ch_setoptions", 2, 2, f_ch_setoptions},
      {"ch_status",     1, 1, f_ch_status},
  #endif
      {"changenr",      0, 0, f_changenr},
***************
*** 9870,9913 ****
  }
  
  /*
!  * Get the option entries from "dict", and parse them.
   * If an option value is invalid return FAIL.
   */
      static int
! get_job_options(dict_T *dict, jobopt_T *opt)
  {
!     dictitem_T        *item;
      char_u    *mode;
  
!     if (dict == NULL)
        return OK;
! 
!     if ((item = dict_find(dict, (char_u *)"mode", -1)) != NULL)
      {
!       mode = get_tv_string(&item->di_tv);
!       if (STRCMP(mode, "nl") == 0)
!           opt->jo_mode = MODE_NL;
!       else if (STRCMP(mode, "raw") == 0)
!           opt->jo_mode = MODE_RAW;
!       else if (STRCMP(mode, "js") == 0)
!           opt->jo_mode = MODE_JS;
!       else if (STRCMP(mode, "json") == 0)
!           opt->jo_mode = MODE_JSON;
!       else
!       {
!           EMSG2(_(e_invarg2), mode);
!           return FAIL;
!       }
      }
  
!     if ((item = dict_find(dict, (char_u *)"callback", -1)) != NULL)
!     {
!       opt->jo_callback = get_callback(&item->di_tv);
!       if (opt->jo_callback == NULL)
        {
!           EMSG2(_(e_invarg2), "callback");
!           return FAIL;
        }
      }
  
      return OK;
--- 9872,9962 ----
  }
  
  /*
!  * Get the option entries from the dict in "tv", parse them and put the result
!  * in "opt".
!  * Only accept options in "supported".
   * If an option value is invalid return FAIL.
   */
      static int
! get_job_options(typval_T *tv, jobopt_T *opt, int supported)
  {
!     typval_T  *item;
      char_u    *mode;
+     dict_T    *dict;
+     int               todo;
+     hashitem_T        *hi;
  
!     if (tv->v_type == VAR_UNKNOWN)
        return OK;
!     if (tv->v_type != VAR_DICT)
      {
!       EMSG(_(e_invarg));
!       return FAIL;
      }
+     dict = tv->vval.v_dict;
+     if (dict == NULL)
+       return OK;
  
!     todo = (int)dict->dv_hashtab.ht_used;
!     for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi)
!       if (!HASHITEM_EMPTY(hi))
        {
!           item = &HI2DI(hi)->di_tv;
! 
!           if (STRCMP(hi->hi_key, "mode") == 0)
!           {
!               if (!(supported & JO_MODE))
!                   break;
!               opt->jo_set |= JO_MODE;
!               mode = get_tv_string(item);
!               if (STRCMP(mode, "nl") == 0)
!                   opt->jo_mode = MODE_NL;
!               else if (STRCMP(mode, "raw") == 0)
!                   opt->jo_mode = MODE_RAW;
!               else if (STRCMP(mode, "js") == 0)
!                   opt->jo_mode = MODE_JS;
!               else if (STRCMP(mode, "json") == 0)
!                   opt->jo_mode = MODE_JSON;
!               else
!               {
!                   EMSG2(_(e_invarg2), mode);
!                   return FAIL;
!               }
!           }
!           else if (STRCMP(hi->hi_key, "callback") == 0)
!           {
!               if (!(supported & JO_CALLBACK))
!                   break;
!               opt->jo_set |= JO_CALLBACK;
!               opt->jo_callback = get_callback(item);
!               if (opt->jo_callback == NULL)
!               {
!                   EMSG2(_(e_invarg2), "callback");
!                   return FAIL;
!               }
!           }
!           else if (STRCMP(hi->hi_key, "waittime") == 0)
!           {
!               if (!(supported & JO_WAITTIME))
!                   break;
!               opt->jo_set |= JO_WAITTIME;
!               opt->jo_waittime = get_tv_number(item);
!           }
!           else if (STRCMP(hi->hi_key, "timeout") == 0)
!           {
!               if (!(supported & JO_TIMEOUT))
!                   break;
!               opt->jo_set |= JO_TIMEOUT;
!               opt->jo_timeout = get_tv_number(item);
!           }
!           else
!               break;
!           --todo;
        }
+     if (todo > 0)
+     {
+       EMSG2(_(e_invarg2), hi->hi_key);
+       return FAIL;
      }
  
      return OK;
***************
*** 10002,10010 ****
      char_u    *p;
      char      *rest;
      int               port;
!     int               waittime = 0;
!     int               timeout = 2000;
!     jobopt_T    options;
      channel_T *channel;
  
      /* default: fail */
--- 10051,10057 ----
      char_u    *p;
      char      *rest;
      int               port;
!     jobopt_T    opt;
      channel_T *channel;
  
      /* default: fail */
***************
*** 10035,10067 ****
        return;
      }
  
!     options.jo_mode = MODE_JSON;
!     options.jo_callback = NULL;
!     if (argvars[1].v_type == VAR_DICT)
!     {
!       dict_T      *dict = argvars[1].vval.v_dict;
!       dictitem_T  *item;
! 
!       /* parse argdict */
!       if (get_job_options(dict, &options) == FAIL)
!           return;
!       if ((item = dict_find(dict, (char_u *)"waittime", -1)) != NULL)
!           waittime = get_tv_number(&item->di_tv);
!       if ((item = dict_find(dict, (char_u *)"timeout", -1)) != NULL)
!           timeout = get_tv_number(&item->di_tv);
!     }
!     if (timeout < 0)
      {
        EMSG(_(e_invarg));
        return;
      }
  
!     channel = channel_open((char *)address, port, waittime, NULL);
      if (channel != NULL)
      {
        rettv->vval.v_channel = channel;
!       channel_set_options(channel, &options);
!       channel_set_timeout(channel, timeout);
      }
  }
  
--- 10082,10107 ----
        return;
      }
  
!     /* parse options */
!     opt.jo_mode = MODE_JSON;
!     opt.jo_callback = NULL;
!     opt.jo_waittime = 0;
!     opt.jo_timeout = 2000;
!     if (get_job_options(&argvars[1], &opt,
!               JO_MODE + JO_CALLBACK + JO_WAITTIME + JO_TIMEOUT) == FAIL)
!       return;
!     if (opt.jo_timeout < 0)
      {
        EMSG(_(e_invarg));
        return;
      }
  
!     channel = channel_open((char *)address, port, opt.jo_waittime, NULL);
      if (channel != NULL)
      {
        rettv->vval.v_channel = channel;
!       opt.jo_set = JO_ALL;
!       channel_set_options(channel, &opt);
      }
  }
  
***************
*** 10077,10107 ****
      rettv->v_type = VAR_STRING;
      rettv->vval.v_string = NULL;
  
      channel = get_channel_arg(&argvars[0]);
      if (channel != NULL)
        rettv->vval.v_string = channel_read_block(channel);
  }
  
  /*
-  * "ch_status()" function
-  */
-     static void
- f_ch_status(typval_T *argvars, typval_T *rettv)
- {
-     /* return an empty string by default */
-     rettv->v_type = VAR_STRING;
- 
-     if (argvars[0].v_type != VAR_CHANNEL)
-     {
-       EMSG2(_(e_invarg2), get_tv_string(&argvars[0]));
-       rettv->vval.v_string = NULL;
-     }
-     else
-       rettv->vval.v_string = vim_strsave(
-                        (char_u *)channel_status(argvars[0].vval.v_channel));
- }
- 
- /*
   * common for "sendexpr()" and "sendraw()"
   * Returns the channel if the caller should read the response.
   * Otherwise returns NULL.
--- 10117,10130 ----
      rettv->v_type = VAR_STRING;
      rettv->vval.v_string = NULL;
  
+     /* TODO: use timeout from the options */
+ 
      channel = get_channel_arg(&argvars[0]);
      if (channel != NULL)
        rettv->vval.v_string = channel_read_block(channel);
  }
  
  /*
   * common for "sendexpr()" and "sendraw()"
   * Returns the channel if the caller should read the response.
   * Otherwise returns NULL.
***************
*** 10110,10140 ****
  send_common(typval_T *argvars, char_u *text, int id, char *fun)
  {
      channel_T *channel;
!     char_u    *callback = NULL;
!     jobopt_T  options;
  
      channel = get_channel_arg(&argvars[0]);
      if (channel == NULL)
        return NULL;
  
!     if (argvars[2].v_type != VAR_UNKNOWN)
!     {
!       if (argvars[2].v_type != VAR_DICT)
!       {
!           EMSG(_(e_invarg));
!           return NULL;
!       }
!       options.jo_callback = NULL;
!       if (get_job_options(argvars[2].vval.v_dict, &options) == FAIL)
!           return NULL;
!       callback = options.jo_callback;
!     }
      /* Set the callback. An empty callback means no callback and not reading
       * the response. */
!     if (callback != NULL && *callback != NUL)
!       channel_set_req_callback(channel, callback, id);
  
!     if (channel_send(channel, text, fun) == OK && callback == NULL)
        return channel;
      return NULL;
  }
--- 10133,10154 ----
  send_common(typval_T *argvars, char_u *text, int id, char *fun)
  {
      channel_T *channel;
!     jobopt_T  opt;
  
      channel = get_channel_arg(&argvars[0]);
      if (channel == NULL)
        return NULL;
  
!     opt.jo_callback = NULL;
!     if (get_job_options(&argvars[2], &opt, JO_CALLBACK) == FAIL)
!       return NULL;
! 
      /* Set the callback. An empty callback means no callback and not reading
       * the response. */
!     if (opt.jo_callback != NULL && *opt.jo_callback != NUL)
!       channel_set_req_callback(channel, opt.jo_callback, id);
  
!     if (channel_send(channel, text, fun) == OK && opt.jo_callback == NULL)
        return channel;
      return NULL;
  }
***************
*** 10208,10213 ****
--- 10222,10263 ----
      if (channel != NULL)
        rettv->vval.v_string = channel_read_block(channel);
  }
+ 
+ /*
+  * "ch_setoptions()" function
+  */
+     static void
+ f_ch_setoptions(typval_T *argvars, typval_T *rettv UNUSED)
+ {
+     channel_T *channel;
+     jobopt_T  opt;
+ 
+     channel = get_channel_arg(&argvars[0]);
+     if (channel == NULL)
+       return;
+     if (get_job_options(&argvars[1], &opt, JO_CALLBACK + JO_TIMEOUT) == FAIL)
+       return NULL;
+     channel_set_options(channel, &opt);
+ }
+ 
+ /*
+  * "ch_status()" function
+  */
+     static void
+ f_ch_status(typval_T *argvars, typval_T *rettv)
+ {
+     /* return an empty string by default */
+     rettv->v_type = VAR_STRING;
+ 
+     if (argvars[0].v_type != VAR_CHANNEL)
+     {
+       EMSG2(_(e_invarg2), get_tv_string(&argvars[0]));
+       rettv->vval.v_string = NULL;
+     }
+     else
+       rettv->vval.v_string = vim_strsave(
+                        (char_u *)channel_status(argvars[0].vval.v_channel));
+ }
  #endif
  
  /*
***************
*** 14535,14541 ****
  #else
      garray_T  ga;
  #endif
!     jobopt_T  options;
  
      rettv->v_type = VAR_JOB;
      job = job_alloc();
--- 14585,14591 ----
  #else
      garray_T  ga;
  #endif
!     jobopt_T  opt;
  
      rettv->v_type = VAR_JOB;
      job = job_alloc();
***************
*** 14546,14563 ****
      rettv->vval.v_job->jv_status = JOB_FAILED;
  
      /* Default mode is NL. */
!     options.jo_mode = MODE_NL;
!     options.jo_callback = NULL;
!     if (argvars[1].v_type != VAR_UNKNOWN)
!     {
!       if (argvars[1].v_type != VAR_DICT)
!       {
!           EMSG(_(e_invarg));
!           return;
!       }
!       if (get_job_options(argvars[1].vval.v_dict, &options) == FAIL)
!           return;
!     }
  
  #ifndef USE_ARGV
      ga_init2(&ga, (int)sizeof(char*), 20);
--- 14596,14605 ----
      rettv->vval.v_job->jv_status = JOB_FAILED;
  
      /* Default mode is NL. */
!     opt.jo_mode = MODE_NL;
!     opt.jo_callback = NULL;
!     if (get_job_options(&argvars[1], &opt, JO_MODE + JO_CALLBACK) == FAIL)
!       return;
  
  #ifndef USE_ARGV
      ga_init2(&ga, (int)sizeof(char*), 20);
***************
*** 14639,14650 ****
        ga_clear(&ga);
      }
  # endif
!     mch_start_job(argv, job, &options);
  #else
  # ifdef FEAT_CHANNEL
      ch_logs(NULL, "Starting job: %s", (char *)cmd);
  # endif
!     mch_start_job((char *)cmd, job, &options);
  #endif
  
  theend:
--- 14681,14692 ----
        ga_clear(&ga);
      }
  # endif
!     mch_start_job(argv, job, &opt);
  #else
  # ifdef FEAT_CHANNEL
      ch_logs(NULL, "Starting job: %s", (char *)cmd);
  # endif
!     mch_start_job((char *)cmd, job, &opt);
  #endif
  
  theend:
*** ../vim-7.4.1355/src/structs.h       2016-02-16 21:02:17.603873545 +0100
--- src/structs.h       2016-02-19 22:03:14.867413067 +0100
***************
*** 1372,1384 ****
      int               ch_refcount;    /* reference count */
  };
  
  /*
   * Options for job and channel commands.
   */
  typedef struct
  {
!     ch_mode_T jo_mode;        /* "mode" */
!     char_u    *jo_callback;   /* "callback", not allocated! */
  } jobopt_T;
  
  
--- 1372,1394 ----
      int               ch_refcount;    /* reference count */
  };
  
+ #define JO_MODE               1
+ #define JO_CALLBACK   2
+ #define JO_WAITTIME   4
+ #define JO_TIMEOUT    8
+ #define JO_ALL                0xffffff
+ 
  /*
   * Options for job and channel commands.
   */
  typedef struct
  {
!     int               jo_set;         /* JO_ bits for values that were set */
! 
!     ch_mode_T jo_mode;
!     char_u    *jo_callback;   /* not allocated! */
!     int               jo_waittime;
!     int               jo_timeout;
  } jobopt_T;
  
  
*** ../vim-7.4.1355/src/proto/channel.pro       2016-02-19 21:04:57.904318201 
+0100
--- src/proto/channel.pro       2016-02-19 22:11:47.370008830 +0100
***************
*** 10,17 ****
  channel_T *channel_open(char *hostname, int port_in, int waittime, void 
(*close_cb)(void));
  void channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err);
  void channel_set_job(channel_T *channel, job_T *job);
- void channel_set_mode(channel_T *channel, ch_mode_T mode);
- void channel_set_timeout(channel_T *channel, int timeout);
  void channel_set_callback(channel_T *channel, char_u *callback);
  void channel_set_options(channel_T *channel, jobopt_T *options);
  void channel_set_req_callback(channel_T *channel, char_u *callback, int id);
--- 10,15 ----
*** ../vim-7.4.1355/src/testdir/test_channel.vim        2016-02-18 
22:58:22.731503159 +0100
--- src/testdir/test_channel.vim        2016-02-19 22:25:26.493372517 +0100
***************
*** 144,149 ****
--- 144,155 ----
    endif
    call assert_equal('got it', s:responseMsg)
  
+   " check setting options (without testing the effect)
+   call ch_setoptions(handle, {'callback': 's:NotUsed'})
+   call ch_setoptions(handle, {'timeout': 111})
+   call assert_fails("call ch_setoptions(handle, {'waittime': 111})", "E475")
+   call assert_fails("call ch_setoptions(handle, {'mode': 'json'})", "E475")
+ 
    " Send an eval request that works.
    call assert_equal('ok', ch_sendexpr(handle, 'eval-works'))
    sleep 10m
*** ../vim-7.4.1355/src/version.c       2016-02-19 21:04:57.904318201 +0100
--- src/version.c       2016-02-19 22:25:55.593065733 +0100
***************
*** 749,750 ****
--- 749,752 ----
  {   /* Add new patch number below this line */
+ /**/
+     1356,
  /**/

-- 
Not too long ago, unzipping in public was illegal...

 /// Bram Moolenaar -- [email protected] -- 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    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui