To: vim_dev@googlegroups.com Subject: Patch 7.4.2039 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.2039 Problem: The Netbeans integration is not tested. Solution: Add a first Netbeans test. Files: src/testdir/test_netbeans.vim, src/testdir/test_netbeans.py, src/testdir/Make_all.mak, src/Makefile, src/testdir/test_channel.vim, src/testdir/shared.vim *** ../vim-7.4.2038/src/testdir/test_netbeans.vim 2016-07-15 17:03:26.807260745 +0200 --- src/testdir/test_netbeans.vim 2016-07-15 16:21:31.779125336 +0200 *************** *** 0 **** --- 1,51 ---- + " Test the netbeans interface. + + if !has('netbeans_intg') + finish + endif + + source shared.vim + + let s:python = PythonProg() + if s:python == '' + " Can't run this test. + finish + endif + + " Run "testfunc" after sarting the server and stop the server afterwards. + func s:run_server(testfunc, ...) + call RunServer('test_netbeans.py', a:testfunc, a:000) + endfunc + + func Nb_basic(port) + call delete("Xnetbeans") + exe 'nbstart :localhost:' . a:port . ':bunny' + call assert_true(has("netbeans_enabled")) + + call WaitFor('len(readfile("Xnetbeans")) > 2') + split +$ Makefile + + " Opening Makefile will result in a setDot command + call WaitFor('len(readfile("Xnetbeans")) > 4') + let pos = getcurpos() + call assert_equal(2, pos[1]) + call assert_equal(20, pos[2]) + close + nbclose + + call WaitFor('len(readfile("Xnetbeans")) > 6') + let lines = readfile("Xnetbeans") + call assert_equal('AUTH bunny', lines[0]) + call assert_equal('0:version=0 "2.5"', lines[1]) + call assert_equal('0:startupDone=0', lines[2]) + call assert_equal('0:fileOpened=0 "Makefile" T F', substitute(lines[3], '".*/', '"', '')) + + call assert_equal('0:disconnect=1', lines[6]) + + call delete("Xnetbeans") + endfunc + + func Test_nb_basic() + call ch_log('Test_nb_basic') + call s:run_server('Nb_basic') + endfunc *** ../vim-7.4.2038/src/testdir/test_netbeans.py 2016-07-15 17:03:26.815260631 +0200 --- src/testdir/test_netbeans.py 2016-07-15 17:06:04.837005846 +0200 *************** *** 0 **** --- 1,91 ---- + #!/usr/bin/python + # + # Server that will communicate with Vim through the netbeans interface. + # Used by test_netbeans.vim. + # + # This requires Python 2.6 or later. + + from __future__ import print_function + import socket + import sys + import time + import threading + + try: + # Python 3 + import socketserver + except ImportError: + # Python 2 + import SocketServer as socketserver + + class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): + + def handle(self): + print("=== socket opened ===") + while True: + try: + received = self.request.recv(4096).decode('utf-8') + except socket.error: + print("=== socket error ===") + break + except IOError: + print("=== socket closed ===") + break + if received == '': + print("=== socket closed ===") + break + print("received: {0}".format(received)) + + # Write the received line into the file, so that the test can check + # what happened. + with open("Xnetbeans", "a") as myfile: + myfile.write(received) + + response = '' + if received.find('Makefile') > 0: + name = received.split('"')[1] + response = '5:putBufferNumber!33 "' + name + '"\n' + response += '5:setDot!1 2/19\n' + elif received.find('disconnect') > 0: + # we're done + self.server.shutdown() + return + + if len(response) > 0: + self.request.sendall(response) + # Write the respoinse into the file, so that the test can knows + # the command was sent. + with open("Xnetbeans", "a") as myfile: + myfile.write('send: ' + response) + + class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): + pass + + def writePortInFile(port): + # Write the port number in Xportnr, so that the test knows it. + f = open("Xportnr", "w") + f.write("{0}".format(port)) + f.close() + + if __name__ == "__main__": + HOST, PORT = "localhost", 0 + + server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler) + ip, port = server.server_address + + # Start a thread with the server. That thread will then start a new thread + # for each connection. + server_thread = threading.Thread(target=server.serve_forever) + server_thread.start() + + writePortInFile(port) + + print("Listening on port {0}".format(port)) + + # Main thread terminates, but the server continues running + # until server.shutdown() is called. + try: + while server_thread.isAlive(): + server_thread.join(1) + except (KeyboardInterrupt, SystemExit): + server.shutdown() *** ../vim-7.4.2038/src/testdir/Make_all.mak 2016-07-13 22:43:47.774233938 +0200 --- src/testdir/Make_all.mak 2016-07-15 13:33:04.995241884 +0200 *************** *** 179,184 **** --- 179,185 ---- test_langmap.res \ test_man.res \ test_matchadd_conceal.res \ + test_netbeans.res \ test_packadd.res \ test_perl.res \ test_quickfix.res \ *** ../vim-7.4.2038/src/Makefile 2016-07-13 22:43:47.774233938 +0200 --- src/Makefile 2016-07-15 13:33:20.899013562 +0200 *************** *** 2055,2060 **** --- 2055,2061 ---- test_matchstrpos \ test_menu \ test_messages \ + test_netbeans \ test_packadd \ test_partial \ test_perl \ *** ../vim-7.4.2038/src/testdir/test_channel.vim 2016-06-27 21:10:28.148544550 +0200 --- src/testdir/test_channel.vim 2016-07-15 16:54:54.090575546 +0200 *************** *** 5,29 **** finish endif ! " This test requires the Python command to run the test server. ! " This most likely only works on Unix and Windows. ! if has('unix') ! " We also need the job feature or the pkill command to make sure the server ! " can be stopped. ! if !(executable('python') && (has('job') || executable('pkill'))) ! finish ! endif ! let s:python = 'python' ! elseif has('win32') ! " Use Python Launcher for Windows (py.exe) if available. ! if executable('py.exe') ! let s:python = 'py.exe' ! elseif executable('python.exe') ! let s:python = 'python.exe' ! else ! finish ! endif ! else " Can't run this test. finish endif --- 5,14 ---- finish endif ! source shared.vim ! ! let s:python = PythonProg() ! if s:python == '' " Can't run this test. finish endif *************** *** 32,119 **** " Run "testfunc" after sarting the server and stop the server afterwards. func s:run_server(testfunc, ...) ! " The Python program writes the port number in Xportnr. ! call delete("Xportnr") ! ! if a:0 == 1 ! let arg = ' ' . a:1 ! else ! let arg = '' ! endif ! let cmd = s:python . " test_channel.py" . arg ! ! try ! if has('job') ! let s:job = job_start(cmd, {"stoponexit": "hup"}) ! call job_setoptions(s:job, {"stoponexit": "kill"}) ! elseif has('win32') ! exe 'silent !start cmd /c start "test_channel" ' . cmd ! else ! exe 'silent !' . cmd . '&' ! endif ! ! " Wait for up to 2 seconds for the port number to be there. ! let l = [] ! for i in range(200) ! try ! let l = readfile("Xportnr") ! catch ! endtry ! if len(l) >= 1 ! break ! endif ! sleep 10m ! endfor ! call delete("Xportnr") ! ! if len(l) == 0 ! " Can't make the connection, give up. ! call assert_false(1, "Can't start test_channel.py") ! return -1 ! endif ! let port = l[0] ! ! call call(function(a:testfunc), [port]) ! catch ! call assert_false(1, "Caught exception: " . v:exception) ! finally ! call s:kill_server() ! endtry ! endfunc ! ! func s:kill_server() ! if has('job') ! if exists('s:job') ! call job_stop(s:job) ! unlet s:job ! endif ! elseif has('win32') ! call system('taskkill /IM ' . s:python . ' /T /F /FI "WINDOWTITLE eq test_channel"') ! else ! call system("pkill -f test_channel.py") ! endif ! endfunc ! ! let s:responseMsg = '' ! func s:RequestHandler(handle, msg) ! let s:responseHandle = a:handle ! let s:responseMsg = a:msg endfunc ! " Wait for up to a second for "expr" to become true. ! func s:waitFor(expr) ! for i in range(100) ! try ! if eval(a:expr) ! return ! endif ! catch ! endtry ! sleep 10m ! endfor endfunc ! func s:communicate(port) let handle = ch_open('localhost:' . a:port, s:chopt) if ch_status(handle) == "fail" call assert_false(1, "Can't open channel") --- 17,32 ---- " Run "testfunc" after sarting the server and stop the server afterwards. func s:run_server(testfunc, ...) ! call RunServer('test_channel.py', a:testfunc, a:000) endfunc ! let g:Ch_responseMsg = '' ! func Ch_requestHandler(handle, msg) ! let g:Ch_responseHandle = a:handle ! let g:Ch_responseMsg = a:msg endfunc ! func Ch_communicate(port) let handle = ch_open('localhost:' . a:port, s:chopt) if ch_status(handle) == "fail" call assert_false(1, "Can't open channel") *************** *** 140,186 **** " split command should work call assert_equal('ok', ch_evalexpr(handle, 'split')) ! call s:waitFor('exists("g:split")') call assert_equal(123, g:split) " Request that triggers sending two ex commands. These will usually be " handled before getting the response, but it's not guaranteed, thus wait a " tiny bit for the commands to get executed. call assert_equal('ok', ch_evalexpr(handle, 'make change')) ! call s:waitFor('"added2" == getline("$")') call assert_equal('added1', getline(line('$') - 1)) call assert_equal('added2', getline('$')) " Request command "foo bar", which fails silently. call assert_equal('ok', ch_evalexpr(handle, 'bad command')) ! call s:waitFor('v:errmsg =~ "E492"') call assert_match('E492:.*foo bar', v:errmsg) call assert_equal('ok', ch_evalexpr(handle, 'do normal', {'timeout': 100})) ! call s:waitFor('"added more" == getline("$")') call assert_equal('added more', getline('$')) " Send a request with a specific handler. ! call ch_sendexpr(handle, 'hello!', {'callback': 's:RequestHandler'}) ! call s:waitFor('exists("s:responseHandle")') ! if !exists('s:responseHandle') ! call assert_false(1, 's:responseHandle was not set') else ! call assert_equal(handle, s:responseHandle) ! unlet s:responseHandle endif ! call assert_equal('got it', s:responseMsg) ! let s:responseMsg = '' ! call ch_sendexpr(handle, 'hello!', {'callback': function('s:RequestHandler')}) ! call s:waitFor('exists("s:responseHandle")') ! if !exists('s:responseHandle') ! call assert_false(1, 's:responseHandle was not set') else ! call assert_equal(handle, s:responseHandle) ! unlet s:responseHandle endif ! call assert_equal('got it', s:responseMsg) " Collect garbage, tests that our handle isn't collected. call test_garbagecollect_now() --- 53,99 ---- " split command should work call assert_equal('ok', ch_evalexpr(handle, 'split')) ! call WaitFor('exists("g:split")') call assert_equal(123, g:split) " Request that triggers sending two ex commands. These will usually be " handled before getting the response, but it's not guaranteed, thus wait a " tiny bit for the commands to get executed. call assert_equal('ok', ch_evalexpr(handle, 'make change')) ! call WaitFor('"added2" == getline("$")') call assert_equal('added1', getline(line('$') - 1)) call assert_equal('added2', getline('$')) " Request command "foo bar", which fails silently. call assert_equal('ok', ch_evalexpr(handle, 'bad command')) ! call WaitFor('v:errmsg =~ "E492"') call assert_match('E492:.*foo bar', v:errmsg) call assert_equal('ok', ch_evalexpr(handle, 'do normal', {'timeout': 100})) ! call WaitFor('"added more" == getline("$")') call assert_equal('added more', getline('$')) " Send a request with a specific handler. ! call ch_sendexpr(handle, 'hello!', {'callback': 'Ch_requestHandler'}) ! call WaitFor('exists("g:Ch_responseHandle")') ! if !exists('g:Ch_responseHandle') ! call assert_false(1, 'g:Ch_responseHandle was not set') else ! call assert_equal(handle, g:Ch_responseHandle) ! unlet g:Ch_responseHandle endif ! call assert_equal('got it', g:Ch_responseMsg) ! let g:Ch_responseMsg = '' ! call ch_sendexpr(handle, 'hello!', {'callback': function('Ch_requestHandler')}) ! call WaitFor('exists("g:Ch_responseHandle")') ! if !exists('g:Ch_responseHandle') ! call assert_false(1, 'g:Ch_responseHandle was not set') else ! call assert_equal(handle, g:Ch_responseHandle) ! unlet g:Ch_responseHandle endif ! call assert_equal('got it', g:Ch_responseMsg) " Collect garbage, tests that our handle isn't collected. call test_garbagecollect_now() *************** *** 225,231 **** " Send an expr request call assert_equal('ok', ch_evalexpr(handle, 'an expr')) ! call s:waitFor('"three" == getline("$")') call assert_equal('one', getline(line('$') - 2)) call assert_equal('two', getline(line('$') - 1)) call assert_equal('three', getline('$')) --- 138,144 ---- " Send an expr request call assert_equal('ok', ch_evalexpr(handle, 'an expr')) ! call WaitFor('"three" == getline("$")') call assert_equal('one', getline(line('$') - 2)) call assert_equal('two', getline(line('$') - 1)) call assert_equal('three', getline('$')) *************** *** 257,267 **** func Test_communicate() call ch_log('Test_communicate()') ! call s:run_server('s:communicate') endfunc " Test that we can open two channels. ! func s:two_channels(port) let handle = ch_open('localhost:' . a:port, s:chopt) if ch_status(handle) == "fail" call assert_false(1, "Can't open channel") --- 170,180 ---- func Test_communicate() call ch_log('Test_communicate()') ! call s:run_server('Ch_communicate') endfunc " Test that we can open two channels. ! func Ch_two_channels(port) let handle = ch_open('localhost:' . a:port, s:chopt) if ch_status(handle) == "fail" call assert_false(1, "Can't open channel") *************** *** 286,296 **** func Test_two_channels() call ch_log('Test_two_channels()') ! call s:run_server('s:two_channels') endfunc " Test that a server crash is handled gracefully. ! func s:server_crash(port) let handle = ch_open('localhost:' . a:port, s:chopt) if ch_status(handle) == "fail" call assert_false(1, "Can't open channel") --- 199,209 ---- func Test_two_channels() call ch_log('Test_two_channels()') ! call s:run_server('Ch_two_channels') endfunc " Test that a server crash is handled gracefully. ! func Ch_server_crash(port) let handle = ch_open('localhost:' . a:port, s:chopt) if ch_status(handle) == "fail" call assert_false(1, "Can't open channel") *************** *** 304,321 **** func Test_server_crash() call ch_log('Test_server_crash()') ! call s:run_server('s:server_crash') endfunc """"""""" ! let s:reply = "" ! func s:Handler(chan, msg) ! unlet s:reply ! let s:reply = a:msg endfunc ! func s:channel_handler(port) let handle = ch_open('localhost:' . a:port, s:chopt) if ch_status(handle) == "fail" call assert_false(1, "Can't open channel") --- 217,234 ---- func Test_server_crash() call ch_log('Test_server_crash()') ! call s:run_server('Ch_server_crash') endfunc """"""""" ! let g:Ch_reply = "" ! func Ch_handler(chan, msg) ! unlet g:Ch_reply ! let g:Ch_reply = a:msg endfunc ! func Ch_channel_handler(port) let handle = ch_open('localhost:' . a:port, s:chopt) if ch_status(handle) == "fail" call assert_false(1, "Can't open channel") *************** *** 324,362 **** " Test that it works while waiting on a numbered message. call assert_equal('ok', ch_evalexpr(handle, 'call me')) ! call s:waitFor('"we called you" == s:reply') ! call assert_equal('we called you', s:reply) " Test that it works while not waiting on a numbered message. call ch_sendexpr(handle, 'call me again') ! call s:waitFor('"we did call you" == s:reply') ! call assert_equal('we did call you', s:reply) endfunc func Test_channel_handler() call ch_log('Test_channel_handler()') ! let s:chopt.callback = 's:Handler' ! call s:run_server('s:channel_handler') ! let s:chopt.callback = function('s:Handler') ! call s:run_server('s:channel_handler') unlet s:chopt.callback endfunc """"""""" ! let s:ch_reply = '' ! func s:ChHandler(chan, msg) ! unlet s:ch_reply ! let s:ch_reply = a:msg endfunc ! let s:zero_reply = '' ! func s:OneHandler(chan, msg) ! unlet s:zero_reply ! let s:zero_reply = a:msg endfunc ! func s:channel_zero(port) let handle = ch_open('localhost:' . a:port, s:chopt) if ch_status(handle) == "fail" call assert_false(1, "Can't open channel") --- 237,275 ---- " Test that it works while waiting on a numbered message. call assert_equal('ok', ch_evalexpr(handle, 'call me')) ! call WaitFor('"we called you" == g:Ch_reply') ! call assert_equal('we called you', g:Ch_reply) " Test that it works while not waiting on a numbered message. call ch_sendexpr(handle, 'call me again') ! call WaitFor('"we did call you" == g:Ch_reply') ! call assert_equal('we did call you', g:Ch_reply) endfunc func Test_channel_handler() call ch_log('Test_channel_handler()') ! let s:chopt.callback = 'Ch_handler' ! call s:run_server('Ch_channel_handler') ! let s:chopt.callback = function('Ch_handler') ! call s:run_server('Ch_channel_handler') unlet s:chopt.callback endfunc """"""""" ! let g:Ch_reply = '' ! func Ch_zeroHandler(chan, msg) ! unlet g:Ch_reply ! let g:Ch_reply = a:msg endfunc ! let g:Ch_zero_reply = '' ! func Ch_oneHandler(chan, msg) ! unlet g:Ch_zero_reply ! let g:Ch_zero_reply = a:msg endfunc ! func Ch_channel_zero(port) let handle = ch_open('localhost:' . a:port, s:chopt) if ch_status(handle) == "fail" call assert_false(1, "Can't open channel") *************** *** 367,429 **** call assert_equal('got it', ch_evalexpr(handle, 'hello!')) " Check that eval works if a zero id message is sent back. ! let s:ch_reply = '' call assert_equal('sent zero', ch_evalexpr(handle, 'send zero')) if s:has_handler ! call s:waitFor('"zero index" == s:ch_reply') ! call assert_equal('zero index', s:ch_reply) else sleep 20m ! call assert_equal('', s:ch_reply) endif " Check that handler works if a zero id message is sent back. ! let s:ch_reply = '' ! let s:zero_reply = '' ! call ch_sendexpr(handle, 'send zero', {'callback': 's:OneHandler'}) ! call s:waitFor('"sent zero" == s:zero_reply') if s:has_handler ! call assert_equal('zero index', s:ch_reply) else ! call assert_equal('', s:ch_reply) endif ! call assert_equal('sent zero', s:zero_reply) endfunc func Test_zero_reply() call ch_log('Test_zero_reply()') " Run with channel handler let s:has_handler = 1 ! let s:chopt.callback = 's:ChHandler' ! call s:run_server('s:channel_zero') unlet s:chopt.callback " Run without channel handler let s:has_handler = 0 ! call s:run_server('s:channel_zero') endfunc """"""""" ! let s:reply1 = "" ! func s:HandleRaw1(chan, msg) ! unlet s:reply1 ! let s:reply1 = a:msg endfunc ! let s:reply2 = "" ! func s:HandleRaw2(chan, msg) ! unlet s:reply2 ! let s:reply2 = a:msg endfunc ! let s:reply3 = "" ! func s:HandleRaw3(chan, msg) ! unlet s:reply3 ! let s:reply3 = a:msg endfunc ! func s:raw_one_time_callback(port) let handle = ch_open('localhost:' . a:port, s:chopt) if ch_status(handle) == "fail" call assert_false(1, "Can't open channel") --- 280,342 ---- call assert_equal('got it', ch_evalexpr(handle, 'hello!')) " Check that eval works if a zero id message is sent back. ! let g:Ch_reply = '' call assert_equal('sent zero', ch_evalexpr(handle, 'send zero')) if s:has_handler ! call WaitFor('"zero index" == g:Ch_reply') ! call assert_equal('zero index', g:Ch_reply) else sleep 20m ! call assert_equal('', g:Ch_reply) endif " Check that handler works if a zero id message is sent back. ! let g:Ch_reply = '' ! let g:Ch_zero_reply = '' ! call ch_sendexpr(handle, 'send zero', {'callback': 'Ch_oneHandler'}) ! call WaitFor('"sent zero" == g:Ch_zero_reply') if s:has_handler ! call assert_equal('zero index', g:Ch_reply) else ! call assert_equal('', g:Ch_reply) endif ! call assert_equal('sent zero', g:Ch_zero_reply) endfunc func Test_zero_reply() call ch_log('Test_zero_reply()') " Run with channel handler let s:has_handler = 1 ! let s:chopt.callback = 'Ch_zeroHandler' ! call s:run_server('Ch_channel_zero') unlet s:chopt.callback " Run without channel handler let s:has_handler = 0 ! call s:run_server('Ch_channel_zero') endfunc """"""""" ! let g:Ch_reply1 = "" ! func Ch_handleRaw1(chan, msg) ! unlet g:Ch_reply1 ! let g:Ch_reply1 = a:msg endfunc ! let g:Ch_reply2 = "" ! func Ch_handleRaw2(chan, msg) ! unlet g:Ch_reply2 ! let g:Ch_reply2 = a:msg endfunc ! let g:Ch_reply3 = "" ! func Ch_handleRaw3(chan, msg) ! unlet g:Ch_reply3 ! let g:Ch_reply3 = a:msg endfunc ! func Ch_raw_one_time_callback(port) let handle = ch_open('localhost:' . a:port, s:chopt) if ch_status(handle) == "fail" call assert_false(1, "Can't open channel") *************** *** 432,452 **** call ch_setoptions(handle, {'mode': 'raw'}) " The message are sent raw, we do our own JSON strings here. ! call ch_sendraw(handle, "[1, \"hello!\"]", {'callback': 's:HandleRaw1'}) ! call s:waitFor('s:reply1 != ""') ! call assert_equal("[1, \"got it\"]", s:reply1) ! call ch_sendraw(handle, "[2, \"echo something\"]", {'callback': 's:HandleRaw2'}) ! call ch_sendraw(handle, "[3, \"wait a bit\"]", {'callback': 's:HandleRaw3'}) ! call s:waitFor('s:reply2 != ""') ! call assert_equal("[2, \"something\"]", s:reply2) " wait for the 200 msec delayed reply ! call s:waitFor('s:reply3 != ""') ! call assert_equal("[3, \"waited\"]", s:reply3) endfunc func Test_raw_one_time_callback() call ch_log('Test_raw_one_time_callback()') ! call s:run_server('s:raw_one_time_callback') endfunc """"""""" --- 345,365 ---- call ch_setoptions(handle, {'mode': 'raw'}) " The message are sent raw, we do our own JSON strings here. ! call ch_sendraw(handle, "[1, \"hello!\"]", {'callback': 'Ch_handleRaw1'}) ! call WaitFor('g:Ch_reply1 != ""') ! call assert_equal("[1, \"got it\"]", g:Ch_reply1) ! call ch_sendraw(handle, "[2, \"echo something\"]", {'callback': 'Ch_handleRaw2'}) ! call ch_sendraw(handle, "[3, \"wait a bit\"]", {'callback': 'Ch_handleRaw3'}) ! call WaitFor('g:Ch_reply2 != ""') ! call assert_equal("[2, \"something\"]", g:Ch_reply2) " wait for the 200 msec delayed reply ! call WaitFor('g:Ch_reply3 != ""') ! call assert_equal("[3, \"waited\"]", g:Ch_reply3) endfunc func Test_raw_one_time_callback() call ch_log('Test_raw_one_time_callback()') ! call s:run_server('Ch_raw_one_time_callback') endfunc """"""""" *************** *** 512,519 **** call job_stop(job) endtry ! let s:job = job ! call s:waitFor('"dead" == job_status(s:job)') let info = job_info(job) call assert_equal("dead", info.status) call assert_equal("term", info.stoponexit) --- 425,432 ---- call job_stop(job) endtry ! let g:Ch_job = job ! call WaitFor('"dead" == job_status(g:Ch_job)') let info = job_info(job) call assert_equal("dead", info.status) call assert_equal("term", info.stoponexit) *************** *** 628,634 **** call ch_sendraw(handle, "echo line one\n") call ch_sendraw(handle, "echo line two\n") call ch_sendraw(handle, "double this\n") ! call s:waitFor('len(readfile("Xoutput")) > 2') call assert_equal(['line one', 'line two', 'this', 'AND this'], readfile('Xoutput')) finally call job_stop(job) --- 541,547 ---- call ch_sendraw(handle, "echo line one\n") call ch_sendraw(handle, "echo line two\n") call ch_sendraw(handle, "double this\n") ! call WaitFor('len(readfile("Xoutput")) > 2') call assert_equal(['line one', 'line two', 'this', 'AND this'], readfile('Xoutput')) finally call job_stop(job) *************** *** 649,655 **** call ch_sendraw(handle, "echoerr line one\n") call ch_sendraw(handle, "echoerr line two\n") call ch_sendraw(handle, "doubleerr this\n") ! call s:waitFor('len(readfile("Xoutput")) > 2') call assert_equal(['line one', 'line two', 'this', 'AND this'], readfile('Xoutput')) finally call job_stop(job) --- 562,568 ---- call ch_sendraw(handle, "echoerr line one\n") call ch_sendraw(handle, "echoerr line two\n") call ch_sendraw(handle, "doubleerr this\n") ! call WaitFor('len(readfile("Xoutput")) > 2') call assert_equal(['line one', 'line two', 'this', 'AND this'], readfile('Xoutput')) finally call job_stop(job) *************** *** 671,677 **** call ch_sendraw(handle, "echo line two\n") call ch_sendraw(handle, "double this\n") call ch_sendraw(handle, "doubleerr that\n") ! call s:waitFor('len(readfile("Xoutput")) > 5') call assert_equal(['line one', 'line two', 'this', 'AND this', 'that', 'AND that'], readfile('Xoutput')) finally call job_stop(job) --- 584,590 ---- call ch_sendraw(handle, "echo line two\n") call ch_sendraw(handle, "double this\n") call ch_sendraw(handle, "doubleerr that\n") ! call WaitFor('len(readfile("Xoutput")) > 5') call assert_equal(['line one', 'line two', 'this', 'AND this', 'that', 'AND that'], readfile('Xoutput')) finally call job_stop(job) *************** *** 680,686 **** endfunc func BufCloseCb(ch) ! let s:bufClosed = 'yes' endfunc func Run_test_pipe_to_buffer(use_name, nomod) --- 593,599 ---- endfunc func BufCloseCb(ch) ! let g:Ch_bufClosed = 'yes' endfunc func Run_test_pipe_to_buffer(use_name, nomod) *************** *** 688,694 **** return endif call ch_log('Test_pipe_to_buffer()') ! let s:bufClosed = 'no' let options = {'out_io': 'buffer', 'close_cb': 'BufCloseCb'} if a:use_name let options['out_name'] = 'pipe-output' --- 601,607 ---- return endif call ch_log('Test_pipe_to_buffer()') ! let g:Ch_bufClosed = 'no' let options = {'out_io': 'buffer', 'close_cb': 'BufCloseCb'} if a:use_name let options['out_name'] = 'pipe-output' *************** *** 711,724 **** call ch_sendraw(handle, "double this\n") call ch_sendraw(handle, "quit\n") sp pipe-output ! call s:waitFor('line("$") >= 6 && s:bufClosed == "yes"') call assert_equal([firstline, 'line one', 'line two', 'this', 'AND this', 'Goodbye!'], getline(1, '$')) if a:nomod call assert_equal(0, &modifiable) else call assert_equal(1, &modifiable) endif ! call assert_equal('yes', s:bufClosed) bwipe! finally call job_stop(job) --- 624,637 ---- call ch_sendraw(handle, "double this\n") call ch_sendraw(handle, "quit\n") sp pipe-output ! call WaitFor('line("$") >= 6 && g:Ch_bufClosed == "yes"') call assert_equal([firstline, 'line one', 'line two', 'this', 'AND this', 'Goodbye!'], getline(1, '$')) if a:nomod call assert_equal(0, &modifiable) else call assert_equal(1, &modifiable) endif ! call assert_equal('yes', g:Ch_bufClosed) bwipe! finally call job_stop(job) *************** *** 764,770 **** call ch_sendraw(handle, "doubleerr this\n") call ch_sendraw(handle, "quit\n") sp pipe-err ! call s:waitFor('line("$") >= 5') call assert_equal([firstline, 'line one', 'line two', 'this', 'AND this'], getline(1, '$')) if a:nomod call assert_equal(0, &modifiable) --- 677,683 ---- call ch_sendraw(handle, "doubleerr this\n") call ch_sendraw(handle, "quit\n") sp pipe-err ! call WaitFor('line("$") >= 5') call assert_equal([firstline, 'line one', 'line two', 'this', 'AND this'], getline(1, '$')) if a:nomod call assert_equal(0, &modifiable) *************** *** 805,811 **** call ch_sendraw(handle, "doubleerr that\n") call ch_sendraw(handle, "quit\n") sp pipe-err ! call s:waitFor('line("$") >= 7') call assert_equal(['Reading from channel output...', 'line one', 'line two', 'this', 'AND this', 'that', 'AND that', 'Goodbye!'], getline(1, '$')) bwipe! finally --- 718,724 ---- call ch_sendraw(handle, "doubleerr that\n") call ch_sendraw(handle, "quit\n") sp pipe-err ! call WaitFor('line("$") >= 7') call assert_equal(['Reading from channel output...', 'line one', 'line two', 'this', 'AND this', 'that', 'AND that', 'Goodbye!'], getline(1, '$')) bwipe! finally *************** *** 862,868 **** call ch_sendraw(handle, "echo line one\n") call ch_sendraw(handle, "echo line two\n") exe ch_getbufnr(handle, "out") . 'sbuf' ! call s:waitFor('line("$") >= 3') call assert_equal(['Reading from channel output...', 'line one', 'line two'], getline(1, '$')) bwipe! finally --- 775,781 ---- call ch_sendraw(handle, "echo line one\n") call ch_sendraw(handle, "echo line two\n") exe ch_getbufnr(handle, "out") . 'sbuf' ! call WaitFor('line("$") >= 3') call assert_equal(['Reading from channel output...', 'line one', 'line two'], getline(1, '$')) bwipe! finally *************** *** 883,889 **** call ch_sendraw(handle, "echo [0, \"hello\"]\n") call ch_sendraw(handle, "echo [-2, 12.34]\n") exe ch_getbufnr(handle, "out") . 'sbuf' ! call s:waitFor('line("$") >= 3') call assert_equal(['Reading from channel output...', '[0,"hello"]', '[-2,12.34]'], getline(1, '$')) bwipe! finally --- 796,802 ---- call ch_sendraw(handle, "echo [0, \"hello\"]\n") call ch_sendraw(handle, "echo [-2, 12.34]\n") exe ch_getbufnr(handle, "out") . 'sbuf' ! call WaitFor('line("$") >= 3') call assert_equal(['Reading from channel output...', '[0,"hello"]', '[-2,12.34]'], getline(1, '$')) bwipe! finally *************** *** 1028,1034 **** let job = job_start([s:python, '-c', \ 'import sys; [sys.stdout.write(".") and sys.stdout.flush() for _ in range(10000)]'], options) call assert_equal("run", job_status(job)) ! call s:waitFor('len(join(getline(2,line("$")),"") >= 10000') try for line in getline(2, '$') let line = substitute(line, '^\.*', '', '') --- 941,947 ---- let job = job_start([s:python, '-c', \ 'import sys; [sys.stdout.write(".") and sys.stdout.flush() for _ in range(10000)]'], options) call assert_equal("run", job_status(job)) ! call WaitFor('len(join(getline(2,line("$")),"") >= 10000') try for line in getline(2, '$') let line = substitute(line, '^\.*', '', '') *************** *** 1075,1084 **** let dict = {'thisis': 'dict: '} func dict.outHandler(chan, msg) dict ! let s:outmsg = self.thisis . a:msg endfunc func dict.errHandler(chan, msg) dict ! let s:errmsg = self.thisis . a:msg endfunc let job = job_start(s:python . " test_channel_pipe.py", \ {'out_cb': dict.outHandler, --- 988,997 ---- let dict = {'thisis': 'dict: '} func dict.outHandler(chan, msg) dict ! let g:Ch_outmsg = self.thisis . a:msg endfunc func dict.errHandler(chan, msg) dict ! let g:Ch_errmsg = self.thisis . a:msg endfunc let job = job_start(s:python . " test_channel_pipe.py", \ {'out_cb': dict.outHandler, *************** *** 1087,1100 **** \ 'err_mode': 'json'}) call assert_equal("run", job_status(job)) try ! let s:outmsg = '' ! let s:errmsg = '' call ch_sendraw(job, "echo [0, \"hello\"]\n") call ch_sendraw(job, "echoerr [0, \"there\"]\n") ! call s:waitFor('s:outmsg != ""') ! call assert_equal("dict: hello", s:outmsg) ! call s:waitFor('s:errmsg != ""') ! call assert_equal("dict: there", s:errmsg) finally call job_stop(job) endtry --- 1000,1013 ---- \ 'err_mode': 'json'}) call assert_equal("run", job_status(job)) try ! let g:Ch_outmsg = '' ! let g:Ch_errmsg = '' call ch_sendraw(job, "echo [0, \"hello\"]\n") call ch_sendraw(job, "echoerr [0, \"there\"]\n") ! call WaitFor('g:Ch_outmsg != ""') ! call assert_equal("dict: hello", g:Ch_outmsg) ! call WaitFor('g:Ch_errmsg != ""') ! call assert_equal("dict: there", g:Ch_errmsg) finally call job_stop(job) endtry *************** *** 1107,1122 **** call ch_log('Test_out_close_cb()') let s:counter = 1 ! let s:msg1 = '' ! let s:closemsg = 0 func! OutHandler(chan, msg) if s:counter == 1 ! let s:msg1 = a:msg endif let s:counter += 1 endfunc func! CloseHandler(chan) ! let s:closemsg = s:counter let s:counter += 1 endfunc let job = job_start(s:python . " test_channel_pipe.py quit now", --- 1020,1035 ---- call ch_log('Test_out_close_cb()') let s:counter = 1 ! let g:Ch_msg1 = '' ! let g:Ch_closemsg = 0 func! OutHandler(chan, msg) if s:counter == 1 ! let g:Ch_msg1 = a:msg endif let s:counter += 1 endfunc func! CloseHandler(chan) ! let g:Ch_closemsg = s:counter let s:counter += 1 endfunc let job = job_start(s:python . " test_channel_pipe.py quit now", *************** *** 1124,1132 **** \ 'close_cb': 'CloseHandler'}) call assert_equal("run", job_status(job)) try ! call s:waitFor('s:closemsg != 0 && s:msg1 != ""') ! call assert_equal('quit', s:msg1) ! call assert_equal(2, s:closemsg) finally call job_stop(job) delfunc OutHandler --- 1037,1045 ---- \ 'close_cb': 'CloseHandler'}) call assert_equal("run", job_status(job)) try ! call WaitFor('g:Ch_closemsg != 0 && g:Ch_msg1 != ""') ! call assert_equal('quit', g:Ch_msg1) ! call assert_equal(2, g:Ch_closemsg) finally call job_stop(job) delfunc OutHandler *************** *** 1140,1155 **** endif call ch_log('Test_read_in_close_cb()') ! let s:received = '' func! CloseHandler(chan) ! let s:received = ch_read(a:chan) endfunc let job = job_start(s:python . " test_channel_pipe.py quit now", \ {'close_cb': 'CloseHandler'}) call assert_equal("run", job_status(job)) try ! call s:waitFor('s:received != ""') ! call assert_equal('quit', s:received) finally call job_stop(job) delfunc CloseHandler --- 1053,1068 ---- endif call ch_log('Test_read_in_close_cb()') ! let g:Ch_received = '' func! CloseHandler(chan) ! let g:Ch_received = ch_read(a:chan) endfunc let job = job_start(s:python . " test_channel_pipe.py quit now", \ {'close_cb': 'CloseHandler'}) call assert_equal("run", job_status(job)) try ! call WaitFor('g:Ch_received != ""') ! call assert_equal('quit', g:Ch_received) finally call job_stop(job) delfunc CloseHandler *************** *** 1158,1201 **** """""""""" ! let s:unletResponse = '' func s:UnletHandler(handle, msg) ! let s:unletResponse = a:msg unlet s:channelfd endfunc " Test that "unlet handle" in a handler doesn't crash Vim. ! func s:unlet_handle(port) let s:channelfd = ch_open('localhost:' . a:port, s:chopt) call ch_sendexpr(s:channelfd, "test", {'callback': function('s:UnletHandler')}) ! call s:waitFor('"what?" == s:unletResponse') ! call assert_equal('what?', s:unletResponse) endfunc func Test_unlet_handle() call ch_log('Test_unlet_handle()') ! call s:run_server('s:unlet_handle') endfunc """""""""" ! let s:unletResponse = '' ! func s:CloseHandler(handle, msg) ! let s:unletResponse = a:msg call ch_close(s:channelfd) endfunc " Test that "unlet handle" in a handler doesn't crash Vim. ! func s:close_handle(port) let s:channelfd = ch_open('localhost:' . a:port, s:chopt) ! call ch_sendexpr(s:channelfd, "test", {'callback': function('s:CloseHandler')}) ! call s:waitFor('"what?" == s:unletResponse') ! call assert_equal('what?', s:unletResponse) endfunc func Test_close_handle() call ch_log('Test_close_handle()') ! call s:run_server('s:close_handle') endfunc """""""""" --- 1071,1114 ---- """""""""" ! let g:Ch_unletResponse = '' func s:UnletHandler(handle, msg) ! let g:Ch_unletResponse = a:msg unlet s:channelfd 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')}) ! call WaitFor('"what?" == g:Ch_unletResponse') ! call assert_equal('what?', g:Ch_unletResponse) endfunc func Test_unlet_handle() call ch_log('Test_unlet_handle()') ! call s:run_server('Ch_unlet_handle') endfunc """""""""" ! let g:Ch_unletResponse = '' ! func Ch_CloseHandler(handle, msg) ! let g:Ch_unletResponse = a:msg call ch_close(s:channelfd) endfunc " Test that "unlet handle" in a handler doesn't crash Vim. ! func Ch_close_handle(port) let s:channelfd = ch_open('localhost:' . a:port, s:chopt) ! call ch_sendexpr(s:channelfd, "test", {'callback': function('Ch_CloseHandler')}) ! call WaitFor('"what?" == g:Ch_unletResponse') ! call assert_equal('what?', g:Ch_unletResponse) endfunc func Test_close_handle() call ch_log('Test_close_handle()') ! call s:run_server('Ch_close_handle') endfunc """""""""" *************** *** 1209,1215 **** """""""""" ! func s:open_delay(port) " Wait up to a second for the port to open. let s:chopt.waittime = 1000 let channel = ch_open('localhost:' . a:port, s:chopt) --- 1122,1128 ---- """""""""" ! func Ch_open_delay(port) " Wait up to a second for the port to open. let s:chopt.waittime = 1000 let channel = ch_open('localhost:' . a:port, s:chopt) *************** *** 1225,1299 **** func Test_open_delay() call ch_log('Test_open_delay()') " The server will wait half a second before creating the port. ! call s:run_server('s:open_delay', 'delay') endfunc """"""""" function MyFunction(a,b,c) ! let s:call_ret = [a:a, a:b, a:c] endfunc ! function s:test_call(port) let handle = ch_open('localhost:' . a:port, s:chopt) if ch_status(handle) == "fail" call assert_false(1, "Can't open channel") return endif ! let s:call_ret = [] call assert_equal('ok', ch_evalexpr(handle, 'call-func')) ! call s:waitFor('len(s:call_ret) > 0') ! call assert_equal([1, 2, 3], s:call_ret) endfunc func Test_call() call ch_log('Test_call()') ! call s:run_server('s:test_call') endfunc """"""""" ! let s:job_exit_ret = 'not yet' function MyExitCb(job, status) ! let s:job_exit_ret = 'done' 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() if has('job') call ch_log('Test_exit_callback()') ! call s:run_server('s:test_exit_callback') " wait up to a second for the job to exit for i in range(100) ! if s:job_exit_ret == 'done' break endif sleep 10m " calling job_status() triggers the callback ! call job_status(s:exit_job) endfor ! call assert_equal('done', s:job_exit_ret) ! call assert_equal('dead', job_info(s:exit_job).status) ! unlet s:exit_job endif endfunc """"""""" ! let s:ch_close_ret = 'alive' function MyCloseCb(ch) ! let s:ch_close_ret = 'closed' endfunc ! function s:test_close_callback(port) let handle = ch_open('localhost:' . a:port, s:chopt) if ch_status(handle) == "fail" call assert_false(1, "Can't open channel") --- 1138,1212 ---- func Test_open_delay() call ch_log('Test_open_delay()') " The server will wait half a second before creating the port. ! call s:run_server('Ch_open_delay', 'delay') endfunc """"""""" function MyFunction(a,b,c) ! let g:Ch_call_ret = [a:a, a:b, a:c] endfunc ! function Ch_test_call(port) let handle = ch_open('localhost:' . a:port, s:chopt) if ch_status(handle) == "fail" call assert_false(1, "Can't open channel") return endif ! let g:Ch_call_ret = [] call assert_equal('ok', ch_evalexpr(handle, 'call-func')) ! call WaitFor('len(g:Ch_call_ret) > 0') ! call assert_equal([1, 2, 3], g:Ch_call_ret) endfunc func Test_call() call ch_log('Test_call()') ! call s:run_server('Ch_test_call') endfunc """"""""" ! let g:Ch_job_exit_ret = 'not yet' function MyExitCb(job, status) ! let g:Ch_job_exit_ret = 'done' endfunc ! function Ch_test_exit_callback(port) ! call job_setoptions(g:currentJob, {'exit_cb': 'MyExitCb'}) ! let g:Ch_exit_job = g:currentJob ! call assert_equal('MyExitCb', job_info(g:currentJob)['exit_cb']) endfunc func Test_exit_callback() if has('job') call ch_log('Test_exit_callback()') ! call s:run_server('Ch_test_exit_callback') " wait up to a second for the job to exit for i in range(100) ! if g:Ch_job_exit_ret == 'done' break endif sleep 10m " calling job_status() triggers the callback ! call job_status(g:Ch_exit_job) endfor ! call assert_equal('done', g:Ch_job_exit_ret) ! call assert_equal('dead', job_info(g:Ch_exit_job).status) ! unlet g:Ch_exit_job endif endfunc """"""""" ! let g:Ch_close_ret = 'alive' function MyCloseCb(ch) ! let g:Ch_close_ret = 'closed' endfunc ! function Ch_test_close_callback(port) let handle = ch_open('localhost:' . a:port, s:chopt) if ch_status(handle) == "fail" call assert_false(1, "Can't open channel") *************** *** 1302,1337 **** call ch_setoptions(handle, {'close_cb': 'MyCloseCb'}) call assert_equal('', ch_evalexpr(handle, 'close me')) ! call s:waitFor('"closed" == s:ch_close_ret') ! call assert_equal('closed', s:ch_close_ret) endfunc func Test_close_callback() call ch_log('Test_close_callback()') ! call s:run_server('s:test_close_callback') endfunc ! function s:test_close_partial(port) let handle = ch_open('localhost:' . a:port, s:chopt) if ch_status(handle) == "fail" call assert_false(1, "Can't open channel") return endif ! let s:d = {} ! func s:d.closeCb(ch) dict let self.close_ret = 'closed' endfunc ! call ch_setoptions(handle, {'close_cb': s:d.closeCb}) call assert_equal('', ch_evalexpr(handle, 'close me')) ! call s:waitFor('"closed" == s:d.close_ret') ! call assert_equal('closed', s:d.close_ret) ! unlet s:d endfunc func Test_close_partial() call ch_log('Test_close_partial()') ! call s:run_server('s:test_close_partial') endfunc func Test_job_start_invalid() --- 1215,1250 ---- call ch_setoptions(handle, {'close_cb': 'MyCloseCb'}) call assert_equal('', ch_evalexpr(handle, 'close me')) ! call WaitFor('"closed" == g:Ch_close_ret') ! call assert_equal('closed', g:Ch_close_ret) endfunc func Test_close_callback() call ch_log('Test_close_callback()') ! call s:run_server('Ch_test_close_callback') endfunc ! function Ch_test_close_partial(port) let handle = ch_open('localhost:' . a:port, s:chopt) if ch_status(handle) == "fail" call assert_false(1, "Can't open channel") return endif ! let g:Ch_d = {} ! func g:Ch_d.closeCb(ch) dict let self.close_ret = 'closed' endfunc ! call ch_setoptions(handle, {'close_cb': g:Ch_d.closeCb}) call assert_equal('', ch_evalexpr(handle, 'close me')) ! call WaitFor('"closed" == g:Ch_d.close_ret') ! call assert_equal('closed', g:Ch_d.close_ret) ! unlet g:Ch_d endfunc func Test_close_partial() call ch_log('Test_close_partial()') ! call s:run_server('Ch_test_close_partial') endfunc func Test_job_start_invalid() *************** *** 1367,1377 **** split testout 1,$delete call job_start('cat test_channel.vim', {'out_io': 'buffer', 'out_name': 'testout'}) ! call s:waitFor('line("$") > g:linecount') call assert_true(line('$') > g:linecount) bwipe! endfunc " Uncomment this to see what happens, output is in src/testdir/channellog. ! " call ch_logfile('channellog', 'w') --- 1280,1290 ---- split testout 1,$delete call job_start('cat test_channel.vim', {'out_io': 'buffer', 'out_name': 'testout'}) ! call WaitFor('line("$") > g:linecount') call assert_true(line('$') > g:linecount) bwipe! endfunc " Uncomment this to see what happens, output is in src/testdir/channellog. ! call ch_logfile('channellog', 'w') *** ../vim-7.4.2038/src/testdir/shared.vim 2016-07-15 17:03:53.698877032 +0200 --- src/testdir/shared.vim 2016-07-15 16:25:11.275996150 +0200 *************** *** 0 **** --- 1,122 ---- + " Functions shared by several tests. + + " Get the name of the Python executable. + " Also keeps it in s:python. + func PythonProg() + " This test requires the Python command to run the test server. + " This most likely only works on Unix and Windows. + if has('unix') + " We also need the job feature or the pkill command to make sure the server + " can be stopped. + if !(executable('python') && (has('job') || executable('pkill'))) + return '' + endif + let s:python = 'python' + elseif has('win32') + " Use Python Launcher for Windows (py.exe) if available. + if executable('py.exe') + let s:python = 'py.exe' + elseif executable('python.exe') + let s:python = 'python.exe' + else + return '' + endif + else + return '' + endif + return s:python + endfunc + + " Run "cmd". Returns the job if using a job. + func RunCommand(cmd) + let job = 0 + if has('job') + let job = job_start(a:cmd, {"stoponexit": "hup"}) + call job_setoptions(job, {"stoponexit": "kill"}) + elseif has('win32') + exe 'silent !start cmd /c start "test_channel" ' . a:cmd + else + exe 'silent !' . a:cmd . '&' + endif + return job + endfunc + + " Read the port number from the Xportnr file. + func GetPort() + let l = [] + for i in range(200) + try + let l = readfile("Xportnr") + catch + endtry + if len(l) >= 1 + break + endif + sleep 10m + endfor + call delete("Xportnr") + + if len(l) == 0 + " Can't make the connection, give up. + return 0 + endif + return l[0] + endfunc + + " Run a Python server for "cmd" and call "testfunc". + " Always kills the server before returning. + func RunServer(cmd, testfunc, args) + " The Python program writes the port number in Xportnr. + call delete("Xportnr") + + if len(a:args) == 1 + let arg = ' ' . a:args[0] + else + let arg = '' + endif + let pycmd = s:python . " " . a:cmd . arg + + try + let g:currentJob = RunCommand(pycmd) + + " Wait for up to 2 seconds for the port number to be there. + let port = GetPort() + if port == 0 + call assert_false(1, "Can't start " . a:cmd) + return + endif + + call call(function(a:testfunc), [port]) + catch + call assert_false(1, "Caught exception: " . v:exception) + finally + call s:kill_server(a:cmd) + endtry + endfunc + + func s:kill_server(cmd) + if has('job') + if exists('g:currentJob') + call job_stop(g:currentJob) + unlet g:currentJob + endif + elseif has('win32') + let cmd = substitute(a:cmd, ".py", '', '') + call system('taskkill /IM ' . s:python . ' /T /F /FI "WINDOWTITLE eq ' . cmd . '"') + else + call system("pkill -f " . a:cmd) + endif + endfunc + + " Wait for up to a second for "expr" to become true. + func WaitFor(expr) + for i in range(100) + try + if eval(a:expr) + return + endif + catch + endtry + sleep 10m + endfor + endfunc *** ../vim-7.4.2038/src/version.c 2016-07-14 23:03:15.116509331 +0200 --- src/version.c 2016-07-15 16:25:39.111599311 +0200 *************** *** 760,761 **** --- 760,763 ---- { /* Add new patch number below this line */ + /**/ + 2039, /**/ -- The psychic said, "God bless you." I said, "I didn't sneeze." She looked deep into my eyes and said, "You will, eventually." And, damn if she wasn't right. Two days later, I sneezed. --Ellen Degeneres /// Bram Moolenaar -- Bram@Moolenaar.net -- 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 ///