Patch 7.4.1925
Problem: Viminfo does not merge file marks properly.
Solution: Use a timestamp. Add the :clearjumps command.
Files: src/mark.c, src/ex_cmds.c, src/ex_docmd.c, src/proto/mark.pro,
src/structs.h, src/vim.h, src/ex_cmds.h,
src/testdir/test_viminfo.vim
*** ../vim-7.4.1924/src/mark.c 2016-01-30 18:51:05.232232015 +0100
--- src/mark.c 2016-06-12 21:17:30.123990602 +0200
***************
*** 106,129 ****
return OK;
}
! #ifndef EBCDIC
! if (c > 'z') /* some islower() and isupper() cannot handle
! characters above 127 */
! return FAIL;
! #endif
! if (islower(c))
{
i = c - 'a';
curbuf->b_namedm[i] = *pos;
return OK;
}
! if (isupper(c))
{
! i = c - 'A';
namedfm[i].fmark.mark = *pos;
namedfm[i].fmark.fnum = fnum;
vim_free(namedfm[i].fname);
namedfm[i].fname = NULL;
return OK;
}
return FAIL;
--- 106,130 ----
return OK;
}
! if (ASCII_ISLOWER(c))
{
i = c - 'a';
curbuf->b_namedm[i] = *pos;
return OK;
}
! if (ASCII_ISUPPER(c) || VIM_ISDIGIT(c))
{
! if (VIM_ISDIGIT(c))
! i = c - '0' + NMARKS;
! else
! i = c - 'A';
namedfm[i].fmark.mark = *pos;
namedfm[i].fmark.fnum = fnum;
vim_free(namedfm[i].fname);
namedfm[i].fname = NULL;
+ #ifdef FEAT_VIMINFO
+ namedfm[i].time_set = vim_time();
+ #endif
return OK;
}
return FAIL;
***************
*** 184,189 ****
--- 185,193 ----
fm->fmark.mark = curwin->w_pcmark;
fm->fmark.fnum = curbuf->b_fnum;
fm->fname = NULL;
+ # ifdef FEAT_VIMINFO
+ fm->time_set = vim_time();
+ # endif
#endif
}
***************
*** 634,639 ****
--- 638,646 ----
{
namedfm[i].fmark.mark.lnum = 0;
namedfm[i].fname = NULL;
+ #ifdef FEAT_VIMINFO
+ namedfm[i].time_set = 0;
+ #endif
}
for (i = 0; i < NMARKS; i++)
***************
*** 849,854 ****
--- 856,864 ----
namedfm[n].fmark.mark.lnum = 0;
vim_free(namedfm[n].fname);
namedfm[n].fname = NULL;
+ #ifdef FEAT_VIMINFO
+ namedfm[n].time_set = 0;
+ #endif
}
}
}
***************
*** 918,923 ****
--- 928,941 ----
MSG_PUTS("\n>");
}
+ void
+ ex_clearjumps(exarg_T *eap UNUSED)
+ {
+ free_jumplist(curwin);
+ curwin->w_jumplistlen = 0;
+ curwin->w_jumplistidx = 0;
+ }
+
/*
* print the changelist
*/
***************
*** 1400,1410 ****
--- 1418,1616 ----
vim_free(fm->fname);
fm->fname = viminfo_readstring(virp, (int)(str - virp->vir_line),
FALSE);
+ fm->time_set = 0;
}
}
return vim_fgets(virp->vir_line, LSIZE, virp->vir_fd);
}
+ static xfmark_T *vi_namedfm = NULL;
+ #ifdef FEAT_JUMPLIST
+ static xfmark_T *vi_jumplist = NULL;
+ static int vi_jumplist_len = 0;
+ #endif
+
+ /*
+ * Prepare for reading viminfo marks when writing viminfo later.
+ */
+ void
+ prepare_viminfo_marks(void)
+ {
+ vi_namedfm = (xfmark_T *)alloc_clear((NMARKS + EXTRA_MARKS)
+ * (int)sizeof(xfmark_T));
+ #ifdef FEAT_JUMPLIST
+ vi_jumplist = (xfmark_T *)alloc_clear(JUMPLISTSIZE
+ * (int)sizeof(xfmark_T));
+ vi_jumplist_len = 0;
+ #endif
+ }
+
+ void
+ finish_viminfo_marks(void)
+ {
+ int i;
+
+ if (vi_namedfm != NULL)
+ {
+ for (i = 0; i < NMARKS + EXTRA_MARKS; ++i)
+ vim_free(vi_namedfm[i].fname);
+ vim_free(vi_namedfm);
+ vi_namedfm = NULL;
+ }
+ #ifdef FEAT_JUMPLIST
+ if (vi_jumplist != NULL)
+ {
+ for (i = 0; i < vi_jumplist_len; ++i)
+ vim_free(vi_jumplist[i].fname);
+ vim_free(vi_jumplist);
+ vi_jumplist = NULL;
+ }
+ #endif
+ }
+
+ /*
+ * Accept a new style mark line from the viminfo, store it when it's new.
+ */
+ void
+ handle_viminfo_mark(garray_T *values, int force)
+ {
+ bval_T *vp = (bval_T *)values->ga_data;
+ int name;
+ linenr_T lnum;
+ colnr_T col;
+ time_t timestamp;
+ xfmark_T *fm = NULL;
+
+ /* Check the format:
+ * |{bartype},{name},{lnum},{col},{timestamp},{filename} */
+ if (values->ga_len < 5
+ || vp[0].bv_type != BVAL_NR
+ || vp[1].bv_type != BVAL_NR
+ || vp[2].bv_type != BVAL_NR
+ || vp[3].bv_type != BVAL_NR
+ || vp[4].bv_type != BVAL_STRING)
+ return;
+
+ name = vp[0].bv_nr;
+ if (name != '\'' && !VIM_ISDIGIT(name) && !ASCII_ISUPPER(name))
+ return;
+ lnum = vp[1].bv_nr;
+ col = vp[2].bv_nr;
+ if (lnum <= 0 || col < 0)
+ return;
+ timestamp = (time_t)vp[3].bv_nr;
+
+ if (name == '\'')
+ {
+ #ifdef FEAT_JUMPLIST
+ if (vi_jumplist != NULL)
+ {
+ if (vi_jumplist_len < JUMPLISTSIZE)
+ fm = &vi_jumplist[vi_jumplist_len++];
+ }
+ else
+ {
+ int idx;
+ int i;
+
+ /* If we have a timestamp insert it in the right place. */
+ if (timestamp != 0)
+ {
+ for (idx = curwin->w_jumplistlen - 1; idx >= 0; --idx)
+ if (curwin->w_jumplist[idx].time_set < timestamp)
+ break;
+ }
+ else if (curwin->w_jumplistlen < JUMPLISTSIZE)
+ /* insert as oldest entry */
+ idx = 0;
+ else
+ idx = -1;
+
+ if (idx >= 0)
+ {
+ if (curwin->w_jumplistlen == JUMPLISTSIZE)
+ {
+ /* Drop the oldest entry. */
+ vim_free(curwin->w_jumplist[0].fname);
+ for (i = 0; i < idx; ++i)
+ curwin->w_jumplist[i] = curwin->w_jumplist[i + 1];
+ }
+ else
+ {
+ /* Move newer entries forward. */
+ ++idx;
+ for (i = curwin->w_jumplistlen; i > idx; --i)
+ curwin->w_jumplist[i] = curwin->w_jumplist[i - 1];
+ ++curwin->w_jumplistidx;
+ ++curwin->w_jumplistlen;
+ }
+ fm = &curwin->w_jumplist[idx];
+ fm->fmark.mark.lnum = 0;
+ fm->fname = NULL;
+ fm->time_set = 0;
+ }
+ }
+ #endif
+ }
+ else
+ {
+ int idx;
+
+ if (VIM_ISDIGIT(name))
+ {
+ if (vi_namedfm != NULL)
+ idx = name - '0' + NMARKS;
+ else
+ {
+ int i;
+
+ /* Do not use the name from the viminfo file, insert in time
+ * order. */
+ for (idx = NMARKS; idx < NMARKS + EXTRA_MARKS; ++idx)
+ if (namedfm[idx].time_set < timestamp)
+ break;
+ if (idx == NMARKS + EXTRA_MARKS)
+ /* All existing entries are newer. */
+ return;
+ i = NMARKS + EXTRA_MARKS - 1;
+
+ vim_free(namedfm[i].fname);
+ for ( ; i > idx; --i)
+ namedfm[i] = namedfm[i - 1];
+ namedfm[idx].fname = NULL;
+ }
+ }
+ else
+ idx = name - 'A';
+ if (vi_namedfm != NULL)
+ fm = &vi_namedfm[idx];
+ else
+ fm = &namedfm[idx];
+ }
+
+ if (fm != NULL)
+ {
+ if (vi_namedfm != NULL || fm->time_set < timestamp || force)
+ {
+ fm->fmark.mark.lnum = lnum;
+ fm->fmark.mark.col = col;
+ #ifdef FEAT_VIRTUALEDIT
+ fm->fmark.mark.coladd = 0;
+ #endif
+ fm->fmark.fnum = 0;
+ vim_free(fm->fname);
+ if (vp[4].bv_allocated)
+ {
+ fm->fname = vp[4].bv_string;
+ vp[4].bv_string = NULL;
+ }
+ else
+ fm->fname = vim_strsave(vp[4].bv_string);
+ fm->time_set = timestamp;
+ }
+ }
+ }
+
void
write_viminfo_filemarks(FILE *fp)
{
***************
*** 1412,1428 ****
char_u *name;
buf_T *buf;
xfmark_T *fm;
if (get_viminfo_parameter('f') == 0)
return;
fputs(_("\n# File marks:\n"), fp);
/*
* Find a mark that is the same file and position as the cursor.
* That one, or else the last one is deleted.
* Move '0 to '1, '1 to '2, etc. until the matching one or '9
! * Set '0 mark to current cursor position.
*/
if (curbuf->b_ffname != NULL && !removable(curbuf->b_ffname))
{
--- 1618,1647 ----
char_u *name;
buf_T *buf;
xfmark_T *fm;
+ int vi_idx;
+ int idx;
if (get_viminfo_parameter('f') == 0)
return;
fputs(_("\n# File marks:\n"), fp);
+ /* Write the filemarks 'A - 'Z */
+ for (i = 0; i < NMARKS; i++)
+ {
+ if (vi_namedfm != NULL && (vi_namedfm[i].time_set > namedfm[i].time_set
+ || namedfm[i].fmark.mark.lnum == 0))
+ fm = &vi_namedfm[i];
+ else
+ fm = &namedfm[i];
+ write_one_filemark(fp, fm, '\'', i + 'A');
+ }
+
/*
* Find a mark that is the same file and position as the cursor.
* That one, or else the last one is deleted.
* Move '0 to '1, '1 to '2, etc. until the matching one or '9
! * Set the '0 mark to current cursor position.
*/
if (curbuf->b_ffname != NULL && !removable(curbuf->b_ffname))
{
***************
*** 1442,1459 ****
namedfm[NMARKS].fmark.mark = curwin->w_cursor;
namedfm[NMARKS].fmark.fnum = curbuf->b_fnum;
namedfm[NMARKS].fname = NULL;
}
! /* Write the filemarks '0 - '9 and 'A - 'Z */
! for (i = 0; i < NMARKS + EXTRA_MARKS; i++)
! write_one_filemark(fp, &namedfm[i], '\'',
! i < NMARKS ? i + 'A' : i - NMARKS + '0');
#ifdef FEAT_JUMPLIST
/* Write the jumplist with -' */
fputs(_("\n# Jumplist (newest first):\n"), fp);
setpcmark(); /* add current cursor position */
cleanup_jumplist();
for (fm = &curwin->w_jumplist[curwin->w_jumplistlen - 1];
fm >= &curwin->w_jumplist[0]; --fm)
{
--- 1661,1690 ----
namedfm[NMARKS].fmark.mark = curwin->w_cursor;
namedfm[NMARKS].fmark.fnum = curbuf->b_fnum;
namedfm[NMARKS].fname = NULL;
+ namedfm[NMARKS].time_set = vim_time();
}
! /* Write the filemarks '0 - '9. Newest (highest timestamp) first. */
! vi_idx = NMARKS;
! idx = NMARKS;
! for (i = NMARKS; i < NMARKS + EXTRA_MARKS; i++)
! {
! if (vi_namedfm != NULL
! && vi_namedfm[vi_idx].fmark.mark.lnum != 0
! && (vi_namedfm[vi_idx].time_set > namedfm[idx].time_set
! || namedfm[idx].fmark.mark.lnum == 0))
! fm = &vi_namedfm[vi_idx++];
! else
! fm = &namedfm[idx++];
! write_one_filemark(fp, fm, '\'', i - NMARKS + '0');
! }
#ifdef FEAT_JUMPLIST
/* Write the jumplist with -' */
fputs(_("\n# Jumplist (newest first):\n"), fp);
setpcmark(); /* add current cursor position */
cleanup_jumplist();
+ /* TODO: when vi_jumplist != NULL merge the two lists. */
for (fm = &curwin->w_jumplist[curwin->w_jumplistlen - 1];
fm >= &curwin->w_jumplist[0]; --fm)
{
***************
*** 1486,1491 ****
--- 1717,1730 ----
fprintf(fp, "%c%c %ld %ld ", c1, c2, (long)fm->fmark.mark.lnum,
(long)fm->fmark.mark.col);
viminfo_writestring(fp, name);
+
+ /* Barline: |{bartype},{name},{lnum},{col},{timestamp},{filename}
+ * size up to filename: 8 + 3 * 20 */
+ fprintf(fp, "|%d,%d,%ld,%ld,%ld,", BARTYPE_MARK, c2,
+ (long)fm->fmark.mark.lnum, (long)fm->fmark.mark.col,
+ (long)fm->time_set);
+ barline_writestring(fp, name, LSIZE - 70);
+ putc('\n', fp);
}
if (fm->fmark.fnum != 0)
*** ../vim-7.4.1924/src/ex_cmds.c 2016-06-11 22:20:59.446252026 +0200
--- src/ex_cmds.c 2016-06-12 20:55:58.594111616 +0200
***************
*** 1983,1988 ****
--- 1983,1990 ----
*/
if (*wp == 'a')
{
+ EMSG2(_("E929: Too many viminfo temp files, like %s!"),
+ tempname);
vim_free(tempname);
tempname = NULL;
break;
***************
*** 2164,2172 ****
{
if (flags & VIF_WANT_INFO)
{
- /* Registers are read and newer ones are used when writing. */
if (fp_out != NULL)
prepare_viminfo_registers();
eof = read_viminfo_up_to_marks(&vir,
flags & VIF_FORCEIT, fp_out != NULL);
--- 2166,2178 ----
{
if (flags & VIF_WANT_INFO)
{
if (fp_out != NULL)
+ {
+ /* Registers and marks are read and kept separate from what
+ * this Vim is using. They are merged when writing. */
prepare_viminfo_registers();
+ prepare_viminfo_marks();
+ }
eof = read_viminfo_up_to_marks(&vir,
flags & VIF_FORCEIT, fp_out != NULL);
***************
*** 2200,2205 ****
--- 2206,2212 ----
write_viminfo_varlist(fp_out);
#endif
write_viminfo_filemarks(fp_out);
+ finish_viminfo_marks();
write_viminfo_bufferlist(fp_out);
write_viminfo_barlines(&vir, fp_out);
count = write_viminfo_marks(fp_out);
***************
*** 2778,2783 ****
--- 2785,2795 ----
handle_viminfo_register(&values, force);
break;
+ case BARTYPE_MARK:
+ barline_parse(virp, p, &values);
+ handle_viminfo_mark(&values, force);
+ break;
+
default:
/* copy unrecognized line (for future use) */
if (writing)
*** ../vim-7.4.1924/src/ex_docmd.c 2016-06-09 22:52:56.207926413 +0200
--- src/ex_docmd.c 2016-06-12 20:33:21.728710974 +0200
***************
*** 474,479 ****
--- 474,480 ----
#endif
#ifndef FEAT_JUMPLIST
# define ex_jumps ex_ni
+ # define ex_clearjumps ex_ni
# define ex_changes ex_ni
#endif
*** ../vim-7.4.1924/src/proto/mark.pro 2016-01-19 13:21:55.841334333 +0100
--- src/proto/mark.pro 2016-06-12 20:40:12.128282992 +0200
***************
*** 16,21 ****
--- 16,22 ----
void do_marks(exarg_T *eap);
void ex_delmarks(exarg_T *eap);
void ex_jumps(exarg_T *eap);
+ void ex_clearjumps(exarg_T *eap);
void ex_changes(exarg_T *eap);
void mark_adjust(linenr_T line1, linenr_T line2, long amount, long
amount_after);
void mark_col_adjust(linenr_T lnum, colnr_T mincol, long lnum_amount, long
col_amount);
***************
*** 24,29 ****
--- 25,33 ----
void set_last_cursor(win_T *win);
void free_all_marks(void);
int read_viminfo_filemark(vir_T *virp, int force);
+ void prepare_viminfo_marks(void);
+ void finish_viminfo_marks(void);
+ void handle_viminfo_mark(garray_T *values, int force);
void write_viminfo_filemarks(FILE *fp);
int removable(char_u *name);
int write_viminfo_marks(FILE *fp_out);
*** ../vim-7.4.1924/src/structs.h 2016-06-06 21:07:48.383578685 +0200
--- src/structs.h 2016-06-12 15:49:28.984338910 +0200
***************
*** 84,90 ****
# ifdef FEAT_XCLIPBOARD
# include <X11/Intrinsic.h>
# endif
! # define guicolor_T long_u /* avoid error in prototypes and
* make FEAT_TERMGUICOLORS work */
# define INVALCOLOR ((guicolor_T)0x1ffffff)
#endif
--- 84,90 ----
# ifdef FEAT_XCLIPBOARD
# include <X11/Intrinsic.h>
# endif
! # define guicolor_T long_u /* avoid error in prototypes and
* make FEAT_TERMGUICOLORS work */
# define INVALCOLOR ((guicolor_T)0x1ffffff)
#endif
***************
*** 112,117 ****
--- 112,120 ----
{
fmark_T fmark;
char_u *fname; /* file name, used when fnum == 0 */
+ #ifdef FEAT_VIMINFO
+ time_t time_set;
+ #endif
} xfmark_T;
/*
*** ../vim-7.4.1924/src/vim.h 2016-06-11 21:04:34.927761279 +0200
--- src/vim.h 2016-06-12 15:16:02.318118048 +0200
***************
*** 1076,1085 ****
#define BARTYPE_VERSION 1
#define BARTYPE_HISTORY 2
#define BARTYPE_REGISTER 3
! #define VIMINFO_VERSION 3
#define VIMINFO_VERSION_WITH_HISTORY 2
#define VIMINFO_VERSION_WITH_REGISTERS 3
typedef enum {
BVAL_NR,
--- 1076,1087 ----
#define BARTYPE_VERSION 1
#define BARTYPE_HISTORY 2
#define BARTYPE_REGISTER 3
+ #define BARTYPE_MARK 4
! #define VIMINFO_VERSION 4
#define VIMINFO_VERSION_WITH_HISTORY 2
#define VIMINFO_VERSION_WITH_REGISTERS 3
+ #define VIMINFO_VERSION_WITH_MARKS 4
typedef enum {
BVAL_NR,
*** ../vim-7.4.1924/src/ex_cmds.h 2016-04-14 18:42:37.330439451 +0200
--- src/ex_cmds.h 2016-06-12 20:32:01.065581129 +0200
***************
*** 316,321 ****
--- 316,324 ----
EX(CMD_close, "close", ex_close,
BANG|RANGE|NOTADR|COUNT|TRLBAR|CMDWIN,
ADDR_WINDOWS),
+ EX(CMD_clearjumps, "clearjumps", ex_clearjumps,
+ TRLBAR|CMDWIN,
+ ADDR_LINES),
EX(CMD_cmap, "cmap", ex_map,
EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN,
ADDR_LINES),
*** ../vim-7.4.1924/src/testdir/test_viminfo.vim 2016-06-11
21:14:14.121484821 +0200
--- src/testdir/test_viminfo.vim 2016-06-12 21:10:08.024815341 +0200
***************
*** 17,25 ****
let lines = readfile('Xviminfo')
let done = 0
for line in lines
! if line[0] == '|' && line !~ '^|3,'
if done == 0
! call assert_equal('|1,3', line)
elseif done == 1
call assert_equal('|copied as-is', line)
elseif done == 2
--- 17,25 ----
let lines = readfile('Xviminfo')
let done = 0
for line in lines
! if line[0] == '|' && line !~ '^|[234],'
if done == 0
! call assert_equal('|1,4', line)
elseif done == 1
call assert_equal('|copied as-is', line)
elseif done == 2
***************
*** 217,222 ****
--- 217,318 ----
call delete('Xviminfo')
endfunc
+ func Test_viminfo_marks()
+ sp bufa
+ let bufa = bufnr('%')
+ sp bufb
+ let bufb = bufnr('%')
+
+ call test_settime(8)
+ call setpos("'A", [bufa, 1, 1, 0])
+ call test_settime(20)
+ call setpos("'B", [bufb, 9, 1, 0])
+ call setpos("'C", [bufa, 7, 1, 0])
+
+ delmark 0-9
+ call test_settime(25)
+ call setpos("'1", [bufb, 12, 1, 0])
+ call test_settime(35)
+ call setpos("'0", [bufa, 11, 1, 0])
+
+ call test_settime(45)
+ wviminfo Xviminfo
+
+ " Writing viminfo inserts the '0 mark.
+ call assert_equal([bufb, 1, 1, 0], getpos("'0"))
+ call assert_equal([bufa, 11, 1, 0], getpos("'1"))
+ call assert_equal([bufb, 12, 1, 0], getpos("'2"))
+
+ call test_settime(4)
+ call setpos("'A", [bufa, 9, 1, 0])
+ call test_settime(30)
+ call setpos("'B", [bufb, 2, 3, 0])
+ delmark C
+
+ delmark 0-9
+ call test_settime(30)
+ call setpos("'1", [bufb, 22, 1, 0])
+ call test_settime(55)
+ call setpos("'0", [bufa, 21, 1, 0])
+
+ rviminfo Xviminfo
+
+ call assert_equal([bufa, 1, 1, 0], getpos("'A"))
+ call assert_equal([bufb, 2, 3, 0], getpos("'B"))
+ call assert_equal([bufa, 7, 1, 0], getpos("'C"))
+
+ " numbered marks are merged
+ call assert_equal([bufa, 21, 1, 0], getpos("'0")) " time 55
+ call assert_equal([bufb, 1, 1, 0], getpos("'1")) " time 45
+ call assert_equal([bufa, 11, 1, 0], getpos("'2")) " time 35
+ call assert_equal([bufb, 22, 1, 0], getpos("'3")) " time 30
+ call assert_equal([bufb, 12, 1, 0], getpos("'4")) " time 25
+
+ call delete('Xviminfo')
+ exe 'bwipe ' . bufa
+ exe 'bwipe ' . bufb
+ endfunc
+
+ func Test_viminfo_jumplist()
+ split testbuf
+ clearjumps
+ call setline(1, ['time 05', 'time 10', 'time 15', 'time 20', 'time 30',
'last pos'])
+ call cursor(2, 1)
+ call test_settime(10)
+ exe "normal /20\r"
+ call test_settime(20)
+ exe "normal /30\r"
+ call test_settime(30)
+ exe "normal /last pos\r"
+ wviminfo Xviminfo
+
+ clearjumps
+ call cursor(1, 1)
+ call test_settime(5)
+ exe "normal /15\r"
+ call test_settime(15)
+ exe "normal /last pos\r"
+ call test_settime(40)
+ exe "normal ?30\r"
+ rviminfo Xviminfo
+
+ call assert_equal('time 30', getline('.'))
+ exe "normal \<C-O>"
+ call assert_equal('last pos', getline('.'))
+ exe "normal \<C-O>"
+ " duplicate for 'time 30' was removed
+ call assert_equal('time 20', getline('.'))
+ exe "normal \<C-O>"
+ call assert_equal('time 15', getline('.'))
+ exe "normal \<C-O>"
+ call assert_equal('time 10', getline('.'))
+ exe "normal \<C-O>"
+ call assert_equal('time 05', getline('.'))
+
+ bwipe!
+ call delete('Xviminfo')
+ endfunc
+
func Test_viminfo_encoding()
if !has('multi_byte')
return
*** ../vim-7.4.1924/src/version.c 2016-06-12 21:18:38.207260690 +0200
--- src/version.c 2016-06-12 21:19:57.294412705 +0200
***************
*** 755,756 ****
--- 755,758 ----
{ /* Add new patch number below this line */
+ /**/
+ 1925,
/**/
--
Warning label on a superhero Halloween costume:
"Caution: Cape does not enable user to fly."
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.