Patch 7.4.1560
Problem:    Dict options with a dash are more difficult to use.
Solution:   Use an underscore, so that dict.err_io can be used.
Files:      src/channel.c, src/structs.h, src/testdir/test_channel.vim,
            runtime/doc/channel.txt


*** ../vim-7.4.1559/src/channel.c       2016-03-14 23:04:49.690923146 +0100
--- src/channel.c       2016-03-14 23:10:43.467205024 +0100
***************
*** 3148,3154 ****
                if (handle_mode(item, opt, &opt->jo_mode, JO_MODE) == FAIL)
                    return FAIL;
            }
!           else if (STRCMP(hi->hi_key, "in-mode") == 0)
            {
                if (!(supported & JO_IN_MODE))
                    break;
--- 3148,3154 ----
                if (handle_mode(item, opt, &opt->jo_mode, JO_MODE) == FAIL)
                    return FAIL;
            }
!           else if (STRCMP(hi->hi_key, "in_mode") == 0)
            {
                if (!(supported & JO_IN_MODE))
                    break;
***************
*** 3156,3162 ****
                                                                      == FAIL)
                    return FAIL;
            }
!           else if (STRCMP(hi->hi_key, "out-mode") == 0)
            {
                if (!(supported & JO_OUT_MODE))
                    break;
--- 3156,3162 ----
                                                                      == FAIL)
                    return FAIL;
            }
!           else if (STRCMP(hi->hi_key, "out_mode") == 0)
            {
                if (!(supported & JO_OUT_MODE))
                    break;
***************
*** 3164,3170 ****
                                                                      == FAIL)
                    return FAIL;
            }
!           else if (STRCMP(hi->hi_key, "err-mode") == 0)
            {
                if (!(supported & JO_ERR_MODE))
                    break;
--- 3164,3170 ----
                                                                      == FAIL)
                    return FAIL;
            }
!           else if (STRCMP(hi->hi_key, "err_mode") == 0)
            {
                if (!(supported & JO_ERR_MODE))
                    break;
***************
*** 3172,3189 ****
                                                                      == FAIL)
                    return FAIL;
            }
!           else if (STRCMP(hi->hi_key, "in-io") == 0
!                   || STRCMP(hi->hi_key, "out-io") == 0
!                   || STRCMP(hi->hi_key, "err-io") == 0)
            {
                if (!(supported & JO_OUT_IO))
                    break;
                if (handle_io(item, part_from_char(*hi->hi_key), opt) == FAIL)
                    return FAIL;
            }
!           else if (STRCMP(hi->hi_key, "in-name") == 0
!                   || STRCMP(hi->hi_key, "out-name") == 0
!                   || STRCMP(hi->hi_key, "err-name") == 0)
            {
                part = part_from_char(*hi->hi_key);
  
--- 3172,3189 ----
                                                                      == FAIL)
                    return FAIL;
            }
!           else if (STRCMP(hi->hi_key, "in_io") == 0
!                   || STRCMP(hi->hi_key, "out_io") == 0
!                   || STRCMP(hi->hi_key, "err_io") == 0)
            {
                if (!(supported & JO_OUT_IO))
                    break;
                if (handle_io(item, part_from_char(*hi->hi_key), opt) == FAIL)
                    return FAIL;
            }
!           else if (STRCMP(hi->hi_key, "in_name") == 0
!                   || STRCMP(hi->hi_key, "out_name") == 0
!                   || STRCMP(hi->hi_key, "err_name") == 0)
            {
                part = part_from_char(*hi->hi_key);
  
***************
*** 3193,3201 ****
                opt->jo_io_name[part] =
                       get_tv_string_buf_chk(item, opt->jo_io_name_buf[part]);
            }
!           else if (STRCMP(hi->hi_key, "in-buf") == 0
!                   || STRCMP(hi->hi_key, "out-buf") == 0
!                   || STRCMP(hi->hi_key, "err-buf") == 0)
            {
                part = part_from_char(*hi->hi_key);
  
--- 3193,3201 ----
                opt->jo_io_name[part] =
                       get_tv_string_buf_chk(item, opt->jo_io_name_buf[part]);
            }
!           else if (STRCMP(hi->hi_key, "in_buf") == 0
!                   || STRCMP(hi->hi_key, "out_buf") == 0
!                   || STRCMP(hi->hi_key, "err_buf") == 0)
            {
                part = part_from_char(*hi->hi_key);
  
***************
*** 3214,3221 ****
                    return FAIL;
                }
            }
!           else if (STRCMP(hi->hi_key, "in-top") == 0
!                   || STRCMP(hi->hi_key, "in-bot") == 0)
            {
                linenr_T *lp;
  
--- 3214,3221 ----
                    return FAIL;
                }
            }
!           else if (STRCMP(hi->hi_key, "in_top") == 0
!                   || STRCMP(hi->hi_key, "in_bot") == 0)
            {
                linenr_T *lp;
  
***************
*** 3262,3268 ****
                    return FAIL;
                }
            }
!           else if (STRCMP(hi->hi_key, "out-cb") == 0)
            {
                if (!(supported & JO_OUT_CALLBACK))
                    break;
--- 3262,3268 ----
                    return FAIL;
                }
            }
!           else if (STRCMP(hi->hi_key, "out_cb") == 0)
            {
                if (!(supported & JO_OUT_CALLBACK))
                    break;
***************
*** 3270,3280 ****
                opt->jo_out_cb = get_callback(item, &opt->jo_out_partial);
                if (opt->jo_out_cb == NULL)
                {
!                   EMSG2(_(e_invarg2), "out-cb");
                    return FAIL;
                }
            }
!           else if (STRCMP(hi->hi_key, "err-cb") == 0)
            {
                if (!(supported & JO_ERR_CALLBACK))
                    break;
--- 3270,3280 ----
                opt->jo_out_cb = get_callback(item, &opt->jo_out_partial);
                if (opt->jo_out_cb == NULL)
                {
!                   EMSG2(_(e_invarg2), "out_cb");
                    return FAIL;
                }
            }
!           else if (STRCMP(hi->hi_key, "err_cb") == 0)
            {
                if (!(supported & JO_ERR_CALLBACK))
                    break;
***************
*** 3282,3292 ****
                opt->jo_err_cb = get_callback(item, &opt->jo_err_partial);
                if (opt->jo_err_cb == NULL)
                {
!                   EMSG2(_(e_invarg2), "err-cb");
                    return FAIL;
                }
            }
!           else if (STRCMP(hi->hi_key, "close-cb") == 0)
            {
                if (!(supported & JO_CLOSE_CALLBACK))
                    break;
--- 3282,3292 ----
                opt->jo_err_cb = get_callback(item, &opt->jo_err_partial);
                if (opt->jo_err_cb == NULL)
                {
!                   EMSG2(_(e_invarg2), "err_cb");
                    return FAIL;
                }
            }
!           else if (STRCMP(hi->hi_key, "close_cb") == 0)
            {
                if (!(supported & JO_CLOSE_CALLBACK))
                    break;
***************
*** 3294,3300 ****
                opt->jo_close_cb = get_callback(item, &opt->jo_close_partial);
                if (opt->jo_close_cb == NULL)
                {
!                   EMSG2(_(e_invarg2), "close-cb");
                    return FAIL;
                }
            }
--- 3294,3300 ----
                opt->jo_close_cb = get_callback(item, &opt->jo_close_partial);
                if (opt->jo_close_cb == NULL)
                {
!                   EMSG2(_(e_invarg2), "close_cb");
                    return FAIL;
                }
            }
***************
*** 3312,3325 ****
                opt->jo_set |= JO_TIMEOUT;
                opt->jo_timeout = get_tv_number(item);
            }
!           else if (STRCMP(hi->hi_key, "out-timeout") == 0)
            {
                if (!(supported & JO_OUT_TIMEOUT))
                    break;
                opt->jo_set |= JO_OUT_TIMEOUT;
                opt->jo_out_timeout = get_tv_number(item);
            }
!           else if (STRCMP(hi->hi_key, "err-timeout") == 0)
            {
                if (!(supported & JO_ERR_TIMEOUT))
                    break;
--- 3312,3325 ----
                opt->jo_set |= JO_TIMEOUT;
                opt->jo_timeout = get_tv_number(item);
            }
!           else if (STRCMP(hi->hi_key, "out_timeout") == 0)
            {
                if (!(supported & JO_OUT_TIMEOUT))
                    break;
                opt->jo_set |= JO_OUT_TIMEOUT;
                opt->jo_out_timeout = get_tv_number(item);
            }
!           else if (STRCMP(hi->hi_key, "err_timeout") == 0)
            {
                if (!(supported & JO_ERR_TIMEOUT))
                    break;
***************
*** 3360,3366 ****
                    return FAIL;
                }
            }
!           else if (STRCMP(hi->hi_key, "exit-cb") == 0)
            {
                if (!(supported & JO_EXIT_CB))
                    break;
--- 3360,3366 ----
                    return FAIL;
                }
            }
!           else if (STRCMP(hi->hi_key, "exit_cb") == 0)
            {
                if (!(supported & JO_EXIT_CB))
                    break;
***************
*** 3375,3381 ****
                                                       item, opt->jo_ecb_buf);
                if (opt->jo_exit_cb == NULL)
                {
!                   EMSG2(_(e_invarg2), "exit-cb");
                    return FAIL;
                }
            }
--- 3375,3381 ----
                                                       item, opt->jo_ecb_buf);
                if (opt->jo_exit_cb == NULL)
                {
!                   EMSG2(_(e_invarg2), "exit_cb");
                    return FAIL;
                }
            }
***************
*** 3546,3552 ****
  }
  
  /*
!  * Called once in a while: check if any jobs with an "exit-cb" have ended.
   */
      void
  job_check_ended(void)
--- 3546,3552 ----
  }
  
  /*
!  * Called once in a while: check if any jobs with an "exit_cb" have ended.
   */
      void
  job_check_ended(void)
***************
*** 3609,3615 ****
                && (!(opt.jo_set & (JO_OUT_NAME << (part - PART_OUT)))
                    || *opt.jo_io_name[part] == NUL))
        {
!           EMSG(_("E920: -io file requires -name to be set"));
            return job;
        }
  
--- 3609,3615 ----
                && (!(opt.jo_set & (JO_OUT_NAME << (part - PART_OUT)))
                    || *opt.jo_io_name[part] == NUL))
        {
!           EMSG(_("E920: _io file requires _name to be set"));
            return job;
        }
  
***************
*** 3626,3632 ****
        }
        else if (!(opt.jo_set & JO_IN_NAME))
        {
!           EMSG(_("E915: in-io buffer requires in-buf or in-name to be set"));
        }
        else
            buf = buflist_find_by_name(opt.jo_io_name[PART_IN], FALSE);
--- 3626,3632 ----
        }
        else if (!(opt.jo_set & JO_IN_NAME))
        {
!           EMSG(_("E915: in_io buffer requires in_buf or in_name to be set"));
        }
        else
            buf = buflist_find_by_name(opt.jo_io_name[PART_IN], FALSE);
***************
*** 3837,3843 ****
      dict_add_nr_str(dict, "process", nr, NULL);
  
      dict_add_nr_str(dict, "exitval", job->jv_exitval, NULL);
!     dict_add_nr_str(dict, "exit-cb", 0L, job->jv_exit_cb);
      dict_add_nr_str(dict, "stoponexit", 0L, job->jv_stoponexit);
  }
  
--- 3837,3843 ----
      dict_add_nr_str(dict, "process", nr, NULL);
  
      dict_add_nr_str(dict, "exitval", job->jv_exitval, NULL);
!     dict_add_nr_str(dict, "exit_cb", 0L, job->jv_exit_cb);
      dict_add_nr_str(dict, "stoponexit", 0L, job->jv_stoponexit);
  }
  
*** ../vim-7.4.1559/src/structs.h       2016-03-14 23:04:49.690923146 +0100
--- src/structs.h       2016-03-14 23:10:54.771086235 +0100
***************
*** 1414,1431 ****
  #define JO_PART                   0x1000      /* "part" */
  #define JO_ID             0x2000      /* "id" */
  #define JO_STOPONEXIT     0x4000      /* "stoponexit" */
! #define JO_EXIT_CB        0x8000      /* "exit-cb" */
! #define JO_OUT_IO         0x10000     /* "out-io" */
! #define JO_ERR_IO         0x20000     /* "err-io" (JO_OUT_IO << 1) */
! #define JO_IN_IO          0x40000     /* "in-io" (JO_OUT_IO << 2) */
! #define JO_OUT_NAME       0x80000     /* "out-name" */
! #define JO_ERR_NAME       0x100000    /* "err-name" (JO_OUT_NAME << 1) */
! #define JO_IN_NAME        0x200000    /* "in-name" (JO_OUT_NAME << 2) */
! #define JO_IN_TOP         0x400000    /* "in-top" */
! #define JO_IN_BOT         0x800000    /* "in-bot" */
! #define JO_OUT_BUF        0x1000000   /* "out-buf" */
! #define JO_ERR_BUF        0x2000000   /* "err-buf" (JO_OUT_BUF << 1) */
! #define JO_IN_BUF         0x4000000   /* "in-buf" (JO_OUT_BUF << 2) */
  #define JO_CHANNEL        0x8000000   /* "channel" */
  #define JO_ALL                    0xfffffff
  
--- 1414,1431 ----
  #define JO_PART                   0x1000      /* "part" */
  #define JO_ID             0x2000      /* "id" */
  #define JO_STOPONEXIT     0x4000      /* "stoponexit" */
! #define JO_EXIT_CB        0x8000      /* "exit_cb" */
! #define JO_OUT_IO         0x10000     /* "out_io" */
! #define JO_ERR_IO         0x20000     /* "err_io" (JO_OUT_IO << 1) */
! #define JO_IN_IO          0x40000     /* "in_io" (JO_OUT_IO << 2) */
! #define JO_OUT_NAME       0x80000     /* "out_name" */
! #define JO_ERR_NAME       0x100000    /* "err_name" (JO_OUT_NAME << 1) */
! #define JO_IN_NAME        0x200000    /* "in_name" (JO_OUT_NAME << 2) */
! #define JO_IN_TOP         0x400000    /* "in_top" */
! #define JO_IN_BOT         0x800000    /* "in_bot" */
! #define JO_OUT_BUF        0x1000000   /* "out_buf" */
! #define JO_ERR_BUF        0x2000000   /* "err_buf" (JO_OUT_BUF << 1) */
! #define JO_IN_BUF         0x4000000   /* "in_buf" (JO_OUT_BUF << 2) */
  #define JO_CHANNEL        0x8000000   /* "channel" */
  #define JO_ALL                    0xfffffff
  
*** ../vim-7.4.1559/src/testdir/test_channel.vim        2016-03-12 
15:51:37.604527751 +0100
--- src/testdir/test_channel.vim        2016-03-14 23:14:42.712691038 +0100
***************
*** 519,525 ****
    endif
    call ch_logfile('Xlog')
    call ch_log('Test_nl_err_to_out_pipe()')
!   let job = job_start(s:python . " test_channel_pipe.py", {'err-io': 'out'})
    call assert_equal("run", job_status(job))
    try
      let handle = job_getchannel(job)
--- 519,525 ----
    endif
    call ch_logfile('Xlog')
    call ch_log('Test_nl_err_to_out_pipe()')
!   let job = job_start(s:python . " test_channel_pipe.py", {'err_io': 'out'})
    call assert_equal("run", job_status(job))
    try
      let handle = job_getchannel(job)
***************
*** 566,572 ****
    call ch_log('Test_nl_read_file()')
    call writefile(['echo something', 'echoerr wrong', 'double this'], 'Xinput')
    let job = job_start(s:python . " test_channel_pipe.py",
!       \ {'in-io': 'file', 'in-name': 'Xinput'})
    call assert_equal("run", job_status(job))
    try
      let handle = job_getchannel(job)
--- 566,572 ----
    call ch_log('Test_nl_read_file()')
    call writefile(['echo something', 'echoerr wrong', 'double this'], 'Xinput')
    let job = job_start(s:python . " test_channel_pipe.py",
!       \ {'in_io': 'file', 'in_name': 'Xinput'})
    call assert_equal("run", job_status(job))
    try
      let handle = job_getchannel(job)
***************
*** 586,592 ****
    endif
    call ch_log('Test_nl_write_out_file()')
    let job = job_start(s:python . " test_channel_pipe.py",
!       \ {'out-io': 'file', 'out-name': 'Xoutput'})
    call assert_equal("run", job_status(job))
    try
      let handle = job_getchannel(job)
--- 586,592 ----
    endif
    call ch_log('Test_nl_write_out_file()')
    let job = job_start(s:python . " test_channel_pipe.py",
!       \ {'out_io': 'file', 'out_name': 'Xoutput'})
    call assert_equal("run", job_status(job))
    try
      let handle = job_getchannel(job)
***************
*** 607,613 ****
    endif
    call ch_log('Test_nl_write_err_file()')
    let job = job_start(s:python . " test_channel_pipe.py",
!       \ {'err-io': 'file', 'err-name': 'Xoutput'})
    call assert_equal("run", job_status(job))
    try
      let handle = job_getchannel(job)
--- 607,613 ----
    endif
    call ch_log('Test_nl_write_err_file()')
    let job = job_start(s:python . " test_channel_pipe.py",
!       \ {'err_io': 'file', 'err_name': 'Xoutput'})
    call assert_equal("run", job_status(job))
    try
      let handle = job_getchannel(job)
***************
*** 628,634 ****
    endif
    call ch_log('Test_nl_write_both_file()')
    let job = job_start(s:python . " test_channel_pipe.py",
!       \ {'out-io': 'file', 'out-name': 'Xoutput', 'err-io': 'out'})
    call assert_equal("run", job_status(job))
    try
      let handle = job_getchannel(job)
--- 628,634 ----
    endif
    call ch_log('Test_nl_write_both_file()')
    let job = job_start(s:python . " test_channel_pipe.py",
!       \ {'out_io': 'file', 'out_name': 'Xoutput', 'err_io': 'out'})
    call assert_equal("run", job_status(job))
    try
      let handle = job_getchannel(job)
***************
*** 649,661 ****
      return
    endif
    call ch_log('Test_pipe_to_buffer()')
!   let options = {'out-io': 'buffer'}
    if a:use_name
!     let options['out-name'] = 'pipe-output'
      let firstline = 'Reading from channel output...'
    else
      sp pipe-output
!     let options['out-buf'] = bufnr('%')
      quit
      let firstline = ''
    endif
--- 649,661 ----
      return
    endif
    call ch_log('Test_pipe_to_buffer()')
!   let options = {'out_io': 'buffer'}
    if a:use_name
!     let options['out_name'] = 'pipe-output'
      let firstline = 'Reading from channel output...'
    else
      sp pipe-output
!     let options['out_buf'] = bufnr('%')
      quit
      let firstline = ''
    endif
***************
*** 689,701 ****
      return
    endif
    call ch_log('Test_pipe_err_to_buffer()')
!   let options = {'err-io': 'buffer'}
    if a:use_name
!     let options['err-name'] = 'pipe-err'
      let firstline = 'Reading from channel error...'
    else
      sp pipe-err
!     let options['err-buf'] = bufnr('%')
      quit
      let firstline = ''
    endif
--- 689,701 ----
      return
    endif
    call ch_log('Test_pipe_err_to_buffer()')
!   let options = {'err_io': 'buffer'}
    if a:use_name
!     let options['err_name'] = 'pipe-err'
      let firstline = 'Reading from channel error...'
    else
      sp pipe-err
!     let options['err_buf'] = bufnr('%')
      quit
      let firstline = ''
    endif
***************
*** 730,736 ****
    endif
    call ch_log('Test_pipe_both_to_buffer()')
    let job = job_start(s:python . " test_channel_pipe.py",
!       \ {'out-io': 'buffer', 'out-name': 'pipe-err', 'err-io': 'out'})
    call assert_equal("run", job_status(job))
    try
      let handle = job_getchannel(job)
--- 730,736 ----
    endif
    call ch_log('Test_pipe_both_to_buffer()')
    let job = job_start(s:python . " test_channel_pipe.py",
!       \ {'out_io': 'buffer', 'out_name': 'pipe-err', 'err_io': 'out'})
    call assert_equal("run", job_status(job))
    try
      let handle = job_getchannel(job)
***************
*** 756,766 ****
  
    sp pipe-input
    call setline(1, ['echo one', 'echo two', 'echo three'])
!   let options = {'in-io': 'buffer'}
    if a:use_name
!     let options['in-name'] = 'pipe-input'
    else
!     let options['in-buf'] = bufnr('%')
    endif
  
    let job = job_start(s:python . " test_channel_pipe.py", options)
--- 756,766 ----
  
    sp pipe-input
    call setline(1, ['echo one', 'echo two', 'echo three'])
!   let options = {'in_io': 'buffer'}
    if a:use_name
!     let options['in_name'] = 'pipe-input'
    else
!     let options['in_buf'] = bufnr('%')
    endif
  
    let job = job_start(s:python . " test_channel_pipe.py", options)
***************
*** 790,796 ****
    endif
    call ch_log('Test_pipe_to_nameless_buffer()')
    let job = job_start(s:python . " test_channel_pipe.py",
!       \ {'out-io': 'buffer'})
    call assert_equal("run", job_status(job))
    try
      let handle = job_getchannel(job)
--- 790,796 ----
    endif
    call ch_log('Test_pipe_to_nameless_buffer()')
    let job = job_start(s:python . " test_channel_pipe.py",
!       \ {'out_io': 'buffer'})
    call assert_equal("run", job_status(job))
    try
      let handle = job_getchannel(job)
***************
*** 811,817 ****
    endif
    call ch_log('Test_pipe_to_buffer_json()')
    let job = job_start(s:python . " test_channel_pipe.py",
!       \ {'out-io': 'buffer', 'out-mode': 'json'})
    call assert_equal("run", job_status(job))
    try
      let handle = job_getchannel(job)
--- 811,817 ----
    endif
    call ch_log('Test_pipe_to_buffer_json()')
    let job = job_start(s:python . " test_channel_pipe.py",
!       \ {'out_io': 'buffer', 'out_mode': 'json'})
    call assert_equal("run", job_status(job))
    try
      let handle = job_getchannel(job)
***************
*** 849,856 ****
    set buftype=nofile
  
    let job = job_start(s:python . " test_channel_pipe.py",
!       \ {'in-io': 'buffer', 'in-name': 'pipe-input', 'in-top': 0,
!       \  'out-io': 'buffer', 'out-name': 'pipe-output'})
    call assert_equal("run", job_status(job))
    try
      exe "normal Gaecho hello\<CR>"
--- 849,856 ----
    set buftype=nofile
  
    let job = job_start(s:python . " test_channel_pipe.py",
!       \ {'in_io': 'buffer', 'in_name': 'pipe-input', 'in_top': 0,
!       \  'out_io': 'buffer', 'out_name': 'pipe-output'})
    call assert_equal("run", job_status(job))
    try
      exe "normal Gaecho hello\<CR>"
***************
*** 884,891 ****
    set buftype=nofile
  
    let job = job_start(s:python . " test_channel_pipe.py",
!       \ {'in-io': 'buffer', 'in-name': 'pipe-io', 'in-top': 0,
!       \  'out-io': 'buffer', 'out-name': 'pipe-io'})
    call assert_equal("run", job_status(job))
    try
      exe "normal Goecho hello\<CR>"
--- 884,891 ----
    set buftype=nofile
  
    let job = job_start(s:python . " test_channel_pipe.py",
!       \ {'in_io': 'buffer', 'in_name': 'pipe-io', 'in_top': 0,
!       \  'out_io': 'buffer', 'out_name': 'pipe-io'})
    call assert_equal("run", job_status(job))
    try
      exe "normal Goecho hello\<CR>"
***************
*** 912,918 ****
    " We cannot check that no I/O works, we only check that the job starts
    " properly.
    let job = job_start(s:python . " test_channel_pipe.py something",
!       \ {'in-io': 'null'})
    call assert_equal("run", job_status(job))
    try
      call assert_equal('something', ch_read(job))
--- 912,918 ----
    " We cannot check that no I/O works, we only check that the job starts
    " properly.
    let job = job_start(s:python . " test_channel_pipe.py something",
!       \ {'in_io': 'null'})
    call assert_equal("run", job_status(job))
    try
      call assert_equal('something', ch_read(job))
***************
*** 921,927 ****
    endtry
  
    let job = job_start(s:python . " test_channel_pipe.py err-out",
!       \ {'out-io': 'null'})
    call assert_equal("run", job_status(job))
    try
      call assert_equal('err-out', ch_read(job, {"part": "err"}))
--- 921,927 ----
    endtry
  
    let job = job_start(s:python . " test_channel_pipe.py err-out",
!       \ {'out_io': 'null'})
    call assert_equal("run", job_status(job))
    try
      call assert_equal('err-out', ch_read(job, {"part": "err"}))
***************
*** 930,936 ****
    endtry
  
    let job = job_start(s:python . " test_channel_pipe.py something",
!       \ {'err-io': 'null'})
    call assert_equal("run", job_status(job))
    try
      call assert_equal('something', ch_read(job))
--- 930,936 ----
    endtry
  
    let job = job_start(s:python . " test_channel_pipe.py something",
!       \ {'err_io': 'null'})
    call assert_equal("run", job_status(job))
    try
      call assert_equal('something', ch_read(job))
***************
*** 939,950 ****
    endtry
  
    let job = job_start(s:python . " test_channel_pipe.py something",
!       \ {'out-io': 'null', 'err-io': 'out'})
    call assert_equal("run", job_status(job))
    call job_stop(job)
  
    let job = job_start(s:python . " test_channel_pipe.py something",
!       \ {'in-io': 'null', 'out-io': 'null', 'err-io': 'null'})
    call assert_equal("run", job_status(job))
    call assert_equal('channel fail', string(job_getchannel(job)))
    call assert_equal('fail', ch_status(job))
--- 939,950 ----
    endtry
  
    let job = job_start(s:python . " test_channel_pipe.py something",
!       \ {'out_io': 'null', 'err_io': 'out'})
    call assert_equal("run", job_status(job))
    call job_stop(job)
  
    let job = job_start(s:python . " test_channel_pipe.py something",
!       \ {'in_io': 'null', 'out_io': 'null', 'err_io': 'null'})
    call assert_equal("run", job_status(job))
    call assert_equal('channel fail', string(job_getchannel(job)))
    call assert_equal('fail', ch_status(job))
***************
*** 1082,1090 ****
  endfunc
  
  function s:test_exit_callback(port)
!   call job_setoptions(s:job, {'exit-cb': 'MyExitCb'})
    let s:exit_job = s:job
!   call assert_equal('MyExitCb', job_info(s:job)['exit-cb'])
  endfunc
  
  func Test_exit_callback()
--- 1082,1090 ----
  endfunc
  
  function s:test_exit_callback(port)
!   call job_setoptions(s:job, {'exit_cb': 'MyExitCb'})
    let s:exit_job = s:job
!   call assert_equal('MyExitCb', job_info(s:job)['exit_cb'])
  endfunc
  
  func Test_exit_callback()
***************
*** 1121,1127 ****
      call assert_false(1, "Can't open channel")
      return
    endif
!   call ch_setoptions(handle, {'close-cb': 'MyCloseCb'})
  
    call assert_equal('', ch_evalexpr(handle, 'close me'))
    call s:waitFor('"closed" == s:ch_close_ret')
--- 1121,1127 ----
      call assert_false(1, "Can't open channel")
      return
    endif
!   call ch_setoptions(handle, {'close_cb': 'MyCloseCb'})
  
    call assert_equal('', ch_evalexpr(handle, 'close me'))
    call s:waitFor('"closed" == s:ch_close_ret')
*** ../vim-7.4.1559/runtime/doc/channel.txt     2016-02-27 21:10:05.121338560 
+0100
--- runtime/doc/channel.txt     2016-03-14 23:18:07.578538580 +0100
***************
*** 1,4 ****
! *channel.txt*      For Vim version 7.4.  Last change: 2016 Feb 27
  
  
                  VIM REFERENCE MANUAL    by Bram Moolenaar
--- 1,4 ----
! *channel.txt*      For Vim version 7.4.  Last change: 2016 Mar 14
  
  
                  VIM REFERENCE MANUAL    by Bram Moolenaar
***************
*** 44,51 ****
  4. Running a filter, synchronously.
     Uses pipes.
  
! For when using sockets See |job-start|, |job-may-start| and |channel-open|.
! For 2 and 3, one or more jobs using pipes, see |job-start|.
  For 4 use the ":{range}!cmd" command, see |filter|.
  
  Over the socket and pipes these protocols are available:
--- 44,51 ----
  4. Running a filter, synchronously.
     Uses pipes.
  
! For when using sockets See |job-start|, |job-start-nochannel| and
! |channel-open|.  For 2 and 3, one or more jobs using pipes, see |job-start|.
  For 4 use the ":{range}!cmd" command, see |filter|.
  
  Over the socket and pipes these protocols are available:
***************
*** 103,108 ****
--- 103,113 ----
        let channel = ch_open('localhost:8765', {'callback': "MyHandler"})
        call ch_sendexpr(channel, 'hello!')
  
+ When trying out channels it's useful to see what is going on.  You can tell
+ Vim to write lines in log file: >
+       call ch_logfile('channellog', 'w')
+ See |ch_logfile()|.
+ 
  ==============================================================================
  3. Opening a channel                                  *channel-open*
  
***************
*** 122,138 ****
        "js"   - Use JS (JavaScript) encoding, more efficient than JSON.
        "nl"   - Use messages that end in a NL character
        "raw"  - Use raw messages
! 
! "in-mode"     mode specifically for stdin, only when using pipes
! "out-mode"    mode specifically for stdout, only when using pipes
! "err-mode"    mode specifically for stderr, only when using pipes
                Note: when setting "mode" the part specific mode is
                overwritten.  Therefore set "mode" first and the part specific
                mode later.
  
!               Note: when writing to a file or buffer NL mode is always used.
  
!                                                       *channel-callback*
  "callback"    A function that is called when a message is received that is
                not handled otherwise.  It gets two arguments: the channel
                and the received message. Example: >
--- 127,144 ----
        "js"   - Use JS (JavaScript) encoding, more efficient than JSON.
        "nl"   - Use messages that end in a NL character
        "raw"  - Use raw messages
!                                               *in_mode* *out_mode* *err_mode*
! "in_mode"     mode specifically for stdin, only when using pipes
! "out_mode"    mode specifically for stdout, only when using pipes
! "err_mode"    mode specifically for stderr, only when using pipes
                Note: when setting "mode" the part specific mode is
                overwritten.  Therefore set "mode" first and the part specific
                mode later.
  
!               Note: when writing to a file or buffer and when reading from a
!               buffer NL mode is used by default.
  
!                                               *channel-callback* *E921*
  "callback"    A function that is called when a message is received that is
                not handled otherwise.  It gets two arguments: the channel
                and the received message. Example: >
***************
*** 147,163 ****
                excluding the NL.
                When "mode" is "raw" the "msg" argument is the whole message
                as a string.
!                                                       *out-cb*
! "out-cb"      A function like "callback" but used for stdout.  Only for when
!               the channel uses pipes.  When "out-cb" wasn't set the channel
                callback is used.
!                                                       *err-cb*
! "err-cb"      A function like "callback" but used for stderr.  Only for when
!               the channel uses pipes.  When "err-cb" wasn't set the channel
                callback is used.
  
!               TODO:                                   *close-cb*
! "close-cb"    A function that is called when the channel gets closed, other
                than by calling ch_close().  It should be defined like this: >
        func MyCloseHandler(channel)
  <                                                     *waittime*
--- 153,169 ----
                excluding the NL.
                When "mode" is "raw" the "msg" argument is the whole message
                as a string.
!                                                       *out_cb*
! "out_cb"      A function like "callback" but used for stdout.  Only for when
!               the channel uses pipes.  When "out_cb" wasn't set the channel
                callback is used.
!                                                       *err_cb*
! "err_cb"      A function like "callback" but used for stderr.  Only for when
!               the channel uses pipes.  When "err_cb" wasn't set the channel
                callback is used.
  
!                                                       *close_cb*
! "close_cb"    A function that is called when the channel gets closed, other
                than by calling ch_close().  It should be defined like this: >
        func MyCloseHandler(channel)
  <                                                     *waittime*
***************
*** 173,181 ****
  "timeout"     The time to wait for a request when blocking, E.g. when using
                ch_evalexpr().  In milliseconds.  The default is 2000 (2
                seconds).
!                                               *out-timeout* *err-timeout*
! "out-timeout" Timeout for stdout.  Only when using pipes.
! "err-timeout" Timeout for stderr.  Only when using pipes.
                Note: when setting "timeout" the part specific mode is
                overwritten.  Therefore set "timeout" first and the part
                specific mode later.
--- 179,187 ----
  "timeout"     The time to wait for a request when blocking, E.g. when using
                ch_evalexpr().  In milliseconds.  The default is 2000 (2
                seconds).
!                                               *out_timeout* *err_timeout*
! "out_timeout" Timeout for stdout.  Only when using pipes.
! "err_timeout" Timeout for stderr.  Only when using pipes.
                Note: when setting "timeout" the part specific mode is
                overwritten.  Therefore set "timeout" first and the part
                specific mode later.
***************
*** 191,196 ****
--- 197,206 ----
      call ch_setoptions(channel, {'callback': callback})
  When "callback" is empty (zero or an empty string) the handler is removed.
  
+ After a callback has been invoked Vim will update the screen and put the
+ cursor back where it belongs.  Thus the callback should not need to do
+ `:redraw`.
+ 
  The timeout can be changed: >
      call ch_setoptions(channel, {'timeout': msec})
  <
***************
*** 259,267 ****
  Then channel handler will then get {response} converted to Vim types.  If the
  channel does not have a handler the message is dropped.
  
! On read error or ch_close(), when using a socket, the string "DETACH" is sent,
! if still possible.  The channel will then be inactive. For a JSON and JS mode
! channel quotes are used around DETACH, otherwise there are no quotes.
  
  It is also possible to use ch_sendraw() and ch_evalraw() on a JSON or JS
  channel.  The caller is then completely responsible for correct encoding and
--- 269,277 ----
  Then channel handler will then get {response} converted to Vim types.  If the
  channel does not have a handler the message is dropped.
  
! On read error or ch_close(), when using a socket with RAW or NL mode, the
! string "DETACH\n" is sent, if still possible.  The channel will then be
! inactive.
  
  It is also possible to use ch_sendraw() and ch_evalraw() on a JSON or JS
  channel.  The caller is then completely responsible for correct encoding and
***************
*** 400,406 ****
        "open"          The channel can be used.
        "closed"        The channel was closed.
  
- TODO:
  To obtain the job associated with a channel: ch_getjob(channel)
  
  To read one message from a channel: >
--- 410,415 ----
***************
*** 431,437 ****
  
  If the command produces a line of output that you want to deal with, specify
  a handler for stdout: >
!     let job = job_start(command, {"out-cb": "MyHandler"})
  The function will be called with the channel and a message. You would define
  it like this: >
      func MyHandler(channel, msg)
--- 440,446 ----
  
  If the command produces a line of output that you want to deal with, specify
  a handler for stdout: >
!     let job = job_start(command, {"out_cb": "MyHandler"})
  The function will be called with the channel and a message. You would define
  it like this: >
      func MyHandler(channel, msg)
***************
*** 439,448 ****
  Without the handler you need to read the output with |ch_read()| or
  |ch_readraw()|.
  
! The handler defined for "out-cb" will not receive stderr.  If you want to
! handle that separately, add an "err-cb" handler: >
!     let job = job_start(command, {"out-cb": "MyHandler",
!           \                     "err-cb": "ErrHandler"})
  
  If you want to handle both stderr and stdout with one handler use the
  "callback" option: >
--- 448,457 ----
  Without the handler you need to read the output with |ch_read()| or
  |ch_readraw()|.
  
! The handler defined for "out_cb" will not receive stderr.  If you want to
! handle that separately, add an "err_cb" handler: >
!     let job = job_start(command, {"out_cb": "MyHandler",
!           \                     "err_cb": "ErrHandler"})
  
  If you want to handle both stderr and stdout with one handler use the
  "callback" option: >
***************
*** 454,501 ****
  There are several options you can use, see |job-options|.
  For example, to start a job and write its output in buffer "dummy": >
        let logjob = job_start("tail -f /tmp/log",
!                            \ {'out-io': 'buffer', 'out-name': 'dummy'})
        sbuf dummy
  
! TODO:
! To run a job and read its output once it is done: >
!       let job = job_start({command}, {'exit-cb': 'MyHandler'})
!       func MyHandler(job, status)
!         let channel = job_getchannel()
!         let output = ch_readall(channel)
!         " parse output
!       endfunc
  
  ==============================================================================
  9. Starting a job without a channel                   *job-start-nochannel*
  
  To start another process without creating a channel: >
!     let job = job_start(command, {"in-io": "null", "out-io": "null"})
  
  This starts {command} in the background, Vim does not wait for it to finish.
  
- TODO:
  When Vim sees that neither stdin, stdout or stderr are connected, no channel
  will be created.  Often you will want to include redirection in the command to
  avoid it getting stuck.
  
  There are several options you can use, see |job-options|.
  
! TODO:                                                 *job-may-start*
! To start a job only when connecting to an address does not work use
! job_maystart('command', {address}, {options}), For Example: >
!       let job = job_maystart(command, address, {"waittime": 1000})
!       let channel = job_gethandle(job)
! 
! This comes down to: >
        let channel = ch_open(address, {"waittime": 0})
        if ch_status(channel) == "fail"
          let job = job_start(command)
          let channel = ch_open(address, {"waittime": 1000})
-         call job_sethandle(channel)
        endif
! Note that the specified waittime applies to when the job has been started.
! This gives the job some time to make the port available.
  
  ==============================================================================
  10. Job options                                               *job-options*
--- 463,516 ----
  There are several options you can use, see |job-options|.
  For example, to start a job and write its output in buffer "dummy": >
        let logjob = job_start("tail -f /tmp/log",
!                            \ {'out_io': 'buffer', 'out_name': 'dummy'})
        sbuf dummy
  
! 
! Job input from a buffer ~
! 
! To run a job that reads from a buffer: >
!       let job = job_start({command},
!           \ {'in_io': 'buffer', 'in_name': 'mybuffer'})
! <
!                                                       *E915* *E918*
! The buffer is found by name, similar to |bufnr()|. The buffer must exist and
! be loaded when job_start() is called.
! 
! By default this reads the whole buffer.  This can be changed with the "in_top"
! and "in_bot" options.
! 
! A special mode is when "in_top" is set to zero and "in_bot" is not set: Every
! time a line is added to the buffer, the last-but-one line will be send to the
! job stdin.  This allows for editing the last line and sending it when pressing
! Enter.
  
  ==============================================================================
  9. Starting a job without a channel                   *job-start-nochannel*
  
  To start another process without creating a channel: >
!     let job = job_start(command,
!       \ {"in_io": "null", "out_io": "null", "err_io": "null"})
  
  This starts {command} in the background, Vim does not wait for it to finish.
  
  When Vim sees that neither stdin, stdout or stderr are connected, no channel
  will be created.  Often you will want to include redirection in the command to
  avoid it getting stuck.
  
  There are several options you can use, see |job-options|.
  
!                                                       *job-start-if-needed*
! To start a job only when connecting to an address does not work, do something
! like this: >
        let channel = ch_open(address, {"waittime": 0})
        if ch_status(channel) == "fail"
          let job = job_start(command)
          let channel = ch_open(address, {"waittime": 1000})
        endif
! 
! Note that the waittime for ch_open() gives the job one second to make the port
! available.
  
  ==============================================================================
  10. Job options                                               *job-options*
***************
*** 509,525 ****
                                                *job-callback*
  "callback": handler   Callback for something to read on any part of the
                        channel.
!                                               *job-out-cb*
! "out-cb": handler     Callback for when there is something to read on
                        stdout.
!                                               *job-err-cb*
! "err-cb": handler     Callback for when there is something to read on
                        stderr.
!                                               *job-close-cb*
! "close-cb": handler   Callback for when the channel is closed.  Same as
!                       "close-cb" on ch_open().
!                                               *job-exit-cb*
! "exit-cb": handler    Callback for when the job ends.  The arguments are the
                        job and the exit status.
                        Vim checks about every 10 seconds for jobs that ended.
                        The callback can also be triggered by calling
--- 524,540 ----
                                                *job-callback*
  "callback": handler   Callback for something to read on any part of the
                        channel.
!                                               *job-out_cb*
! "out_cb": handler     Callback for when there is something to read on
                        stdout.
!                                               *job-err_cb*
! "err_cb": handler     Callback for when there is something to read on
                        stderr.
!                                               *job-close_cb*
! "close_cb": handler   Callback for when the channel is closed.  Same as
!                       "close_cb" on ch_open().
!                                               *job-exit_cb*
! "exit_cb": handler    Callback for when the job ends.  The arguments are the
                        job and the exit status.
                        Vim checks about every 10 seconds for jobs that ended.
                        The callback can also be triggered by calling
***************
*** 530,566 ****
  "stoponexit": ""      Do not stop the job when Vim exits.
                        The default is "term".
  
! TODO:                                         *job-term*
  "term": "open"                Start a terminal and connect the job
                        stdin/stdout/stderr to it.
  
!                                               *job-in-io*
! "in-io": "null"               disconnect stdin  TODO
! "in-io": "pipe"               stdin is connected to the channel (default)
! "in-io": "file"               stdin reads from a file  TODO
! "in-io": "buffer"     stdin reads from a buffer  TODO
! "in-name": "/path/file"       the name of he file or buffer to read from
! "in-buf": number      the number of the buffer to read from  TODO
! 
!                                               *job-out-io*
! "out-io": "null"      disconnect stdout  TODO
! "out-io": "pipe"      stdout is connected to the channel (default)
! "out-io": "file"      stdout writes to a file  TODO
! "out-io": "buffer"    stdout appends to a buffer
! "out-name": "/path/file" the name of the file or buffer to write to
! "out-buf": number     the number of the buffer to write to  TODO
! 
!                                               *job-err-io*
! "err-io": "out"               same as stdout  TODO
! "err-io": "null"      disconnect stderr  TODO
! "err-io": "pipe"      stderr is connected to the channel (default)
! "err-io": "file"      stderr writes to a file  TODO
! "err-io": "buffer"    stderr appends to a buffer  TODO
! "err-name": "/path/file" the name of the file or buffer to write to
! "err-buf": number     the number of the buffer to write to  TODO
! 
! When the IO mode is "buffer" and there is a callback, the text is appended to
! the buffer before invoking the callback.
  
  The name of the buffer is compared the full name of existing buffers.  If
  there is a match that buffer is used.  Otherwise a new buffer is created.
--- 545,602 ----
  "stoponexit": ""      Do not stop the job when Vim exits.
                        The default is "term".
  
!                                               *job-term*
  "term": "open"                Start a terminal and connect the job
                        stdin/stdout/stderr to it.
+                       NOTE: Not implemented yet!
  
! "channel": {channel}  Use an existing channel instead of creating a new one.
!                       The parts of the channel that get used for the new job
!                       will be disconnected from what they were used before.
!                       If the channel was still use by another job this may
!                       cause I/O errors.
!                       Existing callbacks and other settings remain.
! 
!                               *job-in_io* *in_top* *in_bot* *in_name* *in_buf*
! "in_io": "null"               disconnect stdin (read from /dev/null)
! "in_io": "pipe"               stdin is connected to the channel (default)
! "in_io": "file"               stdin reads from a file
! "in_io": "buffer"     stdin reads from a buffer
! "in_top": number      when using "buffer": first line to send (default: 1)
! "in_bot": number      when using "buffer": last line to send (default: last)
! "in_name": "/path/file"       the name of the file or buffer to read from
! "in_buf": number      the number of the buffer to read from
! 
!                               *job-out_io* *out_name* *out_buf*
! "out_io": "null"      disconnect stdout (goes to /dev/null)
! "out_io": "pipe"      stdout is connected to the channel (default)
! "out_io": "file"      stdout writes to a file
! "out_io": "buffer"    stdout appends to a buffer
! "out_name": "/path/file" the name of the file or buffer to write to
! "out_buf": number     the number of the buffer to write to
! 
!                               *job-err_io* *err_name* *err_buf*
! "err_io": "out"               stderr messages to go to stdout
! "err_io": "null"      disconnect stderr  (goes to /dev/null)
! "err_io": "pipe"      stderr is connected to the channel (default)
! "err_io": "file"      stderr writes to a file
! "err_io": "buffer"    stderr appends to a buffer
! "err_name": "/path/file" the name of the file or buffer to write to
! "err_buf": number     the number of the buffer to write to
! 
! 
! Writing to a buffer ~
! 
! When the out_io or err_io mode is "buffer" and there is a callback, the text
! is appended to the buffer before invoking the callback.
! 
! When a buffer is used both for input and output, the output lines are put
! above the last line, since the last line is what is written to the channel
! input.  Otherwise lines are appended below the last line.
! 
! When using JS or JSON mode with "buffer", only messages with zero or negative
! ID will be added to the buffer, after decoding + encoding.  Messages with a
! positive number will be handled by a callback, commands are handled as usual.
  
  The name of the buffer is compared the full name of existing buffers.  If
  there is a match that buffer is used.  Otherwise a new buffer is created.
***************
*** 576,581 ****
--- 612,625 ----
  
  Undo is synced for every added line.
  
+ 
+ Writing to a file ~
+                                                       *E920*
+ The file is created with permissions 600 (read-write for the user, not
+ accessible for others).  Use |setfperm()| to change this.
+ 
+ If the file already exists it is truncated.
+ 
  ==============================================================================
  11. Controlling a job                                 *job-control*
  
*** ../vim-7.4.1559/src/version.c       2016-03-14 23:04:49.702923020 +0100
--- src/version.c       2016-03-14 23:07:07.277477041 +0100
***************
*** 745,746 ****
--- 745,748 ----
  {   /* Add new patch number below this line */
+ /**/
+     1560,
  /**/

-- 
On the other hand, you have different fingers.
                                      -- Steven Wright

 /// 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