# HG changeset patch # User Bram Moolenaar # Date 1566507603 -7200 # Node ID 4ab97fdf7ff7d00ccb3de5d11c77ca9625c34cd9 # Parent e8805fbb60a3060edc75abdd0918f51086033233 patch 8.1.1912: more functions can be used as methods Commit: https://github.com/vim/vim/commit/570497ac409ad448574bb6210cb9c6e573483759 Author: Bram Moolenaar Date: Thu Aug 22 22:55:13 2019 +0200 patch 8.1.1912: more functions can be used as methods Problem: More functions can be used as methods. Solution: Make channel and job functions usable as a method. diff --git a/runtime/doc/channel.txt b/runtime/doc/channel.txt --- a/runtime/doc/channel.txt +++ b/runtime/doc/channel.txt @@ -1,4 +1,4 @@ -*channel.txt* For Vim version 8.1. Last change: 2019 Jul 28 +*channel.txt* For Vim version 8.1. Last change: 2019 Aug 22 VIM REFERENCE MANUAL by Bram Moolenaar @@ -474,18 +474,25 @@ ch_canread({handle}) *ch_canread()* Note that messages are dropped when the channel does not have a callback. Add a close callback to avoid that. + Can also be used as a |method|: > + GetChannel()->ch_canread() ch_close({handle}) *ch_close()* Close {handle}. See |channel-close|. {handle} can be a Channel or a Job that has a Channel. A close callback is not invoked. + Can also be used as a |method|: > + GetChannel()->ch_close() ch_close_in({handle}) *ch_close_in()* Close the "in" part of {handle}. See |channel-close-in|. {handle} can be a Channel or a Job that has a Channel. A close callback is not invoked. + Can also be used as a |method|: > + GetChannel()->ch_close_in() + ch_evalexpr({handle}, {expr} [, {options}]) *ch_evalexpr()* Send {expr} over {handle}. The {expr} is encoded @@ -501,6 +508,9 @@ ch_evalexpr({handle}, {expr} [, {options expression. When there is an error or timeout it returns an empty string. + Can also be used as a |method|: > + GetChannel()->ch_evalexpr(expr) + ch_evalraw({handle}, {string} [, {options}]) *ch_evalraw()* Send {string} over {handle}. @@ -516,6 +526,8 @@ ch_evalraw({handle}, {string} [, {option need to use |ch_readraw()| to fetch the rest. See |channel-use|. + Can also be used as a |method|: > + GetChannel()->ch_evalraw(rawstring) ch_getbufnr({handle}, {what}) *ch_getbufnr()* Get the buffer number that {handle} is using for {what}. @@ -524,12 +536,17 @@ ch_getbufnr({handle}, {what}) *ch_ge socket output. Returns -1 when there is no buffer. + Can also be used as a |method|: > + GetChannel()->ch_getbufnr(what) ch_getjob({channel}) *ch_getjob()* Get the Job associated with {channel}. If there is no job calling |job_status()| on the returned Job will result in "fail". + Can also be used as a |method|: > + GetChannel()->ch_getjob() + ch_info({handle}) *ch_info()* Returns a Dictionary with information about {handle}. The @@ -558,6 +575,9 @@ ch_info({handle}) *ch_info()* "in_io" "null", "pipe", "file" or "buffer" "in_timeout" timeout in msec + Can also be used as a |method|: > + GetChannel()->ch_info() + ch_log({msg} [, {handle}]) *ch_log()* Write {msg} in the channel log file, if it was opened with @@ -567,6 +587,9 @@ ch_log({msg} [, {handle}]) *ch_log() {handle} can be a Channel or a Job that has a Channel. The Channel must be open for the channel number to be used. + Can also be used as a |method|: > + 'did something'->ch_log() + ch_logfile({fname} [, {mode}]) *ch_logfile()* Start logging channel activity to {fname}. @@ -584,6 +607,9 @@ ch_logfile({fname} [, {mode}]) *ch_l aware that this may contain confidential and privacy sensitive information, e.g. a password you type in a terminal window. + Can also be used as a |method|: > + 'logfile'->ch_logfile('w') + ch_open({address} [, {options}]) *ch_open()* Open a channel to {address}. See |channel|. @@ -595,6 +621,9 @@ ch_open({address} [, {options}]) *ch_ If {options} is given it must be a |Dictionary|. See |channel-open-options|. + Can also be used as a |method|: > + GetAddress()->ch_open() + ch_read({handle} [, {options}]) *ch_read()* Read from {handle} and return the received message. @@ -603,11 +632,17 @@ ch_read({handle} [, {options}]) *ch_ there is nothing more to read (channel was closed). See |channel-more|. + Can also be used as a |method|: > + GetChannel()->ch_read() + ch_readblob({handle} [, {options}]) *ch_readblob()* Like ch_read() but reads binary data and returns a |Blob|. See |channel-more|. + Can also be used as a |method|: > + GetChannel()->ch_readblob() + ch_readraw({handle} [, {options}]) *ch_readraw()* Like ch_read() but for a JS and JSON channel does not decode @@ -615,6 +650,9 @@ ch_readraw({handle} [, {options}]) *ch the NL to arrive, but otherwise works like ch_read(). See |channel-more|. + Can also be used as a |method|: > + GetChannel()->ch_readraw() + ch_sendexpr({handle}, {expr} [, {options}]) *ch_sendexpr()* Send {expr} over {handle}. The {expr} is encoded @@ -623,6 +661,9 @@ ch_sendexpr({handle}, {expr} [, {options See |channel-use|. *E912* {handle} can be a Channel or a Job that has a Channel. + Can also be used as a |method|: > + GetChannel()->ch_sendexpr(expr) + ch_sendraw({handle}, {expr} [, {options}]) *ch_sendraw()* Send |String| or |Blob| {expr} over {handle}. @@ -633,6 +674,9 @@ ch_sendraw({handle}, {expr} [, {options} is removed. See |channel-use|. + Can also be used as a |method|: > + GetChannel()->ch_sendraw(rawexpr) + ch_setoptions({handle}, {options}) *ch_setoptions()* Set options on {handle}: @@ -648,6 +692,9 @@ ch_setoptions({handle}, {options}) *ch These options cannot be changed: "waittime" only applies to |ch_open()| + Can also be used as a |method|: > + GetChannel()->ch_setoptions(options) + ch_status({handle} [, {options}]) *ch_status()* Return the status of {handle}: @@ -664,6 +711,8 @@ ch_status({handle} [, {options}]) *ch "err". For example, to get the error status: > ch_status(job, {"part": "err"}) < + Can also be used as a |method|: > + GetChannel()->ch_status() ============================================================================== 9. Starting a job with a channel *job-start* *job* @@ -792,6 +841,8 @@ job_getchannel({job}) *job_getchann To check if the job has no channel: > if string(job_getchannel()) == 'channel fail' < + Can also be used as a |method|: > + GetJob()->job_getchannel() job_info([{job}]) *job_info()* Returns a Dictionary with information about {job}: @@ -817,12 +868,18 @@ job_info([{job}]) *job_info()* Without any arguments, returns a List with all Job objects. + Can also be used as a |method|: > + GetJob()->job_info() + job_setoptions({job}, {options}) *job_setoptions()* Change options for {job}. Supported are: "stoponexit" |job-stoponexit| "exit_cb" |job-exit_cb| + Can also be used as a |method|: > + GetJob()->job_setoptions(options) + job_start({command} [, {options}]) *job_start()* Start a job and return a Job object. Unlike |system()| and @@ -881,6 +938,9 @@ job_start({command} [, {options}]) *jo {options} must be a Dictionary. It can contain many optional items, see |job-options|. + Can also be used as a |method|: > + BuildCommand()->job_start() + job_status({job}) *job_status()* *E916* Returns a String with the status of {job}: @@ -897,6 +957,9 @@ job_status({job}) *job_status()* *E9 For more information see |job_info()|. + Can also be used as a |method|: > + GetJob()->job_status() + job_stop({job} [, {how}]) *job_stop()* Stop the {job}. This can also be used to signal the job. @@ -940,6 +1003,9 @@ job_stop({job} [, {how}]) *job_stop( When using "kill" Vim will assume the job will die and close the channel. + Can also be used as a |method|: > + GetJob()->job_stop() + ============================================================================== 12. Job options *job-options* diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -474,24 +474,24 @@ static funcentry_T global_functions[] = {"ceil", 1, 1, FEARG_1, f_ceil}, #endif #ifdef FEAT_JOB_CHANNEL - {"ch_canread", 1, 1, 0, f_ch_canread}, - {"ch_close", 1, 1, 0, f_ch_close}, - {"ch_close_in", 1, 1, 0, f_ch_close_in}, - {"ch_evalexpr", 2, 3, 0, f_ch_evalexpr}, - {"ch_evalraw", 2, 3, 0, f_ch_evalraw}, - {"ch_getbufnr", 2, 2, 0, f_ch_getbufnr}, - {"ch_getjob", 1, 1, 0, f_ch_getjob}, - {"ch_info", 1, 1, 0, f_ch_info}, - {"ch_log", 1, 2, 0, f_ch_log}, - {"ch_logfile", 1, 2, 0, f_ch_logfile}, - {"ch_open", 1, 2, 0, f_ch_open}, - {"ch_read", 1, 2, 0, f_ch_read}, - {"ch_readblob", 1, 2, 0, f_ch_readblob}, - {"ch_readraw", 1, 2, 0, f_ch_readraw}, - {"ch_sendexpr", 2, 3, 0, f_ch_sendexpr}, - {"ch_sendraw", 2, 3, 0, f_ch_sendraw}, - {"ch_setoptions", 2, 2, 0, f_ch_setoptions}, - {"ch_status", 1, 2, 0, f_ch_status}, + {"ch_canread", 1, 1, FEARG_1, f_ch_canread}, + {"ch_close", 1, 1, FEARG_1, f_ch_close}, + {"ch_close_in", 1, 1, FEARG_1, f_ch_close_in}, + {"ch_evalexpr", 2, 3, FEARG_1, f_ch_evalexpr}, + {"ch_evalraw", 2, 3, FEARG_1, f_ch_evalraw}, + {"ch_getbufnr", 2, 2, FEARG_1, f_ch_getbufnr}, + {"ch_getjob", 1, 1, FEARG_1, f_ch_getjob}, + {"ch_info", 1, 1, FEARG_1, f_ch_info}, + {"ch_log", 1, 2, FEARG_1, f_ch_log}, + {"ch_logfile", 1, 2, FEARG_1, f_ch_logfile}, + {"ch_open", 1, 2, FEARG_1, f_ch_open}, + {"ch_read", 1, 2, FEARG_1, f_ch_read}, + {"ch_readblob", 1, 2, FEARG_1, f_ch_readblob}, + {"ch_readraw", 1, 2, FEARG_1, f_ch_readraw}, + {"ch_sendexpr", 2, 3, FEARG_1, f_ch_sendexpr}, + {"ch_sendraw", 2, 3, FEARG_1, f_ch_sendraw}, + {"ch_setoptions", 2, 2, FEARG_1, f_ch_setoptions}, + {"ch_status", 1, 2, FEARG_1, f_ch_status}, #endif {"changenr", 0, 0, 0, f_changenr}, {"char2nr", 1, 2, 0, f_char2nr}, @@ -635,12 +635,12 @@ static funcentry_T global_functions[] = #endif {"items", 1, 1, FEARG_1, f_items}, #ifdef FEAT_JOB_CHANNEL - {"job_getchannel", 1, 1, 0, f_job_getchannel}, - {"job_info", 0, 1, 0, f_job_info}, - {"job_setoptions", 2, 2, 0, f_job_setoptions}, - {"job_start", 1, 2, 0, f_job_start}, - {"job_status", 1, 1, 0, f_job_status}, - {"job_stop", 1, 2, 0, f_job_stop}, + {"job_getchannel", 1, 1, FEARG_1, f_job_getchannel}, + {"job_info", 0, 1, FEARG_1, f_job_info}, + {"job_setoptions", 2, 2, FEARG_1, f_job_setoptions}, + {"job_start", 1, 2, FEARG_1, f_job_start}, + {"job_status", 1, 1, FEARG_1, f_job_status}, + {"job_stop", 1, 2, FEARG_1, f_job_stop}, #endif {"join", 1, 2, FEARG_1, f_join}, {"js_decode", 1, 1, 0, f_js_decode}, diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -62,7 +62,7 @@ func Ch_communicate(port) " check that getjob without a job is handled correctly call assert_equal('no process', string(ch_getjob(handle))) - let dict = ch_info(handle) + let dict = handle->ch_info() call assert_true(dict.id != 0) call assert_equal('open', dict.status) call assert_equal(a:port, string(dict.port)) @@ -148,7 +148,7 @@ func Ch_communicate(port) call test_garbagecollect_now() " check setting options (without testing the effect) - call ch_setoptions(handle, {'callback': 's:NotUsed'}) + eval handle->ch_setoptions({'callback': 's:NotUsed'}) call ch_setoptions(handle, {'timeout': 1111}) call ch_setoptions(handle, {'mode': 'json'}) call assert_fails("call ch_setoptions(handle, {'waittime': 111})", "E475") @@ -227,7 +227,7 @@ endfunc func Ch_two_channels(port) let handle = ch_open('localhost:' . a:port, s:chopt) call assert_equal(v:t_channel, type(handle)) - if ch_status(handle) == "fail" + if handle->ch_status() == "fail" call assert_report("Can't open channel") return endif @@ -249,7 +249,7 @@ func Ch_two_channels(port) endfunc func Test_two_channels() - call ch_log('Test_two_channels()') + eval 'Test_two_channels()'->ch_log() call s:run_server('Ch_two_channels') endfunc @@ -321,7 +321,7 @@ func Ch_oneHandler(chan, msg) endfunc func Ch_channel_zero(port) - let handle = ch_open('localhost:' . a:port, s:chopt) + let handle = ('localhost:' .. a:port)->ch_open(s:chopt) if ch_status(handle) == "fail" call assert_report("Can't open channel") return @@ -478,8 +478,8 @@ func Test_raw_pipe() call assert_equal("something\n", substitute(msg, "\r", "", 'g')) call ch_sendraw(job, "double this\n") - let g:handle = job_getchannel(job) - call WaitFor('ch_canread(g:handle)') + let g:handle = job->job_getchannel() + call WaitFor('g:handle->ch_canread()') unlet g:handle let msg = ch_readraw(job) call assert_equal("this\nAND this\n", substitute(msg, "\r", "", 'g')) @@ -488,7 +488,7 @@ func Test_raw_pipe() call ch_sendraw(job, "double this\n", {'callback': 'Ch_handler'}) call WaitForAssert({-> assert_equal("this\nAND this\n", substitute(g:Ch_reply, "\r", "", 'g'))}) - let reply = ch_evalraw(job, "quit\n", {'timeout': 100}) + let reply = job->ch_evalraw("quit\n", {'timeout': 100}) call assert_equal("Goodbye!\n", substitute(reply, "\r", "", 'g')) finally call job_stop(job) @@ -496,7 +496,7 @@ func Test_raw_pipe() let g:Ch_job = job call WaitForAssert({-> assert_equal("dead", job_status(g:Ch_job))}) - let info = job_info(job) + let info = job->job_info() call assert_equal("dead", info.status) call assert_equal("term", info.stoponexit) call assert_equal(2, len(info.cmd)) @@ -534,7 +534,7 @@ func Test_raw_pipe_blob() call ch_sendraw(job, blob) " Read a blob with the reply. - let msg = ch_readblob(job) + let msg = job->ch_readblob() let expected = 'something' for i in range(0, len(expected) - 1) call assert_equal(char2nr(expected[i]), msg[i]) @@ -558,7 +558,7 @@ func Test_nl_pipe() try let handle = job_getchannel(job) call ch_sendraw(handle, "echo something\n") - call assert_equal("something", ch_readraw(handle)) + call assert_equal("something", handle->ch_readraw()) call ch_sendraw(handle, "echoerr wrong\n") call assert_equal("wrong", ch_readraw(handle, {'part': 'err'})) @@ -568,7 +568,7 @@ func Test_nl_pipe() call assert_equal("AND this", ch_readraw(handle)) call ch_sendraw(handle, "split this line\n") - call assert_equal("this linethis linethis line", ch_read(handle)) + call assert_equal("this linethis linethis line", handle->ch_read()) let reply = ch_evalraw(handle, "quit\n") call assert_equal("Goodbye!", reply) @@ -873,7 +873,7 @@ func Run_pipe_through_sort(all, use_buff if !a:use_buffer call assert_equal("run", job_status(job)) call ch_sendraw(job, "ccc\naaa\nddd\nbbb\neee\n") - call ch_close_in(job) + eval job->ch_close_in() endif call WaitForAssert({-> assert_equal("dead", job_status(job))}) @@ -917,7 +917,7 @@ func Test_pipe_to_nameless_buffer() let handle = job_getchannel(job) call ch_sendraw(handle, "echo line one\n") call ch_sendraw(handle, "echo line two\n") - exe ch_getbufnr(handle, "out") . 'sbuf' + exe handle->ch_getbufnr("out") .. 'sbuf' call WaitFor('line("$") >= 3') call assert_equal(['Reading from channel output...', 'line one', 'line two'], getline(1, '$')) bwipe! @@ -1249,7 +1249,7 @@ endfunc func Test_close_and_exit_cb() let g:retdict = {'ret': {}} func g:retdict.close_cb(ch) dict - let self.ret['close_cb'] = job_status(ch_getjob(a:ch)) + let self.ret['close_cb'] = a:ch->ch_getjob()->job_status() endfunc func g:retdict.exit_cb(job, status) dict let self.ret['exit_cb'] = job_status(a:job) @@ -1306,7 +1306,7 @@ endfunc " Test that "unlet handle" in a handler doesn't crash Vim. func Ch_unlet_handle(port) let s:channelfd = ch_open('localhost:' . a:port, s:chopt) - call ch_sendexpr(s:channelfd, "test", {'callback': function('s:UnletHandler')}) + eval s:channelfd->ch_sendexpr("test", {'callback': function('s:UnletHandler')}) call WaitForAssert({-> assert_equal('what?', g:Ch_unletResponse)}) endfunc @@ -1320,7 +1320,7 @@ endfunc let g:Ch_unletResponse = '' func Ch_CloseHandler(handle, msg) let g:Ch_unletResponse = a:msg - call ch_close(s:channelfd) + eval s:channelfd->ch_close() endfunc " Test that "unlet handle" in a handler doesn't crash Vim. @@ -1355,7 +1355,7 @@ func Ch_open_delay(port) call assert_report("Can't open channel") return endif - call assert_equal('got it', ch_evalexpr(channel, 'hello!')) + call assert_equal('got it', channel->ch_evalexpr('hello!')) call ch_close(channel) endfunc @@ -1396,7 +1396,7 @@ function MyExitCb(job, status) endfunc function Ch_test_exit_callback(port) - call job_setoptions(g:currentJob, {'exit_cb': 'MyExitCb'}) + eval g:currentJob->job_setoptions({'exit_cb': 'MyExitCb'}) let g:Ch_exit_job = g:currentJob call assert_equal('MyExitCb', job_info(g:currentJob)['exit_cb']) endfunc @@ -1428,7 +1428,7 @@ endfunction func Test_exit_callback_interval() let g:exit_cb_val = {'start': reltime(), 'end': 0, 'process': 0} - let job = job_start([s:python, '-c', 'import time;time.sleep(0.5)'], {'exit_cb': 'MyExitTimeCb'}) + let job = [s:python, '-c', 'import time;time.sleep(0.5)']->job_start({'exit_cb': 'MyExitTimeCb'}) let g:exit_cb_val.process = job_info(job).process call WaitFor('type(g:exit_cb_val.end) != v:t_number || g:exit_cb_val.end != 0') let elapsed = reltimefloat(g:exit_cb_val.end) @@ -1507,7 +1507,7 @@ endfunc func Test_job_stop_immediately() let g:job = job_start([s:python, '-c', 'import time;time.sleep(10)']) try - call job_stop(g:job) + eval g:job->job_stop() call WaitForAssert({-> assert_equal('dead', job_status(g:job))}) finally call job_stop(g:job, 'kill') @@ -1821,7 +1821,7 @@ func Test_raw_large_data() let outlen = 79999 let want = repeat('X', outlen) . "\n" - call ch_sendraw(job, want) + eval job->ch_sendraw(want) call WaitFor({-> len(g:out) >= outlen}, 10000) call WaitForAssert({-> assert_equal("dead", job_status(job))}) call assert_equal(want, substitute(g:out, '\r', '', 'g')) @@ -1919,7 +1919,7 @@ endfunc " Do this last, it stops any channel log. func Test_zz_nl_err_to_out_pipe() - call ch_logfile('Xlog') + eval 'Xlog'->ch_logfile() call ch_log('Test_zz_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)) diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -762,6 +762,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1912, +/**/ 1911, /**/ 1910,