diff options
-rw-r--r-- | runtime/doc/todo.txt | 30 | ||||
-rw-r--r-- | runtime/doc/version7.txt | 27 | ||||
-rw-r--r-- | src/config.mk.in | 2 | ||||
-rw-r--r-- | src/eval.c | 98 | ||||
-rw-r--r-- | src/ex_cmds.c | 150 | ||||
-rw-r--r-- | src/ex_cmds.h | 2 | ||||
-rw-r--r-- | src/proto/ex_cmds.pro | 1 |
7 files changed, 259 insertions, 51 deletions
diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index faf2c60c2a..4fcaec6e57 100644 --- 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 Vim development. See |sponsor|. *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 break. 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. diff --git a/runtime/doc/version7.txt b/runtime/doc/version7.txt index 31507e03a2..f7d86650e9 100644 --- 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 manual pages in .../man/it/man1/, 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 works in the console. (Vipin Aravind) |: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 stored in the viminfo file. 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 name. |:redir| 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 they may come at an unexpected moment. 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: diff --git a/src/config.mk.in b/src/config.mk.in index d5103ecd4c..e750202a30 100644 --- 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@ diff --git a/src/eval.c b/src/eval.c index 6b16cf9b64..7c9cccaf2b 100644 --- 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; + 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); - line = get_tv_string(&argvars[1]); - rettv->vval.v_number = 1; /* FAIL is default */ + 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]); - if (lnum >= 1 - && lnum <= curbuf->b_ml.ml_line_count - && u_savesub(lnum) == OK - && ml_replace(lnum, line, TRUE) == OK) + rettv->vval.v_number = 0; /* OK */ + for (;;) { - changed_bytes(lnum, 0); - check_cursor_col(); - rettv->vval.v_number = 0; + 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) - pat = (char_u *)"[\\x01- ]\\+"; - else + 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- ]\\+"; 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) + while (*str != NUL || keepempty) { - match = vim_regexec_nl(®match, str, col); + if (*str == NUL) + match = FALSE; /* empty item at the end */ + else + match = vim_regexec_nl(®match, 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) diff --git a/src/ex_cmds.c b/src/ex_cmds.c index 46a30c1b9d..20bba1c8b6 100644 --- 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(®match, 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". */ diff --git a/src/ex_cmds.h b/src/ex_cmds.h index 8eada96b92..eb11fb9fe3 100644 --- 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, diff --git a/src/proto/ex_cmds.pro b/src/proto/ex_cmds.pro index 50238bbf8e..baa1233538 100644 --- 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)); |