0
0
mirror of https://github.com/vim/vim.git synced 2025-08-26 20:03:41 -04:00

updated for version 7.0037

This commit is contained in:
Bram Moolenaar 2005-01-11 21:34:41 +00:00
parent 2a41f3a19f
commit 31c67ef813
5 changed files with 592 additions and 74 deletions

View File

@ -1,4 +1,4 @@
*quickfix.txt* For Vim version 7.0aa. Last change: 2005 Jan 08 *quickfix.txt* For Vim version 7.0aa. Last change: 2005 Jan 10
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@ -300,6 +300,9 @@ advantages are:
enclosing it in / any non-ID character |'isident'| enclosing it in / any non-ID character |'isident'|
can be used, so long as it does not appear in can be used, so long as it does not appear in
{pattern}. {pattern}.
'ignorecase' applies. To overrule it use |/\c| to
ignore case or |/\C| to match case. 'smartcase' is
not used.
Examples: > Examples: >
:vimgrep /an error/ *.c :vimgrep /an error/ *.c
:vimgrep /\<FileName\>/ *.h include/* :vimgrep /\<FileName\>/ *.h include/*

View File

@ -1,4 +1,4 @@
*todo.txt* For Vim version 7.0aa. Last change: 2005 Jan 09 *todo.txt* For Vim version 7.0aa. Last change: 2005 Jan 11
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@ -30,18 +30,15 @@ be worked on, but only if you sponsor Vim development. See |sponsor|.
*known-bugs* *known-bugs*
-------------------- Known bugs and current work ----------------------- -------------------- Known bugs and current work -----------------------
Use 'ignorecase' for ":vimgrep"? Fixes in ex_getln.c also in Vim 6.3.
List: List type:
- map() function: map(list, 'some . & . thing')?
- filter() function: filter(list, '& !~ "^\\s*$"')?
- searchlist() function: like index() but with a regexp.
- Make string() work so that a list can be parsed back?
- Add List functions to version7.txt. - Add List functions to version7.txt.
- Add List functions to overview of funtions in user manual. - Add List functions to overview of funtions in user manual.
- Explain Lists in the user manual? - Explain Lists in the user manual?
Better way to get temp file for tcltags and vimspell scripts. (javier Pena) Better way to get temp file for tcltags and vimspell scripts. (javier Pena)
Possibly leave out code for temp directory.
When allocating a new variable, a search is done for an empty entry. May When allocating a new variable, a search is done for an empty entry. May
waste a lot of time if there isn't one. Keep an index of available entry, waste a lot of time if there isn't one. Keep an index of available entry,
@ -244,6 +241,7 @@ profiling for Vim script?
List data type performance: List data type performance:
- Cache the length of a List? - Cache the length of a List?
- Cache the last used index?
- Use blocks of items, so that finding an item by index is faster? - Use blocks of items, so that finding an item by index is faster?
Awaiting updated patches: Awaiting updated patches:

View File

@ -1,4 +1,4 @@
*version7.txt* For Vim version 7.0aa. Last change: 2005 Jan 09 *version7.txt* For Vim version 7.0aa. Last change: 2005 Jan 11
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@ -94,13 +94,21 @@ New data types *new-data-types*
In Vim scripts the following types have been added: In Vim scripts the following types have been added:
list ordered list of items List ordered list of items |List|
dictionary associative array of items Dictionary associative array of items |Dictionary|
function reference to a function Funcref reference to a function |Funcref|
Many functions and commands have been added to support the new types. Many functions and commands have been added to support the new types.
NOT IMPLEMENTED YET! The Dictionary is NOT IMPLEMENTED YET!
The |string()| function can be used to get a string representation of a
variable. Works for Numbers, Strings and composites of them. Then |eval()|
can be used to turn the string back into the variable value.
The |sharp-string| has been added as a convenient way to put an expression in
a string. Examples: >
:let l = filter(mylist, # & =~ '^\A'#)
KDE support *new-KDE* KDE support *new-KDE*
@ -117,6 +125,7 @@ The MzScheme interpreter is supported. |MzScheme|
The |:mzscheme| command can be used to execute MzScheme commands. The |:mzscheme| command can be used to execute MzScheme commands.
The |:mzfile| command can be used to execute an MzScheme script file. The |:mzfile| command can be used to execute an MzScheme script file.
Printing multi-byte text *new-print-multi-byte* Printing multi-byte text *new-print-multi-byte*
------------------ ------------------
@ -651,4 +660,6 @@ When using ":startinsert" or ":startreplace" when already in Insert mode
(possible when using CTRL-R =), pressing Esc would directly restart Insert (possible when using CTRL-R =), pressing Esc would directly restart Insert
mode. (Peter Winters) mode. (Peter Winters)
"2daw" didn't work at end of file if the last word is a single character.
vim:tw=78:ts=8:ft=help:norl: vim:tw=78:ts=8:ft=help:norl:

View File

@ -0,0 +1,38 @@
" Polish letters keymap for cp1250
" Maintainer: HS6_06 <hs6_06@o2.pl>
" Last Changed: 2005 Jan 9
" This keymap adds the special Polish letters
" to an existing Latin keyboard.
" All chars as usual except:
" Polish:
" instead of AltGr+{acelnosxz} you ve to use "/" followed by {acelnosxz}
" short keymap name for statusline
let b:keymap_name = "polish-slash-cp1250"
scriptencoding latin1
loadkeymap
" Polish letters
/a <Char-185> " LATIN SMALL LETTER A WITH OGONEK
/c <Char-230> " LATIN SMALL LETTER C WITH ACUTE
/e <Char-234> " LATIN SMALL LETTER E WITH OGONEK
/l <Char-179> " LATIN SMALL LETTER L WITH STROKE
/n <Char-241> " LATIN SMALL LETTER N WITH ACUTE
/o <Char-243> " LATIN SMALL LETTER O WITH ACUTE
/s <Char-156> " LATIN SMALL LETTER S WITH ACUTE
/x <Char-159> " LATIN SMALL LETTER Z WITH ACUTE
/z <Char-191> " LATIN SMALL LETTER Z WITH DOT ABOVE
/A <Char-165> " LATIN CAPITAL LETTER A WITH OGONEK
/C <Char-198> " LATIN CAPITAL LETTER C WITH ACUTE
/E <Char-202> " LATIN CAPITAL LETTER E WITH OGONEK
/L <Char-163> " LATIN CAPITAL LETTER L WITH STROKE
/N <Char-209> " LATIN CAPITAL LETTER N WITH ACUTE
/O <Char-211> " LATIN CAPITAL LETTER O WITH ACUTE
/S <Char-140> " LATIN CAPITAL LETTER S WITH ACUTE
/X <Char-143> " LATIN CAPITAL LETTER Z WITH ACUTE
/Z <Char-175> " LATIN CAPITAL LETTER Z WITH DOT ABOVE

View File

@ -191,6 +191,8 @@ typedef struct forinfo_S
listvar *fi_list; /* list being used */ listvar *fi_list; /* list being used */
} forinfo; } forinfo;
/* used for map() */
static typeval amp_tv;
/* /*
* Return the name of the executed function. * Return the name of the executed function.
@ -314,6 +316,7 @@ static int eval_index __ARGS((char_u **arg, typeval *rettv, int evaluate));
static int get_option_tv __ARGS((char_u **arg, typeval *rettv, int evaluate)); static int get_option_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
static int get_string_tv __ARGS((char_u **arg, typeval *rettv, int evaluate)); static int get_string_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
static int get_lit_string_tv __ARGS((char_u **arg, typeval *rettv, int evaluate)); static int get_lit_string_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
static int get_sharp_string_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
static int get_list_tv __ARGS((char_u **arg, typeval *rettv, int evaluate)); static int get_list_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
static listvar *list_alloc __ARGS((void)); static listvar *list_alloc __ARGS((void));
static void list_unref __ARGS((listvar *l)); static void list_unref __ARGS((listvar *l));
@ -323,6 +326,7 @@ static void listitem_free __ARGS((listitem *item));
static long list_len __ARGS((listvar *l)); static long list_len __ARGS((listvar *l));
static int list_equal __ARGS((listvar *l1, listvar *l2, int ic)); static int list_equal __ARGS((listvar *l1, listvar *l2, int ic));
static int tv_equal __ARGS((typeval *tv1, typeval *tv2, int ic)); static int tv_equal __ARGS((typeval *tv1, typeval *tv2, int ic));
static int string_isa_number __ARGS((char_u *s));
static listitem *list_find __ARGS((listvar *l, long n)); static listitem *list_find __ARGS((listvar *l, long n));
static long list_idx_of_item __ARGS((listvar *l, listitem *item)); static long list_idx_of_item __ARGS((listvar *l, listitem *item));
static listitem *list_find_ext __ARGS((listvar *l, long *ip)); static listitem *list_find_ext __ARGS((listvar *l, long *ip));
@ -334,7 +338,11 @@ static int list_concat __ARGS((listvar *l1, listvar *l2, typeval *tv));
static listvar *list_copy __ARGS((listvar *orig, int deep)); static listvar *list_copy __ARGS((listvar *orig, int deep));
static void list_getrem __ARGS((listvar *l, listitem *item, listitem *item2)); static void list_getrem __ARGS((listvar *l, listitem *item, listitem *item2));
static char_u *list2string __ARGS((typeval *tv)); static char_u *list2string __ARGS((typeval *tv));
static void list_join __ARGS((garray_T *gap, listvar *l, char_u *sep, int echo));
static char_u *echo_string __ARGS((typeval *tv, char_u **tofree, char_u *numbuf));
static char_u *tv2string __ARGS((typeval *tv, char_u **tofree, char_u *numbuf)); static char_u *tv2string __ARGS((typeval *tv, char_u **tofree, char_u *numbuf));
static char_u *string_quote __ARGS((char_u *str, int function));
static int get_env_tv __ARGS((char_u **arg, typeval *rettv, int evaluate)); static int get_env_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
static int find_internal_func __ARGS((char_u *name)); static int find_internal_func __ARGS((char_u *name));
static char_u *deref_func_name __ARGS((char_u *name, int *lenp)); static char_u *deref_func_name __ARGS((char_u *name, int *lenp));
@ -372,6 +380,7 @@ static void f_diff_filler __ARGS((typeval *argvars, typeval *rettv));
static void f_diff_hlID __ARGS((typeval *argvars, typeval *rettv)); static void f_diff_hlID __ARGS((typeval *argvars, typeval *rettv));
static void f_empty __ARGS((typeval *argvars, typeval *rettv)); static void f_empty __ARGS((typeval *argvars, typeval *rettv));
static void f_escape __ARGS((typeval *argvars, typeval *rettv)); static void f_escape __ARGS((typeval *argvars, typeval *rettv));
static void f_eval __ARGS((typeval *argvars, typeval *rettv));
static void f_eventhandler __ARGS((typeval *argvars, typeval *rettv)); static void f_eventhandler __ARGS((typeval *argvars, typeval *rettv));
static void f_executable __ARGS((typeval *argvars, typeval *rettv)); static void f_executable __ARGS((typeval *argvars, typeval *rettv));
static void f_exists __ARGS((typeval *argvars, typeval *rettv)); static void f_exists __ARGS((typeval *argvars, typeval *rettv));
@ -379,6 +388,7 @@ static void f_expand __ARGS((typeval *argvars, typeval *rettv));
static void f_extend __ARGS((typeval *argvars, typeval *rettv)); static void f_extend __ARGS((typeval *argvars, typeval *rettv));
static void f_filereadable __ARGS((typeval *argvars, typeval *rettv)); static void f_filereadable __ARGS((typeval *argvars, typeval *rettv));
static void f_filewritable __ARGS((typeval *argvars, typeval *rettv)); static void f_filewritable __ARGS((typeval *argvars, typeval *rettv));
static void f_filter __ARGS((typeval *argvars, typeval *rettv));
static void f_finddir __ARGS((typeval *argvars, typeval *rettv)); static void f_finddir __ARGS((typeval *argvars, typeval *rettv));
static void f_findfile __ARGS((typeval *argvars, typeval *rettv)); static void f_findfile __ARGS((typeval *argvars, typeval *rettv));
static void f_fnamemodify __ARGS((typeval *argvars, typeval *rettv)); static void f_fnamemodify __ARGS((typeval *argvars, typeval *rettv));
@ -428,6 +438,7 @@ static void f_inputsave __ARGS((typeval *argvars, typeval *rettv));
static void f_inputsecret __ARGS((typeval *argvars, typeval *rettv)); static void f_inputsecret __ARGS((typeval *argvars, typeval *rettv));
static void f_insert __ARGS((typeval *argvars, typeval *rettv)); static void f_insert __ARGS((typeval *argvars, typeval *rettv));
static void f_isdirectory __ARGS((typeval *argvars, typeval *rettv)); static void f_isdirectory __ARGS((typeval *argvars, typeval *rettv));
static void f_join __ARGS((typeval *argvars, typeval *rettv));
static void f_last_buffer_nr __ARGS((typeval *argvars, typeval *rettv)); static void f_last_buffer_nr __ARGS((typeval *argvars, typeval *rettv));
static void f_len __ARGS((typeval *argvars, typeval *rettv)); static void f_len __ARGS((typeval *argvars, typeval *rettv));
static void f_libcall __ARGS((typeval *argvars, typeval *rettv)); static void f_libcall __ARGS((typeval *argvars, typeval *rettv));
@ -436,6 +447,7 @@ static void f_line __ARGS((typeval *argvars, typeval *rettv));
static void f_line2byte __ARGS((typeval *argvars, typeval *rettv)); static void f_line2byte __ARGS((typeval *argvars, typeval *rettv));
static void f_lispindent __ARGS((typeval *argvars, typeval *rettv)); static void f_lispindent __ARGS((typeval *argvars, typeval *rettv));
static void f_localtime __ARGS((typeval *argvars, typeval *rettv)); static void f_localtime __ARGS((typeval *argvars, typeval *rettv));
static void f_map __ARGS((typeval *argvars, typeval *rettv));
static void f_maparg __ARGS((typeval *argvars, typeval *rettv)); static void f_maparg __ARGS((typeval *argvars, typeval *rettv));
static void f_mapcheck __ARGS((typeval *argvars, typeval *rettv)); static void f_mapcheck __ARGS((typeval *argvars, typeval *rettv));
static void f_match __ARGS((typeval *argvars, typeval *rettv)); static void f_match __ARGS((typeval *argvars, typeval *rettv));
@ -468,7 +480,7 @@ static void f_setreg __ARGS((typeval *argvars, typeval *rettv));
static void f_setwinvar __ARGS((typeval *argvars, typeval *rettv)); static void f_setwinvar __ARGS((typeval *argvars, typeval *rettv));
static void f_simplify __ARGS((typeval *argvars, typeval *rettv)); static void f_simplify __ARGS((typeval *argvars, typeval *rettv));
static void f_sort __ARGS((typeval *argvars, typeval *rettv)); static void f_sort __ARGS((typeval *argvars, typeval *rettv));
static void f_str2list __ARGS((typeval *argvars, typeval *rettv)); static void f_split __ARGS((typeval *argvars, typeval *rettv));
#ifdef HAVE_STRFTIME #ifdef HAVE_STRFTIME
static void f_strftime __ARGS((typeval *argvars, typeval *rettv)); static void f_strftime __ARGS((typeval *argvars, typeval *rettv));
#endif #endif
@ -517,6 +529,7 @@ static long get_tv_number __ARGS((typeval *varp));
static linenr_T get_tv_lnum __ARGS((typeval *argvars)); static linenr_T get_tv_lnum __ARGS((typeval *argvars));
static char_u *get_tv_string __ARGS((typeval *varp)); static char_u *get_tv_string __ARGS((typeval *varp));
static char_u *get_tv_string_buf __ARGS((typeval *varp, char_u *buf)); static char_u *get_tv_string_buf __ARGS((typeval *varp, char_u *buf));
static int get_amp_tv __ARGS((typeval *rettv));
static VAR find_var __ARGS((char_u *name, int writing)); static VAR find_var __ARGS((char_u *name, int writing));
static VAR find_var_in_ga __ARGS((garray_T *gap, char_u *varname)); static VAR find_var_in_ga __ARGS((garray_T *gap, char_u *varname));
static garray_T *find_var_ga __ARGS((char_u *name, char_u **varname)); static garray_T *find_var_ga __ARGS((char_u *name, char_u **varname));
@ -824,7 +837,7 @@ eval_to_number(expr)
{ {
typeval rettv; typeval rettv;
int retval; int retval;
char_u *p = expr; char_u *p = skipwhite(expr);
++emsg_off; ++emsg_off;
@ -1995,6 +2008,13 @@ set_context_for_expression(xp, arg, cmdidx)
/* skip */ ; /* skip */ ;
xp->xp_context = EXPAND_NOTHING; xp->xp_context = EXPAND_NOTHING;
} }
else if (c == '#') /* sharp string */
{
/* Trick: ## is like stopping and starting a sharp string. */
while ((c = *++xp->xp_pattern) != NUL && c != '#')
/* skip */ ;
xp->xp_context = EXPAND_NOTHING;
}
else if (c == '|') else if (c == '|')
{ {
if (xp->xp_pattern[1] == '|') if (xp->xp_pattern[1] == '|')
@ -3112,6 +3132,12 @@ eval7(arg, rettv, evaluate)
case '\'': ret = get_lit_string_tv(arg, rettv, evaluate); case '\'': ret = get_lit_string_tv(arg, rettv, evaluate);
break; break;
/*
* Sharp string constant: #str##ing#.
*/
case '#': ret = get_sharp_string_tv(arg, rettv, evaluate);
break;
/* /*
* List: [expr, expr] * List: [expr, expr]
*/ */
@ -3119,9 +3145,16 @@ eval7(arg, rettv, evaluate)
break; break;
/* /*
* Option value: &name * Option value: &name or map() item "&".
*/ */
case '&': ret = get_option_tv(arg, rettv, evaluate); case '&': if (!ASCII_ISALPHA(*(*arg + 1)))
{
*arg = skipwhite(*arg + 1);
if (evaluate)
ret = get_amp_tv(rettv);
}
else
ret = get_option_tv(arg, rettv, evaluate);
break; break;
/* /*
@ -3509,7 +3542,7 @@ get_string_tv(arg, rettv, evaluate)
/* /*
* Find the end of the string, skipping backslashed characters. * Find the end of the string, skipping backslashed characters.
*/ */
for (p = *arg + 1; *p && *p != '"'; mb_ptr_adv(p)) for (p = *arg + 1; *p != NUL && *p != '"'; mb_ptr_adv(p))
{ {
if (*p == '\\' && p[1] != NUL) if (*p == '\\' && p[1] != NUL)
{ {
@ -3543,7 +3576,7 @@ get_string_tv(arg, rettv, evaluate)
return FAIL; return FAIL;
i = 0; i = 0;
for (p = *arg + 1; *p && *p != '"'; ++p) for (p = *arg + 1; *p != NUL && *p != '"'; ++p)
{ {
if (*p == '\\') if (*p == '\\')
{ {
@ -3688,6 +3721,86 @@ get_lit_string_tv(arg, rettv, evaluate)
return OK; return OK;
} }
/*
* Allocate a variable for a #string# constant.
* Return OK or FAIL.
*/
static int
get_sharp_string_tv(arg, rettv, evaluate)
char_u **arg;
typeval *rettv;
int evaluate;
{
char_u *p;
char_u *str;
int i;
int reduce = 0;
/*
* Find the end of the string, skipping ##.
*/
for (p = *arg + 1; *p != NUL; mb_ptr_adv(p))
{
if (*p == '#')
{
if (p[1] != '#')
break;
++reduce;
++p;
}
}
if (*p != '#')
{
EMSG2(_("E999: Missing #: %s"), *arg);
return FAIL;
}
/* If only parsing, set *arg and return here */
if (!evaluate)
{
*arg = p + 1;
return OK;
}
/*
* Copy the string into allocated memory, handling ## to # reduction.
*/
str = alloc((unsigned)((p - *arg) - reduce));
if (str == NULL)
return FAIL;
i = 0;
for (p = *arg + 1; *p != NUL; ++p)
{
if (*p == '#')
{
if (p[1] != '#')
break;
++p;
}
str[i++] = *p;
#ifdef FEAT_MBYTE
/* For a multi-byte character copy the bytes after the first one. */
if (has_mbyte)
{
int l = (*mb_ptr2len_check)(p);
while (--l > 0)
str[i++] = *++p;
}
#endif
}
str[i] = NUL;
*arg = p + 1;
rettv->v_type = VAR_STRING;
rettv->vval.v_string = str;
return OK;
}
/* /*
* Allocate a variable for a List and fill it from "*arg". * Allocate a variable for a List and fill it from "*arg".
* Return OK or FAIL. * Return OK or FAIL.
@ -3879,6 +3992,13 @@ tv_equal(tv1, tv2, ic)
} }
else if (tv1->v_type == VAR_NUMBER || tv2->v_type == VAR_NUMBER) else if (tv1->v_type == VAR_NUMBER || tv2->v_type == VAR_NUMBER)
{ {
/* "4" is equal to 4. But don't consider 'a' and zero to be equal.
* Don't consider "4x" to be equal to 4. */
if ((tv1->v_type == VAR_STRING
&& !string_isa_number(tv1->vval.v_string))
|| (tv2->v_type == VAR_STRING
&& !string_isa_number(tv2->vval.v_string)))
return FALSE;
if (get_tv_number(tv1) != get_tv_number(tv2)) if (get_tv_number(tv1) != get_tv_number(tv2))
return FALSE; return FALSE;
} }
@ -3891,6 +4011,19 @@ tv_equal(tv1, tv2, ic)
return TRUE; return TRUE;
} }
/*
* Return TRUE if "tv" is a number without other non-white characters.
*/
static int
string_isa_number(s)
char_u *s;
{
int len;
vim_str2nr(s, NULL, &len, TRUE, TRUE, NULL, NULL);
return len > 0 && *skipwhite(s + len) == NUL;
}
/* /*
* Locate item with index "n" in list "l" and return it. * Locate item with index "n" in list "l" and return it.
* A negative index is counted from the end; -1 is the last item. * A negative index is counted from the end; -1 is the last item.
@ -4187,43 +4320,60 @@ list2string(tv)
typeval *tv; typeval *tv;
{ {
garray_T ga; garray_T ga;
listitem *item;
int first = TRUE;
char_u *tofree;
char_u *s;
char_u numbuf[NUMBUFLEN];
if (tv->vval.v_list == NULL) if (tv->vval.v_list == NULL)
return NULL; return NULL;
ga_init2(&ga, (int)sizeof(char), 80); ga_init2(&ga, (int)sizeof(char), 80);
ga_append(&ga, '['); ga_append(&ga, '[');
list_join(&ga, tv->vval.v_list, (char_u *)", ", FALSE);
for (item = tv->vval.v_list->lv_first; item != NULL; item = item->li_next)
{
if (first)
first = FALSE;
else
ga_concat(&ga, (char_u *)", ");
s = tv2string(&item->li_tv, &tofree, numbuf);
if (s != NULL)
ga_concat(&ga, s);
vim_free(tofree);
}
ga_append(&ga, ']'); ga_append(&ga, ']');
ga_append(&ga, NUL); ga_append(&ga, NUL);
return (char_u *)ga.ga_data; return (char_u *)ga.ga_data;
} }
/*
* Join list "l" into a string in "*gap", using separator "sep".
* When "echo" is TRUE use String as echoed, otherwise as inside a List.
*/
static void
list_join(gap, l, sep, echo)
garray_T *gap;
listvar *l;
char_u *sep;
int echo;
{
int first = TRUE;
char_u *tofree;
char_u numbuf[NUMBUFLEN];
listitem *item;
char_u *s;
for (item = l->lv_first; item != NULL; item = item->li_next)
{
if (first)
first = FALSE;
else
ga_concat(gap, sep);
if (echo)
s = echo_string(&item->li_tv, &tofree, numbuf);
else
s = tv2string(&item->li_tv, &tofree, numbuf);
if (s != NULL)
ga_concat(gap, s);
vim_free(tofree);
}
}
/* /*
* Return a string with the string representation of a variable. * Return a string with the string representation of a variable.
* If the memory is allocated "tofree" is set to it, otherwise NULL. * If the memory is allocated "tofree" is set to it, otherwise NULL.
* "numbuf" is used for a number. * "numbuf" is used for a number.
* Does not put quotes around strings, as ":echo" displays values.
* May return NULL; * May return NULL;
*/ */
static char_u * static char_u *
tv2string(tv, tofree, numbuf) echo_string(tv, tofree, numbuf)
typeval *tv; typeval *tv;
char_u **tofree; char_u **tofree;
char_u *numbuf; char_u *numbuf;
@ -4239,6 +4389,39 @@ tv2string(tv, tofree, numbuf)
case VAR_STRING: case VAR_STRING:
case VAR_NUMBER: case VAR_NUMBER:
break; break;
default:
EMSG2(_(e_intern2), "echo_string()");
}
*tofree = NULL;
return get_tv_string_buf(tv, numbuf);
}
/*
* Return a string with the string representation of a variable.
* If the memory is allocated "tofree" is set to it, otherwise NULL.
* "numbuf" is used for a number.
* Puts quotes around strings, so that they can be parsed back by eval().
* May return NULL;
*/
static char_u *
tv2string(tv, tofree, numbuf)
typeval *tv;
char_u **tofree;
char_u *numbuf;
{
switch (tv->v_type)
{
case VAR_NUMBER:
break;
case VAR_FUNC:
*tofree = string_quote(tv->vval.v_string, TRUE);
return *tofree;
case VAR_STRING:
*tofree = string_quote(tv->vval.v_string, FALSE);
return *tofree;
case VAR_LIST:
*tofree = list2string(tv);
return *tofree;
default: default:
EMSG2(_(e_intern2), "tv2string()"); EMSG2(_(e_intern2), "tv2string()");
} }
@ -4246,6 +4429,55 @@ tv2string(tv, tofree, numbuf)
return get_tv_string_buf(tv, numbuf); return get_tv_string_buf(tv, numbuf);
} }
/*
* Return a string in # quotes, doubling # characters.
* If "function" is TRUE make it function(#string#).
*/
static char_u *
string_quote(str, function)
char_u *str;
int function;
{
unsigned len = function ? 13 : 3;
char_u *p, *r, *s;
for (p = str; *p != NUL; mb_ptr_adv(p))
if (*p == '#')
++len;
s = r = alloc(len);
if (r != NULL)
{
if (function)
{
STRCPY(r, "function(#");
r += 10;
}
else
*r++ = '#';
for (p = str; *p != NUL; ++p)
{
if (*p == '#')
*r++ = '#';
*r++ = *p;
#ifdef FEAT_MBYTE
/* For a multi-byte character copy the bytes after the first one. */
if (has_mbyte)
{
int l = (*mb_ptr2len_check)(p);
while (--l > 0)
*r++ = *++p;
}
#endif
}
*r++ = '#';
if (function)
*r++ = ')';
*r++ = NUL;
}
return s;
}
/* /*
* Get the value of an environment variable. * Get the value of an environment variable.
* "arg" is pointing to the '$'. It is advanced to after the name. * "arg" is pointing to the '$'. It is advanced to after the name.
@ -4332,7 +4564,7 @@ static struct fst
{"col", 1, 1, f_col}, {"col", 1, 1, f_col},
{"confirm", 1, 4, f_confirm}, {"confirm", 1, 4, f_confirm},
{"copy", 1, 1, f_copy}, {"copy", 1, 1, f_copy},
{"count", 2, 3, f_count}, {"count", 2, 4, f_count},
{"cscope_connection",0,3, f_cscope_connection}, {"cscope_connection",0,3, f_cscope_connection},
{"cursor", 2, 2, f_cursor}, {"cursor", 2, 2, f_cursor},
{"deepcopy", 1, 1, f_deepcopy}, {"deepcopy", 1, 1, f_deepcopy},
@ -4342,6 +4574,7 @@ static struct fst
{"diff_hlID", 2, 2, f_diff_hlID}, {"diff_hlID", 2, 2, f_diff_hlID},
{"empty", 1, 1, f_empty}, {"empty", 1, 1, f_empty},
{"escape", 2, 2, f_escape}, {"escape", 2, 2, f_escape},
{"eval", 1, 1, f_eval},
{"eventhandler", 0, 0, f_eventhandler}, {"eventhandler", 0, 0, f_eventhandler},
{"executable", 1, 1, f_executable}, {"executable", 1, 1, f_executable},
{"exists", 1, 1, f_exists}, {"exists", 1, 1, f_exists},
@ -4350,6 +4583,7 @@ static struct fst
{"file_readable", 1, 1, f_filereadable}, /* obsolete */ {"file_readable", 1, 1, f_filereadable}, /* obsolete */
{"filereadable", 1, 1, f_filereadable}, {"filereadable", 1, 1, f_filereadable},
{"filewritable", 1, 1, f_filewritable}, {"filewritable", 1, 1, f_filewritable},
{"filter", 2, 2, f_filter},
{"finddir", 1, 3, f_finddir}, {"finddir", 1, 3, f_finddir},
{"findfile", 1, 3, f_findfile}, {"findfile", 1, 3, f_findfile},
{"fnamemodify", 2, 2, f_fnamemodify}, {"fnamemodify", 2, 2, f_fnamemodify},
@ -4393,7 +4627,7 @@ static struct fst
{"hostname", 0, 0, f_hostname}, {"hostname", 0, 0, f_hostname},
{"iconv", 3, 3, f_iconv}, {"iconv", 3, 3, f_iconv},
{"indent", 1, 1, f_indent}, {"indent", 1, 1, f_indent},
{"index", 2, 3, f_index}, {"index", 2, 4, f_index},
{"input", 1, 2, f_input}, {"input", 1, 2, f_input},
{"inputdialog", 1, 3, f_inputdialog}, {"inputdialog", 1, 3, f_inputdialog},
{"inputrestore", 0, 0, f_inputrestore}, {"inputrestore", 0, 0, f_inputrestore},
@ -4401,6 +4635,7 @@ static struct fst
{"inputsecret", 1, 2, f_inputsecret}, {"inputsecret", 1, 2, f_inputsecret},
{"insert", 2, 3, f_insert}, {"insert", 2, 3, f_insert},
{"isdirectory", 1, 1, f_isdirectory}, {"isdirectory", 1, 1, f_isdirectory},
{"join", 1, 2, f_join},
{"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */ {"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */
{"len", 1, 1, f_len}, {"len", 1, 1, f_len},
{"libcall", 3, 3, f_libcall}, {"libcall", 3, 3, f_libcall},
@ -4409,6 +4644,7 @@ static struct fst
{"line2byte", 1, 1, f_line2byte}, {"line2byte", 1, 1, f_line2byte},
{"lispindent", 1, 1, f_lispindent}, {"lispindent", 1, 1, f_lispindent},
{"localtime", 0, 0, f_localtime}, {"localtime", 0, 0, f_localtime},
{"map", 2, 2, f_map},
{"maparg", 1, 2, f_maparg}, {"maparg", 1, 2, f_maparg},
{"mapcheck", 1, 2, f_mapcheck}, {"mapcheck", 1, 2, f_mapcheck},
{"match", 2, 4, f_match}, {"match", 2, 4, f_match},
@ -4441,7 +4677,7 @@ static struct fst
{"setwinvar", 3, 3, f_setwinvar}, {"setwinvar", 3, 3, f_setwinvar},
{"simplify", 1, 1, f_simplify}, {"simplify", 1, 1, f_simplify},
{"sort", 1, 2, f_sort}, {"sort", 1, 2, f_sort},
{"str2list", 1, 2, f_str2list}, {"split", 1, 2, f_split},
#ifdef HAVE_STRFTIME #ifdef HAVE_STRFTIME
{"strftime", 1, 2, f_strftime}, {"strftime", 1, 2, f_strftime},
#endif #endif
@ -5477,11 +5713,18 @@ f_count(argvars, rettv)
EMSG(_(e_listreq)); EMSG(_(e_listreq));
else if (argvars[0].vval.v_list != NULL) else if (argvars[0].vval.v_list != NULL)
{ {
li = argvars[0].vval.v_list->lv_first;
if (argvars[2].v_type != VAR_UNKNOWN) if (argvars[2].v_type != VAR_UNKNOWN)
ic = get_tv_number(&argvars[2]); {
for (n = get_tv_number(&argvars[2]); n > 0 && li != NULL;
for (li = argvars[0].vval.v_list->lv_first; li != NULL;
li = li->li_next) li = li->li_next)
--n;
if (argvars[3].v_type != VAR_UNKNOWN)
ic = get_tv_number(&argvars[3]);
}
n = 0;
for ( ; li != NULL; li = li->li_next)
if (tv_equal(&li->li_tv, &argvars[1], ic)) if (tv_equal(&li->li_tv, &argvars[1], ic))
++n; ++n;
} }
@ -5722,6 +5965,26 @@ f_escape(argvars, rettv)
rettv->v_type = VAR_STRING; rettv->v_type = VAR_STRING;
} }
/*
* "eval()" function
*/
/*ARGSUSED*/
static void
f_eval(argvars, rettv)
typeval *argvars;
typeval *rettv;
{
char_u *s;
s = get_tv_string(&argvars[0]);
s = skipwhite(s);
if (eval1(&s, rettv, TRUE) == FAIL)
rettv->vval.v_number = 0;
else if (*s != NUL)
EMSG(_(e_trailing));
}
/* /*
* "eventhandler()" function * "eventhandler()" function
*/ */
@ -6009,6 +6272,77 @@ findfilendir(argvars, rettv, dir)
rettv->v_type = VAR_STRING; rettv->v_type = VAR_STRING;
} }
static void filter_map __ARGS((typeval *argvars, typeval *rettv, int map));
/*
* Implementation of map() and filter().
*/
static void
filter_map(argvars, rettv, map)
typeval *argvars;
typeval *rettv;
int map;
{
char_u buf[NUMBUFLEN];
char_u *expr, *s;
listitem *li, *nli;
listvar *l;
rettv->vval.v_number = 0;
if (argvars[0].v_type != VAR_LIST)
EMSG(_(e_listreq));
else if ((l = argvars[0].vval.v_list) != NULL)
{
expr = skipwhite(get_tv_string_buf(&argvars[1], buf));
for (li = l->lv_first; li != NULL; li = nli)
{
copy_tv(&li->li_tv, &amp_tv);
s = expr;
if (eval1(&s, rettv, TRUE) == FAIL)
break;
if (*s != NUL) /* check for trailing chars after expr */
{
EMSG2(_(e_invexpr2), s);
break;
}
nli = li->li_next;
if (map)
{
/* map(): replace the list item value */
clear_tv(&li->li_tv);
li->li_tv = *rettv;
}
else
{
/* filter(): when expr is zero remove the item */
if (get_tv_number(rettv) == 0)
{
list_getrem(l, li, li);
clear_tv(&li->li_tv);
}
clear_tv(rettv);
}
clear_tv(&amp_tv);
}
clear_tv(&amp_tv);
amp_tv.v_type = VAR_UNKNOWN;
copy_tv(&argvars[0], rettv);
}
}
/*
* "filter()" function
*/
static void
f_filter(argvars, rettv)
typeval *argvars;
typeval *rettv;
{
filter_map(argvars, rettv, FALSE);
}
/* /*
* "finddir({fname}[, {path}[, {count}]])" function * "finddir({fname}[, {path}[, {count}]])" function
*/ */
@ -6264,7 +6598,7 @@ f_function(argvars, rettv)
char_u *s; char_u *s;
s = get_tv_string(&argvars[0]); s = get_tv_string(&argvars[0]);
if (s == NULL || *s == NUL || isdigit(*s)) if (s == NULL || *s == NUL || VIM_ISDIGIT(*s))
EMSG2(_(e_invarg2), s); EMSG2(_(e_invarg2), s);
else if (!function_exists(s)) else if (!function_exists(s))
EMSG2(_("E700: Unknown function: %s"), s); EMSG2(_("E700: Unknown function: %s"), s);
@ -7636,6 +7970,7 @@ f_index(argvars, rettv)
listvar *l; listvar *l;
listitem *item; listitem *item;
long idx = 0; long idx = 0;
long min_idx = 0;
int ic = FALSE; int ic = FALSE;
rettv->vval.v_number = -1; rettv->vval.v_number = -1;
@ -7648,10 +7983,14 @@ f_index(argvars, rettv)
if (l != NULL) if (l != NULL)
{ {
if (argvars[2].v_type != VAR_UNKNOWN) if (argvars[2].v_type != VAR_UNKNOWN)
ic = get_tv_number(&argvars[2]); {
min_idx = get_tv_number(&argvars[2]);
if (argvars[3].v_type != VAR_UNKNOWN)
ic = get_tv_number(&argvars[3]);
}
for (item = l->lv_first; item != NULL; item = item->li_next, ++idx) for (item = l->lv_first; item != NULL; item = item->li_next, ++idx)
if (tv_equal(&item->li_tv, &argvars[1], ic)) if (idx >= min_idx && tv_equal(&item->li_tv, &argvars[1], ic))
{ {
rettv->vval.v_number = idx; rettv->vval.v_number = idx;
break; break;
@ -7869,6 +8208,38 @@ f_isdirectory(argvars, rettv)
rettv->vval.v_number = mch_isdir(get_tv_string(&argvars[0])); rettv->vval.v_number = mch_isdir(get_tv_string(&argvars[0]));
} }
/*
* "join()" function
*/
static void
f_join(argvars, rettv)
typeval *argvars;
typeval *rettv;
{
garray_T ga;
char_u *sep;
rettv->vval.v_number = 0;
if (argvars[0].v_type != VAR_LIST)
{
EMSG(_(e_listreq));
return;
}
if (argvars[0].vval.v_list == NULL)
return;
if (argvars[1].v_type == VAR_UNKNOWN)
sep = (char_u *)" ";
else
sep = get_tv_string(&argvars[1]);
ga_init2(&ga, (int)sizeof(char), 80);
list_join(&ga, argvars[0].vval.v_list, sep, TRUE);
ga_append(&ga, NUL);
rettv->v_type = VAR_STRING;
rettv->vval.v_string = (char_u *)ga.ga_data;
}
/* /*
* "last_buffer_nr()" function. * "last_buffer_nr()" function.
*/ */
@ -8106,6 +8477,17 @@ get_maparg(argvars, rettv, exact)
} }
} }
/*
* "map()" function
*/
static void
f_map(argvars, rettv)
typeval *argvars;
typeval *rettv;
{
filter_map(argvars, rettv, TRUE);
}
/* /*
* "maparg()" function * "maparg()" function
*/ */
@ -8136,23 +8518,25 @@ find_some_match(argvars, rettv, type)
typeval *rettv; typeval *rettv;
int type; int type;
{ {
char_u *str; char_u *str = NULL;
char_u *expr; char_u *expr = NULL;
char_u *pat; char_u *pat;
regmatch_T regmatch; regmatch_T regmatch;
char_u patbuf[NUMBUFLEN]; char_u patbuf[NUMBUFLEN];
char_u strbuf[NUMBUFLEN];
char_u *save_cpo; char_u *save_cpo;
long start = 0; long start = 0;
long nth = 1; long nth = 1;
int match; int match;
listvar *l = NULL;
listitem *li = NULL;
long idx = 0;
char_u *tofree;
/* Make 'cpoptions' empty, the 'l' flag should not be used here. */ /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
save_cpo = p_cpo; save_cpo = p_cpo;
p_cpo = (char_u *)""; p_cpo = (char_u *)"";
expr = str = get_tv_string(&argvars[0]);
pat = get_tv_string_buf(&argvars[1], patbuf);
if (type == 2) if (type == 2)
{ {
rettv->v_type = VAR_STRING; rettv->v_type = VAR_STRING;
@ -8161,14 +8545,44 @@ find_some_match(argvars, rettv, type)
else else
rettv->vval.v_number = -1; rettv->vval.v_number = -1;
if (argvars[0].v_type == VAR_LIST)
{
if ((l = argvars[0].vval.v_list) == NULL)
goto theend;
li = l->lv_first;
}
else
expr = str = get_tv_string(&argvars[0]);
pat = get_tv_string_buf(&argvars[1], patbuf);
if (argvars[2].v_type != VAR_UNKNOWN) if (argvars[2].v_type != VAR_UNKNOWN)
{ {
start = get_tv_number(&argvars[2]); start = get_tv_number(&argvars[2]);
if (start < 0) if (l != NULL)
start = 0; {
if (start > (long)STRLEN(str)) li = list_find(l, start);
goto theend; if (li == NULL)
str += start; goto theend;
if (start < 0)
{
listitem *ni;
/* Need to compute the index. */
for (ni = li; ni->li_prev != NULL; ni = ni->li_prev)
++idx;
}
else
idx = start;
}
else
{
if (start < 0)
start = 0;
if (start > (long)STRLEN(str))
goto theend;
str += start;
}
if (argvars[3].v_type != VAR_UNKNOWN) if (argvars[3].v_type != VAR_UNKNOWN)
nth = get_tv_number(&argvars[3]); nth = get_tv_number(&argvars[3]);
@ -8181,22 +8595,53 @@ find_some_match(argvars, rettv, type)
while (1) while (1)
{ {
if (l != NULL)
{
if (li == NULL)
{
match = FALSE;
break;
}
str = echo_string(&li->li_tv, &tofree, strbuf);
}
match = vim_regexec_nl(&regmatch, str, (colnr_T)0); match = vim_regexec_nl(&regmatch, str, (colnr_T)0);
if (!match || --nth <= 0)
if (l != NULL)
vim_free(tofree);
if (match && --nth <= 0)
break; break;
if (l == NULL && !match)
break;
/* Advance to just after the match. */ /* Advance to just after the match. */
if (l != NULL)
{
li = li->li_next;
++idx;
}
else
{
#ifdef FEAT_MBYTE #ifdef FEAT_MBYTE
str = regmatch.startp[0] + mb_ptr2len_check(regmatch.startp[0]); str = regmatch.startp[0] + mb_ptr2len_check(regmatch.startp[0]);
#else #else
str = regmatch.startp[0] + 1; str = regmatch.startp[0] + 1;
#endif #endif
}
} }
if (match) if (match)
{ {
if (type == 2) if (type == 2)
rettv->vval.v_string = vim_strnsave(regmatch.startp[0], {
if (l != NULL)
copy_tv(&li->li_tv, rettv);
else
rettv->vval.v_string = vim_strnsave(regmatch.startp[0],
(int)(regmatch.endp[0] - regmatch.startp[0])); (int)(regmatch.endp[0] - regmatch.startp[0]));
}
else if (l != NULL)
rettv->vval.v_number = idx;
else else
{ {
if (type != 0) if (type != 0)
@ -9689,7 +10134,7 @@ f_sort(argvars, rettv)
} }
static void static void
f_str2list(argvars, rettv) f_split(argvars, rettv)
typeval *argvars; typeval *argvars;
typeval *rettv; typeval *rettv;
{ {
@ -11313,13 +11758,16 @@ get_tv_number(varp)
n = (long)(varp->vval.v_number); n = (long)(varp->vval.v_number);
break; break;
case VAR_FUNC: case VAR_FUNC:
EMSG(_("E703: Using function reference as a number")); EMSG(_("E703: Using a Funcref as a number"));
break; break;
case VAR_STRING: case VAR_STRING:
if (varp->vval.v_string != NULL) if (varp->vval.v_string != NULL)
vim_str2nr(varp->vval.v_string, NULL, NULL, vim_str2nr(varp->vval.v_string, NULL, NULL,
TRUE, TRUE, &n, NULL); TRUE, TRUE, &n, NULL);
break; break;
case VAR_LIST:
EMSG(_("E703: Using a List as a number"));
break;
default: default:
break; break;
} }
@ -11391,6 +11839,22 @@ get_tv_string_buf(varp, buf)
return (char_u *)""; return (char_u *)"";
} }
/*
* Get value for "&", as used in map() and filter().
*/
static int
get_amp_tv(rettv)
typeval *rettv;
{
if (amp_tv.v_type == VAR_UNKNOWN)
{
EMSG(_("E712: Using & outside of map() or filter()"));
return FAIL;
}
copy_tv(&amp_tv, rettv);
return OK;
}
/* /*
* Find variable "name" in the list of variables. * Find variable "name" in the list of variables.
* Return a pointer to it if found, NULL if not found. * Return a pointer to it if found, NULL if not found.
@ -11573,7 +12037,7 @@ list_one_var(v, prefix)
char_u *s; char_u *s;
char_u numbuf[NUMBUFLEN]; char_u numbuf[NUMBUFLEN];
s = tv2string(&v->tv, &tofree, numbuf); s = echo_string(&v->tv, &tofree, numbuf);
list_one_var_a(prefix, v->v_name, v->tv.v_type, list_one_var_a(prefix, v->v_name, v->tv.v_type,
s == NULL ? (char_u *)"" : s); s == NULL ? (char_u *)"" : s);
vim_free(tofree); vim_free(tofree);
@ -11826,7 +12290,7 @@ ex_echo(eap)
} }
else if (eap->cmdidx == CMD_echo) else if (eap->cmdidx == CMD_echo)
msg_puts_attr((char_u *)" ", echo_attr); msg_puts_attr((char_u *)" ", echo_attr);
for (p = tv2string(&rettv, &tofree, numbuf); for (p = echo_string(&rettv, &tofree, numbuf);
*p != NUL && !got_int; ++p) *p != NUL && !got_int; ++p)
if (*p == '\n' || *p == '\r' || *p == TAB) if (*p == '\n' || *p == '\r' || *p == TAB)
{ {
@ -12249,25 +12713,28 @@ ex_function(eap)
for (p = theline; vim_iswhite(*p) || *p == ':'; ++p) for (p = theline; vim_iswhite(*p) || *p == ':'; ++p)
; ;
/* Check for "endfunction" (should be more strict...). */ /* Check for "endfunction". */
if (STRNCMP(p, "endf", 4) == 0 && nesting-- == 0) if (checkforcmd(&p, "endfunction", 4) && nesting-- == 0)
{ {
vim_free(theline); vim_free(theline);
break; break;
} }
/* Increase indent inside "if", "while", and "try", decrease /* Increase indent inside "if", "while", "for" and "try", decrease
* at "end". */ * at "end". */
if (indent > 2 && STRNCMP(p, "end", 3) == 0) if (indent > 2 && STRNCMP(p, "end", 3) == 0)
indent -= 2; indent -= 2;
else if (STRNCMP(p, "if", 2) == 0 || STRNCMP(p, "wh", 2) == 0 else if (STRNCMP(p, "if", 2) == 0
|| STRNCMP(p, "wh", 2) == 0
|| STRNCMP(p, "for", 3) == 0
|| STRNCMP(p, "try", 3) == 0) || STRNCMP(p, "try", 3) == 0)
indent += 2; indent += 2;
/* Check for defining a function inside this function. */ /* Check for defining a function inside this function. */
if (STRNCMP(p, "fu", 2) == 0) if (checkforcmd(&p, "function", 2))
{ {
p = skipwhite(skiptowhite(p)); if (*p == '!')
p = skipwhite(p + 1);
p += eval_fname_script(p); p += eval_fname_script(p);
if (ASCII_ISALPHA(*p)) if (ASCII_ISALPHA(*p))
{ {
@ -13042,7 +13509,7 @@ get_return_cmd(rettv)
if (rettv == NULL) if (rettv == NULL)
s = (char_u *)""; s = (char_u *)"";
else else
s = tv2string((typeval *)rettv, &tofree, numbuf); s = echo_string((typeval *)rettv, &tofree, numbuf);
STRCPY(IObuff, ":return "); STRCPY(IObuff, ":return ");
STRNCPY(IObuff + 8, s, IOSIZE - 8); STRNCPY(IObuff + 8, s, IOSIZE - 8);
@ -13231,7 +13698,8 @@ write_viminfo_varlist(fp)
default: continue; default: continue;
} }
fprintf(fp, "!%s\t%s\t", this_var->v_name, s); fprintf(fp, "!%s\t%s\t", this_var->v_name, s);
viminfo_writestring(fp, tv2string(&this_var->tv, &tofree, numbuf)); viminfo_writestring(fp, echo_string(&this_var->tv,
&tofree, numbuf));
vim_free(tofree); vim_free(tofree);
} }
} }