Patch 8.2.0738
Problem: Mouse handling in a terminal window not well tested.
Solution: Add tests. (Yegappan Lakshmanan, closes #6052)
Files: src/testdir/term_util.vim, src/testdir/test_gui.vim,
src/testdir/test_modeless.vim, src/testdir/test_terminal.vim
*** ../vim-8.2.0737/src/testdir/term_util.vim 2020-04-08 21:50:18.872619665 +0200
--- src/testdir/term_util.vim 2020-05-11 21:31:24.787014475 +0200
***************
*** 127,132 ****
--- 127,135 ----
" In Command-line it's inserted, the CTRL-U removes it again.
call term_sendkeys(a:buf, "\<C-O>:\<C-U>qa!\<cr>")
+ " Wait for all the pending updates to terminal to complete
+ call TermWait(a:buf)
+
call WaitForAssert({-> assert_equal("finished", term_getstatus(a:buf))})
only!
endfunc
*** ../vim-8.2.0737/src/testdir/test_gui.vim 2020-04-12 15:10:36.618312729 +0200
--- src/testdir/test_gui.vim 2020-05-11 21:31:24.787014475 +0200
***************
*** 838,841 ****
--- 838,859 ----
call delete('Xtestgui')
endfunc
+ " Test for "!" option in 'guioptions'. Use a terminal for running external
+ " commands
+ func Test_gui_run_cmd_in_terminal()
+ let save_guioptions = &guioptions
+ set guioptions+=!
+ if has('win32')
+ let cmd = 'type'
+ else
+ " assume all the other systems have a cat command
+ let cmd = 'cat'
+ endif
+ let cmd = ':silent !' . cmd . " test_gui.vim\<CR>\<CR>"
+ call feedkeys(cmd, 'xt')
+ " TODO: how to check that the command ran in a separate terminal?
+ " Maybe check for $TERM (dumb vs xterm) in the spawned shell?
+ let &guioptions = save_guioptions
+ endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
*** ../vim-8.2.0737/src/testdir/test_modeless.vim 2020-03-22 14:08:27.321399669 +0100
--- src/testdir/test_modeless.vim 2020-05-11 21:31:24.787014475 +0200
***************
*** 24,30 ****
exe 'set ttymouse=' .. ttymouse_val
" select multiple characters within a line
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
--- 24,30 ----
exe 'set ttymouse=' .. ttymouse_val
" select multiple characters within a line
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
***************
*** 36,42 ****
call assert_equal("wo th", @*, msg)
" select multiple characters including the end of line
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
--- 36,42 ----
call assert_equal("wo th", @*, msg)
" select multiple characters including the end of line
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
***************
*** 48,54 ****
call assert_equal("ree\n", @*, msg)
" extend a selection using right mouse click
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
set mousemodel=extend
--- 48,54 ----
call assert_equal("ree\n", @*, msg)
" extend a selection using right mouse click
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
set mousemodel=extend
***************
*** 64,70 ****
set mousemodel&
" extend a selection backwards using right mouse click
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
set mousemodel=extend
--- 64,70 ----
set mousemodel&
" extend a selection backwards using right mouse click
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
set mousemodel=extend
***************
*** 80,86 ****
set mousemodel&
" select multiple characters within a line backwards
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
--- 80,86 ----
set mousemodel&
" select multiple characters within a line backwards
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
***************
*** 93,99 ****
" select multiple characters across lines with (end row > start row) and
" (end column < start column)
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
--- 93,99 ----
" select multiple characters across lines with (end row > start row) and
" (end column < start column)
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
***************
*** 106,112 ****
" select multiple characters across lines with (end row > start row) and
" (end column > start column)
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
--- 106,112 ----
" select multiple characters across lines with (end row > start row) and
" (end column > start column)
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
***************
*** 119,125 ****
" select multiple characters across lines with (end row < start row) and
" (end column < start column)
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
--- 119,125 ----
" select multiple characters across lines with (end row < start row) and
" (end column < start column)
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
***************
*** 132,138 ****
" select multiple characters across lines with (end row < start row) and
" (end column > start column)
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
--- 132,138 ----
" select multiple characters across lines with (end row < start row) and
" (end column > start column)
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
***************
*** 145,151 ****
" select multiple characters across lines with (end row < start row) and
" the end column is greater than the line length
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
--- 145,151 ----
" select multiple characters across lines with (end row < start row) and
" the end column is greater than the line length
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
***************
*** 158,164 ****
" select multiple characters across lines with start/end row and start/end
" column outside the lines in the buffer
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
--- 158,164 ----
" select multiple characters across lines with start/end row and start/end
" column outside the lines in the buffer
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
***************
*** 170,176 ****
call assert_equal("\n~ ", @*, msg)
" change selection using right mouse click within the selected text
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
set mousemodel=extend
--- 170,176 ----
call assert_equal("\n~ ", @*, msg)
" change selection using right mouse click within the selected text
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
set mousemodel=extend
***************
*** 188,194 ****
set mousemodel&
" select text multiple times at different places
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
--- 188,194 ----
set mousemodel&
" select text multiple times at different places
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
***************
*** 205,211 ****
" Test for 'clipboard' set to 'autoselectml' to automatically copy the
" modeless selection to the clipboard
set clipboard=autoselectml
! let @* = ''
let keys = ":"
let keys ..= MouseLeftClickCode(2, 5)
let keys ..= MouseLeftDragCode(2, 7)
--- 205,211 ----
" Test for 'clipboard' set to 'autoselectml' to automatically copy the
" modeless selection to the clipboard
set clipboard=autoselectml
! let @* = 'clean'
let keys = ":"
let keys ..= MouseLeftClickCode(2, 5)
let keys ..= MouseLeftDragCode(2, 7)
***************
*** 216,222 ****
set clipboard&
" quadruple click should start characterwise selectmode
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
--- 216,222 ----
set clipboard&
" quadruple click should start characterwise selectmode
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
***************
*** 259,265 ****
exe 'set ttymouse=' .. ttymouse_val
" select multiple words within a line
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
--- 259,265 ----
exe 'set ttymouse=' .. ttymouse_val
" select multiple words within a line
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
***************
*** 273,279 ****
call assert_equal("two three", @*, msg)
" select a single word
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
--- 273,279 ----
call assert_equal("two three", @*, msg)
" select a single word
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
***************
*** 286,292 ****
call assert_equal("bar", @*, msg)
" select multiple words backwards within a line
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
--- 286,292 ----
call assert_equal("bar", @*, msg)
" select multiple words backwards within a line
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
***************
*** 300,306 ****
call assert_equal("bar baz", @*, msg)
" select multiple words backwards across lines
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
--- 300,306 ----
call assert_equal("bar baz", @*, msg)
" select multiple words backwards across lines
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
***************
*** 339,345 ****
exe 'set ttymouse=' .. ttymouse_val
" select single line
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
--- 339,345 ----
exe 'set ttymouse=' .. ttymouse_val
" select single line
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
***************
*** 354,360 ****
call assert_equal("foo bar baz\n", @*, msg)
" select multiple lines
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
--- 354,360 ----
call assert_equal("foo bar baz\n", @*, msg)
" select multiple lines
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
***************
*** 370,376 ****
call assert_equal("one two three\nfoo bar baz\n", @*, msg)
" select multiple lines backwards
! let @* = ''
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
--- 370,376 ----
call assert_equal("one two three\nfoo bar baz\n", @*, msg)
" select multiple lines backwards
! let @* = 'clean'
call MouseRightClick(1, 1)
call MouseRightRelease(1, 1)
let keys = ":"
*** ../vim-8.2.0737/src/testdir/test_terminal.vim 2020-05-03 16:29:46.891538441 +0200
--- src/testdir/test_terminal.vim 2020-05-11 22:00:11.781804565 +0200
***************
*** 5,10 ****
--- 5,11 ----
source shared.vim
source screendump.vim
+ source mouse.vim
let s:python = PythonProg()
let $PROMPT_COMMAND=''
***************
*** 1206,1211 ****
--- 1207,1232 ----
let &encoding = save_enc
endfunc
+ " Tests for failures in the term_dumpwrite() function
+ func Test_terminal_dumpwrite_errors()
+ CheckRunVimInTerminal
+ call assert_fails("call term_dumpwrite({}, 'Xtest.dump')", 'E728:')
+ let buf = RunVimInTerminal('', {})
+ call term_wait(buf)
+ call assert_fails("call term_dumpwrite(buf, 'Xtest.dump', '')", 'E715:')
+ call assert_fails("call term_dumpwrite(buf, [])", 'E730:')
+ call writefile([], 'Xtest.dump')
+ call assert_fails("call term_dumpwrite(buf, 'Xtest.dump')", 'E953:')
+ call delete('Xtest.dump')
+ call assert_fails("call term_dumpwrite(buf, '')", 'E482:')
+ call assert_fails("call term_dumpwrite(buf, test_null_string())", 'E482:')
+ call StopVimInTerminal(buf)
+ call term_wait(buf)
+ call assert_fails("call term_dumpwrite(buf, 'Xtest.dump')", 'E958:')
+ call assert_fails('call term_sendkeys([], ":q\<CR>")', 'E745:')
+ call assert_equal(0, term_sendkeys(buf, ":q\<CR>"))
+ endfunc
+
" just testing basic functionality.
func Test_terminal_dumpload()
let curbuf = winbufnr('')
***************
*** 1231,1236 ****
--- 1252,1259 ----
let closedbuf = winbufnr('')
quit
call assert_fails("call term_dumpload('dumps/Test_popup_command_01.dump', {'bufnr': closedbuf})", 'E475:')
+ call assert_fails('call term_dumpload([])', 'E474:')
+ call assert_fails('call term_dumpload("xabcy.dump")', 'E485:')
quit
endfunc
***************
*** 1258,1263 ****
--- 1281,1292 ----
call Check_dump01(42)
call assert_equal(' bbbbbbbbbbbbbbbbbb ', getline(26)[0:29])
quit
+
+ call assert_fails('call term_dumpdiff("X1.dump", [])', 'E474:')
+ call assert_fails('call term_dumpdiff("X1.dump", "X2.dump")', 'E485:')
+ call writefile([], 'X1.dump')
+ call assert_fails('call term_dumpdiff("X1.dump", "X2.dump")', 'E485:')
+ call delete('X1.dump')
endfunc
func Test_terminal_dumpdiff_swap()
***************
*** 2652,2655 ****
--- 2681,2880 ----
call assert_fails('call term_setkill([], "")', 'E745:')
endfunc
+ " Test for sending various special keycodes to a terminal
+ func Test_term_keycode_translation()
+ CheckRunVimInTerminal
+
+ let buf = RunVimInTerminal('', {})
+ call term_sendkeys(buf, ":set nocompatible\<CR>")
+
+ let keys = ["\<F1>", "\<F2>", "\<F3>", "\<F4>", "\<F5>", "\<F6>", "\<F7>",
+ \ "\<F8>", "\<F9>", "\<F10>", "\<F11>", "\<F12>", "\<Home>",
+ \ "\<S-Home>", "\<C-Home>", "\<End>", "\<S-End>", "\<C-End>",
+ \ "\<Ins>", "\<Del>", "\<Left>", "\<S-Left>", "\<C-Left>", "\<Right>",
+ \ "\<S-Right>", "\<C-Right>", "\<Up>", "\<S-Up>", "\<Down>",
+ \ "\<S-Down>"]
+ let output = ['<F1>', '<F2>', '<F3>', '<F4>', '<F5>', '<F6>', '<F7>',
+ \ '<F8>', '<F9>', '<F10>', '<F11>', '<F12>', '<Home>', '<S-Home>',
+ \ '<C-Home>', '<End>', '<S-End>', '<C-End>', '<Insert>', '<Del>',
+ \ '<Left>', '<S-Left>', '<C-Left>', '<Right>', '<S-Right>',
+ \ '<C-Right>', '<Up>', '<S-Up>', '<Down>', '<S-Down>',
+ \ '0123456789', "\t\t.+-*/"]
+
+ for k in keys
+ call term_sendkeys(buf, "i\<C-K>" .. k .. "\<CR>\<C-\>\<C-N>")
+ endfor
+ call term_sendkeys(buf, "i\<K0>\<K1>\<K2>\<K3>\<K4>\<K5>\<K6>\<K7>")
+ call term_sendkeys(buf, "\<K8>\<K9>\<kEnter>\<kPoint>\<kPlus>")
+ call term_sendkeys(buf, "\<kMinus>\<kMultiply>\<kDivide>\<C-\>\<C-N>")
+ call term_sendkeys(buf, "\<Home>\<Ins>\<Tab>\<S-Tab>\<C-\>\<C-N>")
+
+ call term_sendkeys(buf, ":write Xkeycodes\<CR>")
+ call term_wait(buf)
+ call StopVimInTerminal(buf)
+ call assert_equal(output, readfile('Xkeycodes'))
+ call delete('Xkeycodes')
+ endfunc
+
+ " Test for using the mouse in a terminal
+ func Test_term_mouse()
+ CheckNotGui
+ CheckRunVimInTerminal
+
+ let save_mouse = &mouse
+ let save_term = &term
+ let save_ttymouse = &ttymouse
+ let save_clipboard = &clipboard
+ call test_override('no_query_mouse', 1)
+ set mouse=a term=xterm ttymouse=sgr mousetime=200 clipboard=
+
+ let lines =<< trim END
+ one two three four five
+ red green yellow red blue
+ vim emacs sublime nano
+ END
+ call writefile(lines, 'Xtest_mouse')
+
+ let buf = RunVimInTerminal('Xtest_mouse -n', {})
+ call term_sendkeys(buf, ":set nocompatible\<CR>")
+ call term_sendkeys(buf, ":set mouse=a term=xterm ttymouse=sgr\<CR>")
+ call term_sendkeys(buf, ":set clipboard=\<CR>")
+ call term_sendkeys(buf, ":set mousemodel=extend\<CR>")
+ call term_wait(buf)
+ redraw!
+
+ " Test for <LeftMouse> click/release
+ call test_setmouse(2, 5)
+ call feedkeys("\<LeftMouse>\<LeftRelease>", 'xt')
+ call test_setmouse(3, 8)
+ call term_sendkeys(buf, "\<LeftMouse>\<LeftRelease>")
+ call term_wait(buf, 50)
+ call term_sendkeys(buf, ":call writefile([json_encode(getpos('.'))], 'Xbuf')\<CR>")
+ call term_wait(buf, 50)
+ let pos = json_decode(readfile('Xbuf')[0])
+ call assert_equal([3, 8], pos[1:2])
+
+ " Test for selecting text using mouse
+ call delete('Xbuf')
+ call test_setmouse(2, 11)
+ call term_sendkeys(buf, "\<LeftMouse>")
+ call test_setmouse(2, 16)
+ call term_sendkeys(buf, "\<LeftRelease>y")
+ call term_wait(buf, 50)
+ call term_sendkeys(buf, ":call writefile([@\"], 'Xbuf')\<CR>")
+ call term_wait(buf, 50)
+ call assert_equal('yellow', readfile('Xbuf')[0])
+
+ " Test for selecting text using doubleclick
+ call delete('Xbuf')
+ call test_setmouse(1, 11)
+ call term_sendkeys(buf, "\<LeftMouse>\<LeftRelease>\<LeftMouse>")
+ call test_setmouse(1, 17)
+ call term_sendkeys(buf, "\<LeftRelease>y")
+ call term_wait(buf, 50)
+ call term_sendkeys(buf, ":call writefile([@\"], 'Xbuf')\<CR>")
+ call term_wait(buf, 50)
+ call assert_equal('three four', readfile('Xbuf')[0])
+
+ " Test for selecting a line using triple click
+ call delete('Xbuf')
+ call test_setmouse(3, 2)
+ call term_sendkeys(buf, "\<LeftMouse>\<LeftRelease>\<LeftMouse>\<LeftRelease>\<LeftMouse>\<LeftRelease>y")
+ call term_wait(buf, 50)
+ call term_sendkeys(buf, ":call writefile([@\"], 'Xbuf')\<CR>")
+ call term_wait(buf, 50)
+ call assert_equal("vim emacs sublime nano\n", readfile('Xbuf')[0])
+
+ " Test for selecting a block using qudraple click
+ call delete('Xbuf')
+ call test_setmouse(1, 11)
+ call term_sendkeys(buf, "\<LeftMouse>\<LeftRelease>\<LeftMouse>\<LeftRelease>\<LeftMouse>\<LeftRelease>\<LeftMouse>")
+ call test_setmouse(3, 13)
+ call term_sendkeys(buf, "\<LeftRelease>y")
+ call term_wait(buf, 50)
+ call term_sendkeys(buf, ":call writefile([@\"], 'Xbuf')\<CR>")
+ call term_wait(buf, 50)
+ call assert_equal("ree\nyel\nsub", readfile('Xbuf')[0])
+
+ " Test for extending a selection using right click
+ call delete('Xbuf')
+ call test_setmouse(2, 9)
+ call term_sendkeys(buf, "\<LeftMouse>\<LeftRelease>")
+ call test_setmouse(2, 16)
+ call term_sendkeys(buf, "\<RightMouse>\<RightRelease>y")
+ call term_wait(buf, 50)
+ call term_sendkeys(buf, ":call writefile([@\"], 'Xbuf')\<CR>")
+ call term_wait(buf, 50)
+ call assert_equal("n yellow", readfile('Xbuf')[0])
+
+ " Test for pasting text using middle click
+ call delete('Xbuf')
+ call term_sendkeys(buf, ":let @r='bright '\<CR>")
+ call test_setmouse(2, 22)
+ call term_sendkeys(buf, "\"r\<MiddleMouse>\<MiddleRelease>")
+ call term_wait(buf, 50)
+ call term_sendkeys(buf, ":call writefile([getline(2)], 'Xbuf')\<CR>")
+ call term_wait(buf, 50)
+ call assert_equal("red bright blue", readfile('Xbuf')[0][-15:])
+
+ " cleanup
+ call term_wait(buf)
+ call StopVimInTerminal(buf)
+ let &mouse = save_mouse
+ let &term = save_term
+ let &ttymouse = save_ttymouse
+ let &clipboard = save_clipboard
+ set mousetime&
+ call test_override('no_query_mouse', 0)
+ call delete('Xtest_mouse')
+ call delete('Xbuf')
+ endfunc
+
+ " Test for modeless selection in a terminal
+ func Test_term_modeless_selection()
+ CheckUnix
+ CheckNotGui
+ CheckRunVimInTerminal
+ CheckFeature clipboard_working
+
+ let save_mouse = &mouse
+ let save_term = &term
+ let save_ttymouse = &ttymouse
+ call test_override('no_query_mouse', 1)
+ set mouse=a term=xterm ttymouse=sgr mousetime=200
+ set clipboard=autoselectml
+
+ let lines =<< trim END
+ one two three four five
+ red green yellow red blue
+ vim emacs sublime nano
+ END
+ call writefile(lines, 'Xtest_modeless')
+
+ let buf = RunVimInTerminal('Xtest_modeless -n', {})
+ call term_sendkeys(buf, ":set nocompatible\<CR>")
+ call term_sendkeys(buf, ":set mouse=\<CR>")
+ call term_wait(buf)
+ redraw!
+
+ " Test for copying a modeless selection to clipboard
+ let @* = 'clean'
+ " communicating with X server may take a little time
+ sleep 100m
+ call feedkeys(MouseLeftClickCode(2, 3), 'x')
+ call feedkeys(MouseLeftDragCode(2, 11), 'x')
+ call feedkeys(MouseLeftReleaseCode(2, 11), 'x')
+ call assert_equal("d green y", @*)
+
+ " cleanup
+ call term_wait(buf)
+ call StopVimInTerminal(buf)
+ let &mouse = save_mouse
+ let &term = save_term
+ let &ttymouse = save_ttymouse
+ set mousetime& clipboard&
+ call test_override('no_query_mouse', 0)
+ call delete('Xtest_modeless')
+ endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
*** ../vim-8.2.0737/src/version.c 2020-05-11 20:54:37.626875113 +0200
--- src/version.c 2020-05-11 21:31:53.950959668 +0200
***************
*** 748,749 ****
--- 748,751 ----
{ /* Add new patch number below this line */
+ /**/
+ 738,
/**/
--
% cat /usr/include/real_life.h
void life(void);
/// Bram Moolenaar -- Br...@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 ///