changeset 284:e697bd3c3876 v7.0075

updated for version 7.0075
author vimboss
date Sun, 22 May 2005 22:12:58 +0000
parents a2ff714de3db
children 6c7fb97ce82e
files runtime/doc/todo.txt runtime/doc/version7.txt src/config.mk.in src/eval.c src/ex_cmds.c src/ex_cmds.h src/proto/ex_cmds.pro
diffstat 7 files changed, 264 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -1,4 +1,4 @@
-*todo.txt*      For Vim version 7.0aa.  Last change: 2005 May 20
+*todo.txt*      For Vim version 7.0aa.  Last change: 2005 May 22
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -30,29 +30,13 @@ be worked on, but only if you sponsor Vi
 							*known-bugs*
 -------------------- Known bugs and current work -----------------------
 
-Problem with ":mksession" for "vim -o "+argdel *" prog1 prog2 prog3"
-(Bill McCarthy, 2005 April 26)
-
-getreg('=') returns the result of evaluating the expression.  How to get the
-expression itself, so that it can be restored? (David Fishburn)  Perhaps use
-getreg('=', 1).  Also make setreg('=') work then.
-
-Use "file::func()" for autoload?
-
-Win32: With the taskbar at the top of the screen, scrolling doesn't redraw
-properly. (Sergey Khorev, 2005 April 27)
+Make option like 'verbose' that writes output into a file?  Should make it
+possible to see what's happening without messing up the display.
 
 Mac unicode patch (Da Woon Jung):
 - selecting proportional font breaks display
 - UTF-8 text causes display problems.  Font replacement causes this.
 
-When 'shortmess' is empty and 'keymap' set to accents, in Insert mode CTRL-N
-may cause the hit-enter prompt.  Typing 'a then doesn't result in the accented
-character. (Ilya Dogolazky)
-
-split(): keep empty items halfway.  With an option also keep empty items at
-start and end. (Johnny Blaze)
-
 autoload:
 - Add a Vim script in $VIMRUNTIME/tools that takes a file with a list of
   script names and a help file and produces a script that can be sourced to
@@ -69,11 +53,6 @@ Win32: Balloon text can't contain line b
     Patch from Sergey Khorev, 2005 Apr 11
     Add has("balloon_multiline")
 
-setline() should accept a List.
-
-Add ":[range]sort" command.  Sort on specified field, using a regexp?  Remove
-duplicates?
-
 Patch to alternate fold highlighting.  (Anthony Iano-Fletcher, 2005 May 12)
 More levels?
 
@@ -82,9 +61,6 @@ Awaiting response:
 -   Win32: tearoff menu window should have a scrollbar when it's taller than
     the screen.
 
-Make option like 'verbose' that writes output into a file?  Should make it
-possible to see what's happening without messing up the display.
-
 Patch for if_python to make exit work better with threads. (ugo)
 Still seems to fail 15% of the time.
 
--- a/runtime/doc/version7.txt
+++ b/runtime/doc/version7.txt
@@ -1,4 +1,4 @@
-*version7.txt*  For Vim version 7.0aa.  Last change: 2005 May 20
+*version7.txt*  For Vim version 7.0aa.  Last change: 2005 May 22
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -192,6 +192,9 @@ The Unix Makefile installs the Italian m
 standard for what encoding goes in the "it" directory, the 8-bit encoded file
 is used there as a best guess.
 Other languages are installed in similar places.
+The translated pages are not automatically installed when Vim was configured
+with "--disable-nls", but "make install-languages install-tool-languages" will
+do it anyway.
 
 
 Internal grep						*new-vimgrep*
@@ -319,6 +322,10 @@ Win32: The ":winpos" command now also wo
 |:cbuffer|		Read error lines from a buffer. (partly by Yegappan
 			Lakshmanan)
 
+|:sort|			Sort lines in the buffer without depending on an
+			external command.
+
+
 New functions: ~
 
 |add()|			append an item to a List
@@ -569,12 +576,14 @@ When a register is empty it is not store
 
 Removed the tcltags script, it's obsolete.
 
-":redir @*>" and ":redir @+>" append to the clipboard.  Better check for
+":redir @*>>" and ":redir @+>>" append to the clipboard.  Better check for
 invalid characters after the register name. |:redir|
 
 ":redir => variable" and ":redir =>> variable" write or append to a variable.
 (Yegappan Lakshmanan) |:redir|
 
+":redir @{a-z}>>" appends to register a to z.
+
 ":let g:" lists global variables.
 ":let b:" lists buffer-local variables.
 ":let w:" lists window-local variables.
@@ -583,6 +592,12 @@ invalid characters after the register na
 The stridx() and strridx() functions take a third argument, where to start
 searching.  (Yegappan Lakshmanan)
 
+The getreg() function takes an extra argument to be able to get the expression
+for the '=' register instead of the result of evaluating it.
+
+The setline() function can take a List argument to set multiple lines.  When
+the line number is just below the last line the line is appended.
+
 g CTRL-G also shows the number of characters if it differs from the number of
 bytes.
 
@@ -1084,4 +1099,12 @@ change the window size ourselves, but th
 Peek for a character to get any window resize events and fix 'columns' and
 'lines' to undo this.
 
+After deleting files from the argument list a session file generated with
+":mksession" may contain invalid ":next" commands.
+
+When 'shortmess' is empty and 'keymap' set to accents, in Insert mode CTRL-N
+may cause the hit-enter prompt.  Typing 'a then didn't result in the accented
+character.  Put the character typed at the prompt back in the typeahead buffer
+so that mapping is done in the right mode.
+
  vim:tw=78:ts=8:ft=help:norl:
--- a/src/config.mk.in
+++ b/src/config.mk.in
@@ -93,6 +93,8 @@ COMPILEDBY	= @compiledby@
 
 INSTALLVIMDIFF	= @dovimdiff@
 INSTALLGVIMDIFF	= @dogvimdiff@
+INSTALL_LANGS	= @INSTALL_LANGS@
+INSTALL_TOOL_LANGS	= @INSTALL_TOOL_LANGS@
 
 ### Line break character as octal number for "tr"
 NL		= @line_break@
--- a/src/eval.c
+++ b/src/eval.c
@@ -1878,7 +1878,7 @@ ex_let_one(arg, tv, copy, endchars, op)
 	    p = get_tv_string(tv);
 	    if (op != NULL && *op == '.')
 	    {
-		s = get_reg_contents(*arg == '@' ? '"' : *arg, FALSE);
+		s = get_reg_contents(*arg == '@' ? '"' : *arg, FALSE, FALSE);
 		if (s != NULL)
 		{
 		    p = tofree = concat_str(s, p);
@@ -4092,7 +4092,8 @@ eval7(arg, rettv, evaluate)
 		if (evaluate)
 		{
 		    rettv->v_type = VAR_STRING;
-		    rettv->vval.v_string = get_reg_contents(**arg, FALSE);
+		    rettv->vval.v_string = get_reg_contents(**arg,
+								FALSE, FALSE);
 		}
 		if (**arg != NUL)
 		    ++*arg;
@@ -6158,7 +6159,7 @@ static struct fst
     {"getftype",	1, 1, f_getftype},
     {"getline",		1, 2, f_getline},
     {"getqflist",	0, 0, f_getqflist},
-    {"getreg",		0, 1, f_getreg},
+    {"getreg",		0, 2, f_getreg},
     {"getregtype",	0, 1, f_getregtype},
     {"getwinposx",	0, 0, f_getwinposx},
     {"getwinposy",	0, 0, f_getwinposy},
@@ -6239,7 +6240,7 @@ static struct fst
     {"setwinvar",	3, 3, f_setwinvar},
     {"simplify",	1, 1, f_simplify},
     {"sort",		1, 2, f_sort},
-    {"split",		1, 2, f_split},
+    {"split",		1, 3, f_split},
 #ifdef HAVE_STRFTIME
     {"strftime",	1, 2, f_strftime},
 #endif
@@ -8970,9 +8971,14 @@ f_getreg(argvars, rettv)
 {
     char_u	*strregname;
     int		regname;
+    int		arg2 = FALSE;
 
     if (argvars[0].v_type != VAR_UNKNOWN)
+    {
 	strregname = get_tv_string(&argvars[0]);
+	if (argvars[1].v_type != VAR_UNKNOWN)
+	    arg2 = get_tv_number(&argvars[1]);
+    }
     else
 	strregname = vimvars[VV_REG].vv_str;
     regname = (strregname == NULL ? '"' : *strregname);
@@ -8980,7 +8986,7 @@ f_getreg(argvars, rettv)
 	regname = '"';
 
     rettv->v_type = VAR_STRING;
-    rettv->vval.v_string = get_reg_contents(regname, TRUE);
+    rettv->vval.v_string = get_reg_contents(regname, TRUE, arg2);
 }
 
 /*
@@ -12345,20 +12351,60 @@ f_setline(argvars, rettv)
 {
     linenr_T	lnum;
     char_u	*line;
-
-    lnum = get_tv_lnum(argvars);
-    line = get_tv_string(&argvars[1]);
-    rettv->vval.v_number = 1;		/* FAIL is default */
-
-    if (lnum >= 1
-	    && lnum <= curbuf->b_ml.ml_line_count
-	    && u_savesub(lnum) == OK
-	    && ml_replace(lnum, line, TRUE) == OK)
-    {
-	changed_bytes(lnum, 0);
-	check_cursor_col();
-	rettv->vval.v_number = 0;
-    }
+    list_T	*l = NULL;
+    listitem_T	*li = NULL;
+    long	added = 0;
+    linenr_T	lcount = curbuf->b_ml.ml_line_count;
+
+    lnum = get_tv_lnum(&argvars[0]);
+    if (argvars[1].v_type == VAR_LIST)
+    {
+	l = argvars[1].vval.v_list;
+	li = l->lv_first;
+    }
+    else
+	line = get_tv_string(&argvars[1]);
+
+    rettv->vval.v_number = 0;		/* OK */
+    for (;;)
+    {
+	if (l != NULL)
+	{
+	    /* list argument, get next string */
+	    if (li == NULL)
+		break;
+	    line = get_tv_string(&li->li_tv);
+	    li = li->li_next;
+	}
+
+	rettv->vval.v_number = 1;	/* FAIL */
+	if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
+	    break;
+	if (lnum <= curbuf->b_ml.ml_line_count)
+	{
+	    /* existing line, replace it */
+	    if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK)
+	    {
+		changed_bytes(lnum, 0);
+		check_cursor_col();
+		rettv->vval.v_number = 0;	/* OK */
+	    }
+	}
+	else if (added > 0 || u_save(lnum - 1, lnum) == OK)
+	{
+	    /* lnum is one past the last line, append the line */
+	    ++added;
+	    if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK)
+		rettv->vval.v_number = 0;	/* OK */
+	}
+
+	if (l == NULL)			/* only one string argument */
+	    break;
+	++lnum;
+    }
+
+    if (added > 0)
+	appended_lines_mark(lcount, added);
 }
 
 /*
@@ -12695,7 +12741,7 @@ f_split(argvars, rettv)
 {
     char_u	*str;
     char_u	*end;
-    char_u	*pat;
+    char_u	*pat = NULL;
     regmatch_T	regmatch;
     char_u	patbuf[NUMBUFLEN];
     char_u	*save_cpo;
@@ -12703,16 +12749,21 @@ f_split(argvars, rettv)
     listitem_T	*ni;
     list_T	*l;
     colnr_T	col = 0;
+    int		keepempty = FALSE;
 
     /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
     save_cpo = p_cpo;
     p_cpo = (char_u *)"";
 
     str = get_tv_string(&argvars[0]);
-    if (argvars[1].v_type == VAR_UNKNOWN)
+    if (argvars[1].v_type != VAR_UNKNOWN)
+    {
+	pat = get_tv_string_buf(&argvars[1], patbuf);
+	if (argvars[2].v_type != VAR_UNKNOWN)
+	    keepempty = get_tv_number(&argvars[2]);
+    }
+    if (pat == NULL || *pat == NUL)
 	pat = (char_u *)"[\\x01- ]\\+";
-    else
-	pat = get_tv_string_buf(&argvars[1], patbuf);
 
     l = list_alloc();
     if (l == NULL)
@@ -12725,14 +12776,17 @@ f_split(argvars, rettv)
     if (regmatch.regprog != NULL)
     {
 	regmatch.rm_ic = FALSE;
-	while (*str != NUL)
-	{
-	    match = vim_regexec_nl(&regmatch, str, col);
+	while (*str != NUL || keepempty)
+	{
+	    if (*str == NUL)
+		match = FALSE;	/* empty item at the end */
+	    else
+		match = vim_regexec_nl(&regmatch, str, col);
 	    if (match)
 		end = regmatch.startp[0];
 	    else
 		end = str + STRLEN(str);
-	    if (end > str)
+	    if (keepempty || end > str || (l->lv_len > 0 && *str != NUL))
 	    {
 		ni = listitem_alloc();
 		if (ni == NULL)
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -261,6 +261,156 @@ linelen(has_tab)
     return len;
 }
 
+/* Buffer for one line used during sorting.  It's allocated to contain the
+ * longest line being sorted. */
+static char_u	*sortbuf;
+
+static int	sort_ic;		/* ignore case */
+
+static int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+sort_compare __ARGS((const void *s1, const void *s2));
+
+    static int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+sort_compare(s1, s2)
+    const void	*s1;
+    const void	*s2;
+{
+    lpos_T	l1 = *(lpos_T *)s1;
+    lpos_T	l2 = *(lpos_T *)s2;
+    char_u	*s;
+
+    /* We need to copy one line into "sortbuf", because there is no guarantee
+     * that the first pointer becomes invalid when obtaining the second one. */
+    STRCPY(sortbuf, ml_get(l1.lnum) + l1.col);
+    s = ml_get(l2.lnum) + l2.col;
+    return sort_ic ? STRICMP(sortbuf, s) : STRCMP(sortbuf, s);
+}
+
+/*
+ * ":sort".
+ */
+    void
+ex_sort(eap)
+    exarg_T	*eap;
+{
+    regmatch_T	regmatch;
+    int		len;
+    linenr_T	lnum;
+    long	maxlen = 0;
+    lpos_T	*nrs;
+    size_t	count = eap->line2 - eap->line1 + 1;
+    int		i;
+    char_u	*p;
+    char_u	*s;
+    int		unique = FALSE;
+    long	deleted;
+
+    if (u_save((linenr_T)(eap->line1 - 1), (linenr_T)(eap->line2 + 1)) == FAIL)
+	return;
+    sortbuf = NULL;
+    regmatch.regprog = NULL;
+    nrs = (lpos_T *)lalloc((long_u)(count * sizeof(lpos_T)), TRUE);
+    if (nrs == NULL)
+	goto theend;
+
+    for (p = eap->arg; *p != NUL; ++p)
+    {
+	if (vim_iswhite(*p))
+	    ;
+	else if (*p == 'i')
+	    sort_ic = TRUE;
+	else if (*p == 'u')
+	    unique = TRUE;
+	else if (!ASCII_ISALPHA(*p))
+	{
+	    s = skip_regexp(p + 1, *p, TRUE, NULL);
+	    if (*s != *p)
+	    {
+		EMSG(_(e_invalpat));
+		goto theend;
+	    }
+	    *s = NUL;
+	    regmatch.regprog = vim_regcomp(p + 1, RE_MAGIC);
+	    if (regmatch.regprog == NULL)
+		goto theend;
+	    p = s + 1;
+	    regmatch.rm_ic = p_ic;
+	}
+	else
+	{
+	    EMSG2(_(e_invarg2), p);
+	    goto theend;
+	}
+    }
+
+    /*
+     * Make an array with all line numbers, so that we don't have to copy all
+     * the lines into allocated memory.
+     * Also get the longest line length.
+     */
+    for (lnum = eap->line1; lnum <= eap->line2; ++lnum)
+    {
+	nrs[lnum - eap->line1].lnum = lnum;
+	nrs[lnum - eap->line1].col = 0;
+
+	s = ml_get(lnum);
+	if (regmatch.regprog != NULL && vim_regexec(&regmatch, s, 0))
+	    nrs[lnum - eap->line1].col = regmatch.endp[0] - s;
+
+	len = STRLEN(s);
+	if (maxlen < len)
+	    maxlen = len;
+    }
+
+    sortbuf = alloc((unsigned)maxlen + 1);
+    if (sortbuf == NULL)
+	goto theend;
+
+    /* sort the array of line numbers */
+    qsort((void *)nrs, count, sizeof(lpos_T), sort_compare);
+
+    /* Insert the lines in the sorted order below the last one. */
+    lnum = eap->line2;
+    for (i = 0; i < count; ++i)
+    {
+	s = ml_get(nrs[eap->forceit ? count - i - 1 : i].lnum);
+	if (!unique || i == 0
+		|| (sort_ic ? STRICMP(s, sortbuf) : STRCMP(s, sortbuf)) != 0)
+	{
+	    if (ml_append(lnum++, s, (colnr_T)0, FALSE) == FAIL)
+		break;
+	    STRCPY(sortbuf, s);
+	}
+    }
+
+    /* delete the original lines if appending worked */
+    if (i == count)
+	for (i = 0; i < count; ++i)
+	    ml_delete(eap->line1, FALSE);
+    else
+	count = 0;
+
+    deleted = count - (lnum - eap->line2);
+    if (deleted > 0)
+	mark_adjust(eap->line2 - deleted, eap->line2, (long)MAXLNUM, -deleted);
+    else if (deleted < 0)
+	mark_adjust(eap->line2, MAXLNUM, -deleted, 0L);
+    changed_lines(eap->line1, 0, eap->line2 + 1, -deleted);
+    curwin->w_cursor.lnum = eap->line1;
+    beginline(BL_WHITE | BL_FIX);
+
+theend:
+    vim_free(nrs);
+    vim_free(sortbuf);
+    vim_free(regmatch.regprog);
+}
+
 /*
  * ":retab".
  */
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -753,6 +753,8 @@ EX(CMD_snomagic,	"snomagic",	ex_submagic
 			RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY),
 EX(CMD_source,		"source",	ex_source,
 			BANG|FILE1|TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_sort,		"sort",		ex_sort,
+			RANGE|DFLALL|WHOLEFOLD|BANG|EXTRA|NOTRLCOM|MODIFY),
 EX(CMD_split,		"split",	ex_splitview,
 			BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|TRLBAR),
 EX(CMD_sprevious,	"sprevious",	ex_previous,
--- a/src/proto/ex_cmds.pro
+++ b/src/proto/ex_cmds.pro
@@ -1,6 +1,7 @@
 /* ex_cmds.c */
 void do_ascii __ARGS((exarg_T *eap));
 void ex_align __ARGS((exarg_T *eap));
+void ex_sort __ARGS((exarg_T *eap));
 void ex_retab __ARGS((exarg_T *eap));
 int do_move __ARGS((linenr_T line1, linenr_T line2, linenr_T dest));
 void ex_copy __ARGS((linenr_T line1, linenr_T line2, linenr_T n));