To: vim_dev@googlegroups.com Subject: Patch 8.2.0509 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0509 Problem: various code is not properly tested. Solution: Add more tests. (Yegappan Lakshmanan, closes #5871) Files: src/main.c, src/testdir/check.vim, src/testdir/shared.vim, src/testdir/term_util.vim, src/testdir/test_clientserver.vim, src/testdir/test_ex_mode.vim, src/testdir/test_expand.vim, src/testdir/test_functions.vim, src/testdir/test_options.vim, src/testdir/test_startup.vim, src/testdir/test_textformat.vim, src/testdir/test_trycatch.vim, src/testdir/test_viminfo.vim *** ../vim-8.2.0508/src/main.c 2020-02-14 13:21:55.646197062 +0100 --- src/main.c 2020-04-04 13:36:02.729150119 +0200 *************** *** 1966,1972 **** #endif } ! // Checking for "ex" here may catch some weir names, such as "vimex" or // "viewex", we assume the user knows that. if (STRNICMP(initstr, "ex", 2) == 0) { --- 1966,1972 ---- #endif } ! // Checking for "ex" here may catch some weird names, such as "vimex" or // "viewex", we assume the user knows that. if (STRNICMP(initstr, "ex", 2) == 0) { *** ../vim-8.2.0508/src/testdir/check.vim 2020-03-26 22:16:44.307582067 +0100 --- src/testdir/check.vim 2020-04-04 13:36:02.729150119 +0200 *************** *** 133,135 **** --- 133,145 ---- throw 'Skipped: cannot run test as root' endif endfunc + + " Command to check that the current language is English + command CheckEnglish call CheckEnglish() + func CheckEnglish() + if v:lang != "C" && v:lang !~ '^[Ee]n' + throw 'Skipped: only works in English language environment' + endif + endfunc + + " vim: shiftwidth=2 sts=2 expandtab *** ../vim-8.2.0508/src/testdir/shared.vim 2020-01-30 18:24:46.997204019 +0100 --- src/testdir/shared.vim 2020-04-04 13:36:02.729150119 +0200 *************** *** 337,339 **** --- 337,341 ---- endif return v:false endfunc + + " vim: shiftwidth=2 sts=2 expandtab *** ../vim-8.2.0508/src/testdir/term_util.vim 2020-03-18 21:10:41.104567492 +0100 --- src/testdir/term_util.vim 2020-04-04 13:36:02.729150119 +0200 *************** *** 82,87 **** --- 82,89 ---- let cols = term_getsize(buf)[1] endif + call term_wait(buf) + " Wait for "All" or "Top" of the ruler to be shown in the last line or in " the status line of the last window. This can be quite slow (e.g. when " using valgrind). *************** *** 113,115 **** --- 115,119 ---- call WaitForAssert({-> assert_equal("finished", term_getstatus(a:buf))}) only! endfunc + + " vim: shiftwidth=2 sts=2 expandtab *** ../vim-8.2.0508/src/testdir/test_clientserver.vim 2020-03-30 19:30:07.129542925 +0200 --- src/testdir/test_clientserver.vim 2020-04-04 13:36:02.729150119 +0200 *************** *** 6,16 **** source shared.vim ! func Test_client_server() ! let cmd = GetVimCommand() ! if cmd == '' ! return ! endif if has('x11') if empty($DISPLAY) throw 'Skipped: $DISPLAY is not set' --- 6,12 ---- source shared.vim ! func Check_X11_Connection() if has('x11') if empty($DISPLAY) throw 'Skipped: $DISPLAY is not set' *************** *** 19,29 **** call remote_send('xxx', '') catch if v:exception =~ 'E240:' ! throw 'Skipped: no connection to the X server' endif " ignore other errors endtry endif let name = 'XVIMTEST' let cmd .= ' --servername ' . name --- 15,33 ---- call remote_send('xxx', '') catch if v:exception =~ 'E240:' ! throw 'Skipped: no connection to the X server' endif " ignore other errors endtry endif + endfunc + + func Test_client_server() + let cmd = GetVimCommand() + if cmd == '' + return + endif + call Check_X11_Connection() let name = 'XVIMTEST' let cmd .= ' --servername ' . name *************** *** 72,77 **** --- 76,85 ---- endif let g:testvar = 'myself' call assert_equal('myself', remote_expr(v:servername, 'testvar')) + call remote_send(v:servername, ":let g:testvar2 = 75\") + call feedkeys('', 'x') + call assert_equal(75, g:testvar2) + call assert_fails('let v = remote_expr(v:servername, "/2")', 'E449:') call remote_send(name, ":call server2client(expand(''), 'got it')\", 'g:myserverid') call assert_equal('got it', g:myserverid->remote_read(2)) *************** *** 92,97 **** --- 100,154 ---- call assert_equal('another', g:peek_result) call assert_equal('another', remote_read(g:myserverid, 2)) + if !has('gui_running') + " In GUI vim, the following tests display a dialog box + + let cmd = GetVimProg() .. ' --servername ' .. name + + " Run a separate instance to send a command to the server + call remote_expr(name, 'execute("only")') + call system(cmd .. ' --remote-send ":new Xfile"') + call assert_equal('2', remote_expr(name, 'winnr("$")')) + call assert_equal('Xfile', remote_expr(name, 'winbufnr(1)->bufname()')) + call remote_expr(name, 'execute("only")') + + " Invoke a remote-expr. On MS-Windows, the returned value has a carriage + " return. + let l = system(cmd .. ' --remote-expr "2 + 2"') + call assert_equal(['4'], split(l, "\n")) + + " Edit multiple files using --remote + call system(cmd .. ' --remote Xfile1 Xfile2 Xfile3') + call assert_equal("Xfile1\nXfile2\nXfile3\n", remote_expr(name, 'argv()')) + eval name->remote_send(":%bw!\") + + " Edit files in separate tab pages + call system(cmd .. ' --remote-tab Xfile1 Xfile2 Xfile3') + call assert_equal('3', remote_expr(name, 'tabpagenr("$")')) + call assert_equal('Xfile2', remote_expr(name, 'bufname(tabpagebuflist(2)[0])')) + eval name->remote_send(":%bw!\") + + " Edit a file using --remote-wait + eval name->remote_send(":source $VIMRUNTIME/plugin/rrhelper.vim\") + call system(cmd .. ' --remote-wait +enew Xfile1') + call assert_equal("Xfile1", remote_expr(name, 'bufname("#")')) + eval name->remote_send(":%bw!\") + + " Edit files using --remote-tab-wait + call system(cmd .. ' --remote-tabwait +tabonly\|enew Xfile1 Xfile2') + call assert_equal('1', remote_expr(name, 'tabpagenr("$")')) + eval name->remote_send(":%bw!\") + + " Error cases + if v:lang == "C" || v:lang =~ '^[Ee]n' + let l = split(system(cmd .. ' --remote +pwd'), "\n") + call assert_equal("Argument missing after: \"+pwd\"", l[1]) + endif + let l = system(cmd .. ' --remote-expr "abcd"') + call assert_match('^E449: ', l) + endif + + eval name->remote_send(":%bw!\") eval name->remote_send(":qa!\") try call WaitForAssert({-> assert_equal("dead", job_status(job))}) *************** *** 102,109 **** endif endtry ! call assert_fails("let x=remote_peek([])", 'E730:') ! call assert_fails("let x=remote_read('vim10')", 'E277:') endfunc " Uncomment this line to get a debugging log --- 159,166 ---- endif endtry ! call assert_fails("let x = remote_peek([])", 'E730:') ! call assert_fails("let x = remote_read('vim10')", 'E277:') endfunc " Uncomment this line to get a debugging log *** ../vim-8.2.0508/src/testdir/test_ex_mode.vim 2020-03-23 20:54:28.220520961 +0100 --- src/testdir/test_ex_mode.vim 2020-04-04 13:36:02.729150119 +0200 *************** *** 146,154 **** " In Ex-mode, backslashes at the end of a command should be halved. func Test_Ex_echo_backslash() " This test works only when the language is English ! if v:lang != "C" && v:lang !~ '^[Ee]n' ! return ! endif let bsl = '\\\\' let bsl2 = '\\\' call assert_fails('call feedkeys("Qecho " .. bsl .. "\nvisual\n", "xt")', --- 146,152 ---- " In Ex-mode, backslashes at the end of a command should be halved. func Test_Ex_echo_backslash() " This test works only when the language is English ! CheckEnglish let bsl = '\\\\' let bsl2 = '\\\' call assert_fails('call feedkeys("Qecho " .. bsl .. "\nvisual\n", "xt")', *** ../vim-8.2.0508/src/testdir/test_expand.vim 2020-02-21 17:54:41.830235712 +0100 --- src/testdir/test_expand.vim 2020-04-04 13:36:02.729150119 +0200 *************** *** 84,89 **** --- 84,98 ---- let $FOO="blue\tsky" call setline(1, "$FOO") call assert_equal("grep pat blue\tsky", expandcmd('grep pat ')) + + " Test for expression expansion `= + let $FOO= "blue" + call assert_equal("blue sky", expandcmd("`=$FOO .. ' sky'`")) + + " Test for env variable with spaces + let $FOO= "foo bar baz" + call assert_equal("e foo bar baz", expandcmd("e $FOO")) + unlet $FOO close! endfunc *** ../vim-8.2.0508/src/testdir/test_functions.vim 2020-04-03 18:43:31.886980756 +0200 --- src/testdir/test_functions.vim 2020-04-04 13:36:02.729150119 +0200 *************** *** 659,664 **** --- 659,665 ---- return '' endfunc + " Test for the mode() function func Test_mode() new call append(0, ["Blue Ball Black", "Brown Band Bowl", ""]) *************** *** 782,787 **** --- 783,790 ---- call assert_equal('c-c', g:current_modes) call feedkeys("gQecho \=Save_mode()\\vi\", 'xt') call assert_equal('c-cv', g:current_modes) + call feedkeys("Qcall Save_mode()\vi\", 'xt') + call assert_equal('c-ce', g:current_modes) " How to test Ex mode? bwipe! *************** *** 1284,1289 **** --- 1287,1305 ---- call feedkeys(":let c = inputlist(['Select color:', '1. red', '2. green', '3. blue'])\3\", 'tx') call assert_equal(3, c) + " Use backspace to delete characters in the prompt + call feedkeys(":let c = inputlist(['Select color:', '1. red', '2. green', '3. blue'])\1\3\2\", 'tx') + call assert_equal(2, c) + + " Use mouse to make a selection + call test_setmouse(&lines - 3, 2) + call feedkeys(":let c = inputlist(['Select color:', '1. red', '2. green', '3. blue'])\\", 'tx') + call assert_equal(1, c) + " Mouse click outside of the list + call test_setmouse(&lines - 6, 2) + call feedkeys(":let c = inputlist(['Select color:', '1. red', '2. green', '3. blue'])\\", 'tx') + call assert_equal(-2, c) + call assert_fails('call inputlist("")', 'E686:') endfunc *** ../vim-8.2.0508/src/testdir/test_options.vim 2020-03-23 19:28:40.599056151 +0100 --- src/testdir/test_options.vim 2020-04-04 13:36:02.729150119 +0200 *************** *** 1,6 **** --- 1,7 ---- " Test for options source check.vim + source view_util.vim func Test_whichwrap() set whichwrap=b,s *************** *** 707,710 **** --- 708,719 ---- set rightleft& endfunc + " Test for the "debug" option + func Test_debug_option() + set debug=beep + exe "normal \" + call assert_equal('Beep!', Screenline(&lines)) + set debug& + endfunc + " vim: shiftwidth=2 sts=2 expandtab *** ../vim-8.2.0508/src/testdir/test_startup.vim 2019-12-01 15:10:16.000000000 +0100 --- src/testdir/test_startup.vim 2020-04-04 13:50:26.389187818 +0200 *************** *** 2,7 **** --- 2,8 ---- source shared.vim source screendump.vim + source term_util.vim source check.vim " Check that loading startup.vim works. *************** *** 10,15 **** --- 11,19 ---- source $VIMRUNTIME/defaults.vim call assert_equal(0, &compatible) + " Restore some options, so that the following tests doesn't break + set nomore + set noshowmode endfunc " Verify the order in which plugins are loaded: *************** *** 322,327 **** --- 326,335 ---- \ lines) endif + " Test with a non-existing error file (exits with value 3) + let out = system(GetVimCommand() .. ' -q xyz.err') + call assert_equal(3, v:shell_error) + call delete('Xtestout') call delete('Xerrors') endfunc *************** *** 687,689 **** --- 695,962 ---- call assert_true(idx > 2) call assert_equal(['arg1', '--cmd', 'echo v:argv', '--cmd', 'q'']'], list[idx:]) endfunc + + " Test for the "-r" recovery mode option + func Test_r_arg() + " Can't catch the output of gvim. + CheckNotGui + CheckUnix + CheckEnglish + let cmd = GetVimCommand() + " There can be swap files anywhere, only check for the headers. + let expected =<< trim END + Swap files found:.* + In current directory:.* + In directory \~/tmp:.* + In directory /var/tmp:.* + In directory /tmp:.* + END + call assert_match(join(expected, ""), system(cmd .. " -r")->substitute("[\r\n]\\+", '', '')) + endfunc + + " Test for the '-t' option to jump to a tag + func Test_t_arg() + let before =<< trim [CODE] + set tags=Xtags + [CODE] + let after =<< trim [CODE] + let s = bufname('') .. ':L' .. line('.') .. 'C' .. col('.') + call writefile([s], "Xtestout") + qall + [CODE] + + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "first\tXfile1\t/^ \\zsfirst$/", + \ "second\tXfile1\t/^ \\zssecond$/", + \ "third\tXfile1\t/^ \\zsthird$/"], + \ 'Xtags') + call writefile([' first', ' second', ' third'], 'Xfile1') + + if RunVim(before, after, '-t second') + call assert_equal(['Xfile1:L2C5'], readfile('Xtestout')) + call delete('Xtestout') + endif + + call delete('Xtags') + call delete('Xfile1') + endfunc + + " Test for entering the insert mode on startup + func Test_start_insertmode() + let before =<< trim [CODE] + set insertmode + [CODE] + let after =<< trim [CODE] + call writefile(['insertmode=' .. &insertmode], 'Xtestout') + qall + [CODE] + if RunVim(before, after, '') + call assert_equal(['insertmode=1'], readfile('Xtestout')) + call delete('Xtestout') + endif + endfunc + + " Test for enabling the binary mode on startup + func Test_b_arg() + let after =<< trim [CODE] + call writefile(['binary=' .. &binary], 'Xtestout') + qall + [CODE] + if RunVim([], after, '-b') + call assert_equal(['binary=1'], readfile('Xtestout')) + call delete('Xtestout') + endif + endfunc + + " Test for enabling the lisp mode on startup + func Test_l_arg() + let after =<< trim [CODE] + let s = 'lisp=' .. &lisp .. ', showmatch=' .. &showmatch + call writefile([s], 'Xtestout') + qall + [CODE] + if RunVim([], after, '-l') + call assert_equal(['lisp=1, showmatch=1'], readfile('Xtestout')) + call delete('Xtestout') + endif + endfunc + + " Test for specifying a non-existing vimrc file using "-u" + func Test_missing_vimrc() + if !CanRunVimInTerminal() + throw 'Skipped: cannot run vim in terminal' + endif + let after =<< trim [CODE] + call assert_match('^E282:', v:errmsg) + call writefile(v:errors, 'Xtestout') + [CODE] + call writefile(after, 'Xafter') + + let cmd = GetVimCommandCleanTerm() . ' -u Xvimrc_missing -S Xafter' + let buf = term_start(cmd, {'term_rows' : 10}) + call WaitForAssert({-> assert_equal("running", term_getstatus(buf))}) + call term_wait(buf) + call term_sendkeys(buf, "\n:") + call term_wait(buf) + call WaitForAssert({-> assert_match(':', term_getline(buf, 10))}) + call StopVimInTerminal(buf) + call assert_equal([], readfile('Xtestout')) + call delete('Xafter') + call delete('Xtestout') + endfunc + + " Test for using the $VIMINIT environment variable + func Test_VIMINIT() + let after =<< trim [CODE] + call assert_equal(1, exists('viminit_found')) + call assert_equal('yes', viminit_found) + call writefile(v:errors, 'Xtestout') + qall + [CODE] + call writefile(after, 'Xafter') + let cmd = GetVimProg() . ' --not-a-term -S Xafter --cmd "set enc=utf8"' + call setenv('VIMINIT', 'let viminit_found="yes"') + exe "silent !" . cmd + call assert_equal([], readfile('Xtestout')) + call delete('Xtestout') + call delete('Xafter') + endfunc + + " Test for using the $EXINIT environment variable + func Test_EXINIT() + let after =<< trim [CODE] + call assert_equal(1, exists('exinit_found')) + call assert_equal('yes', exinit_found) + call writefile(v:errors, 'Xtestout') + qall + [CODE] + call writefile(after, 'Xafter') + let cmd = GetVimProg() . ' --not-a-term -S Xafter --cmd "set enc=utf8"' + call setenv('EXINIT', 'let exinit_found="yes"') + exe "silent !" . cmd + call assert_equal([], readfile('Xtestout')) + call delete('Xtestout') + call delete('Xafter') + endfunc + + " Test for using the 'exrc' option + func Test_exrc() + let after =<< trim [CODE] + call assert_equal(1, &exrc) + call assert_equal(1, &secure) + call assert_equal(37, exrc_found) + call writefile(v:errors, 'Xtestout') + qall + [CODE] + call mkdir('Xdir') + call writefile(['let exrc_found=37'], 'Xdir/.exrc') + call writefile(after, 'Xdir/Xafter') + let cmd = GetVimProg() . ' --not-a-term -S Xafter --cmd "cd Xdir" --cmd "set enc=utf8 exrc secure"' + exe "silent !" . cmd + call assert_equal([], readfile('Xdir/Xtestout')) + call delete('Xdir', 'rf') + endfunc + + " Test for starting Vim with a non-terminal as input/output + func Test_io_not_a_terminal() + " Can't catch the output of gvim. + CheckNotGui + CheckUnix + CheckEnglish + let l = systemlist(GetVimProg() .. ' --ttyfail') + call assert_equal(['Vim: Warning: Output is not to a terminal', + \ 'Vim: Warning: Input is not from a terminal'], l) + endfunc + + " Test for the "-w scriptout" argument + func Test_w_arg() + " Can't catch the output of gvim. + CheckNotGui + call writefile(["iVim Editor\:q!\"], 'Xscriptin', 'b') + if RunVim([], [], '-s Xscriptin -w Xscriptout') + call assert_equal(["iVim Editor\e:q!\r"], readfile('Xscriptout')) + call delete('Xscriptout') + endif + call delete('Xscriptin') + + " Test for failing to open the script output file. This test works only when + " the language is English. + if v:lang == "C" || v:lang =~ '^[Ee]n' + call mkdir("Xdir") + let m = system(GetVimCommand() .. " -w Xdir") + call assert_equal("Cannot open for script output: \"Xdir\"\n", m) + call delete("Xdir", 'rf') + endif + endfunc + + " Test for the "-s scriptin" argument + func Test_s_arg() + " Can't catch the output of gvim. + CheckNotGui + CheckEnglish + " Test for failing to open the script input file. + let m = system(GetVimCommand() .. " -s abcxyz") + call assert_equal("Cannot open for reading: \"abcxyz\"\n", m) + + call writefile([], 'Xinput') + let m = system(GetVimCommand() .. " -s Xinput -s Xinput") + call assert_equal("Attempt to open script file again: \"-s Xinput\"\n", m) + call delete('Xinput') + endfunc + + " Test for the "-n" (no swap file) argument + func Test_n_arg() + let after =<< trim [CODE] + call assert_equal(0, &updatecount) + call writefile(v:errors, 'Xtestout') + qall + [CODE] + if RunVim([], after, '-n') + call assert_equal([], readfile('Xtestout')) + call delete('Xtestout') + endif + call delete('Xafter') + endfunc + + " Test for the "-h" (help) argument + func Test_h_arg() + " Can't catch the output of gvim. + CheckNotGui + let l = systemlist(GetVimProg() .. ' -h') + call assert_match('^VIM - Vi IMproved', l[0]) + let l = systemlist(GetVimProg() .. ' -?') + call assert_match('^VIM - Vi IMproved', l[0]) + endfunc + + " Test for the "-F" (farsi) argument + func Test_F_arg() + " Can't catch the output of gvim. + CheckNotGui + let l = systemlist(GetVimProg() .. ' -F') + call assert_match('^E27:', l[0]) + endfunc + + " Test for the "-E" (improved Ex mode) argument + func Test_E_arg() + let after =<< trim [CODE] + call assert_equal('cv', mode(1)) + call writefile(v:errors, 'Xtestout') + qall + [CODE] + if RunVim([], after, '-E') + call assert_equal([], readfile('Xtestout')) + call delete('Xtestout') + endif + call delete('Xafter') + endfunc + + " Test for too many edit argument errors + func Test_too_many_edit_args() + " Can't catch the output of gvim. + CheckNotGui + CheckEnglish + let l = systemlist(GetVimProg() .. ' - -') + call assert_match('^Too many edit arguments: "-"', l[1]) + endfunc + + " vim: shiftwidth=2 sts=2 expandtab *** ../vim-8.2.0508/src/testdir/test_textformat.vim 2020-03-30 19:39:22.891094168 +0200 --- src/testdir/test_textformat.vim 2020-04-04 13:36:02.729150119 +0200 *************** *** 1026,1031 **** --- 1026,1066 ---- %bw! endfunc + " Test for a space character in 'comments' setting + func Test_comment_space() + new + setlocal comments=b:\ > fo+=ro + exe "normal i> B\nD\ggOA\joC" + exe "normal Go > F\nH\kOE\joG" + let expected =<< trim END + A + > B + C + D + > E + > F + > G + > H + END + call assert_equal(expected, getline(1, '$')) + %bw! + endfunc + + " Test for the 'O' flag in 'comments' + func Test_comment_O() + new + setlocal comments=Ob:* fo+=ro + exe "normal i* B\nD\kOA\joC" + let expected =<< trim END + A + * B + * C + * D + END + call assert_equal(expected, getline(1, '$')) + %bw! + endfunc + " Test for 'a' and 'w' flags in 'formatoptions' func Test_fo_a_w() new *************** *** 1035,1038 **** --- 1070,1092 ---- %bw! endfunc + " Test for 'j' flag in 'formatoptions' + func Test_fo_j() + new + setlocal fo+=j comments=:// + call setline(1, ['i++; // comment1', ' // comment2']) + normal J + call assert_equal('i++; // comment1 comment2', getline(1)) + setlocal fo-=j + call setline(1, ['i++; // comment1', ' // comment2']) + normal J + call assert_equal('i++; // comment1 // comment2', getline(1)) + " Test with nested comments + setlocal fo+=j comments=n:>,n:) + call setline(1, ['i++; > ) > ) comment1', ' > ) comment2']) + normal J + call assert_equal('i++; > ) > ) comment1 comment2', getline(1)) + %bw! + endfunc + " vim: shiftwidth=2 sts=2 expandtab *** ../vim-8.2.0508/src/testdir/test_trycatch.vim 2020-02-22 21:21:23.698595570 +0100 --- src/testdir/test_trycatch.vim 2020-04-04 13:36:02.729150119 +0200 *************** *** 2012,2020 **** " Test for verbose messages with :try :catch, and :finally {{{1 func Test_try_catch_verbose() " This test works only when the language is English ! if v:lang != "C" && v:lang !~ '^[Ee]n' ! return ! endif set verbose=14 --- 2012,2018 ---- " Test for verbose messages with :try :catch, and :finally {{{1 func Test_try_catch_verbose() " This test works only when the language is English ! CheckEnglish set verbose=14 *** ../vim-8.2.0508/src/testdir/test_viminfo.vim 2019-12-27 17:33:23.475080942 +0100 --- src/testdir/test_viminfo.vim 2020-04-04 13:36:02.729150119 +0200 *************** *** 760,765 **** --- 760,770 ---- call setfperm('Xviminfo', '--x------') call assert_fails('rviminfo Xviminfo', 'E195:') call delete('Xviminfo') + + " Try to write the viminfo to a directory + call mkdir('Xdir') + call assert_fails('wviminfo Xdir', 'E886:') + call delete('Xdir', 'rf') endfunc " Test for writing to an existing viminfo file merges the file marks *** ../vim-8.2.0508/src/version.c 2020-04-03 21:59:29.333665628 +0200 --- src/version.c 2020-04-04 13:37:26.248766792 +0200 *************** *** 740,741 **** --- 740,743 ---- { /* Add new patch number below this line */ + /**/ + 509, /**/ -- BRIDGEKEEPER: What is your favorite colour? LAUNCELOT: Blue. BRIDGEKEEPER: Right. Off you go. "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// 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 ///