1
0
forked from aniani/vim

updated for version 7.0031

This commit is contained in:
Bram Moolenaar
2005-01-05 22:16:17 +00:00
parent 06fb435a1c
commit 1280586e4b
11 changed files with 290 additions and 154 deletions

View File

@@ -1,4 +1,4 @@
*eval.txt* For Vim version 7.0aa. Last change: 2005 Jan 04 *eval.txt* For Vim version 7.0aa. Last change: 2005 Jan 05
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@@ -2774,6 +2774,7 @@ string({expr}) Return {expr} converted to a String.
String identical String identical
Number decimal representation Number decimal representation
Funcref name of the function Funcref name of the function
List "[item, item]" form
*strlen()* *strlen()*
strlen({expr}) The result is a Number, which is the length of the String strlen({expr}) The result is a Number, which is the length of the String
@@ -3619,29 +3620,69 @@ This would call the function "my_func_whizz(parameter)".
as long as {expr1} evaluates to non-zero. as long as {expr1} evaluates to non-zero.
When an error is detected from a command inside the When an error is detected from a command inside the
loop, execution continues after the "endwhile". loop, execution continues after the "endwhile".
Example: >
:let lnum = 1
:while lnum <= line("$")
:call FixLine(lnum)
:let lnum = lnum + 1
:endwhile
<
NOTE: The ":append" and ":insert" commands don't work NOTE: The ":append" and ":insert" commands don't work
properly inside a ":while" loop. properly inside a :while" and ":for" loop.
:for {var} in {list} *:for*
:endfo[r] *:endfo* *:endfor*
Repeat the commands between ":for" and ":endfor" for
each item in {list}. {var} is set to the value of the
item.
When an error is detected from a command inside the
loop, execution continues after the "endfor".
A copy of {list} is made, so that it cannot change
while executing the commands. Example (an inefficient
way to make a list empty): >
:for a in mylist
:call remove(mylist, 0)
:endfor
< Note that the type of each list item should be
identical to avoid errors for the type of {var}
changing. Unlet the variable at the end of the loop
to allow multiple item types.
:for {var} in {string}
:endfo[r] Like ":for" above, but use each character in {string}
as a list item.
Composing characters are used as separate characters.
A Number is first converted to a String.
:for [{var1}, {var2}, ...] in {listlist}
:endfo[r]
Like ":for" above, but each item in {listlist} must be
a list, of which each item is assigned to {var1},
{var2}, etc. Example: >
:for [lnum, col] in [[1, 3], [2, 5], [3, 8]]
:echo getline(lnum)[col]
:endfor
<
*:continue* *:con* *E586* *:continue* *:con* *E586*
:con[tinue] When used inside a ":while", jumps back to the :con[tinue] When used inside a ":while" or ":for" loop, jumps back
":while". If it is used after a |:try| inside the to the start of the loop.
":while" but before the matching |:finally| (if If it is used after a |:try| inside the loop but
present), the commands following the ":finally" up to before the matching |:finally| (if present), the
the matching |:endtry| are executed first. This commands following the ":finally" up to the matching
process applies to all nested ":try"s inside the |:endtry| are executed first. This process applies to
":while". The outermost ":endtry" then jumps back to all nested ":try"s inside the loop. The outermost
the ":while". ":endtry" then jumps back to the start of the loop.
*:break* *:brea* *E587* *:break* *:brea* *E587*
:brea[k] When used inside a ":while", skips to the command :brea[k] When used inside a ":while" or ":for" loop, skips to
after the matching ":endwhile". If it is used after the command after the matching ":endwhile" or
a |:try| inside the ":while" but before the matching ":endfor".
|:finally| (if present), the commands following the If it is used after a |:try| inside the loop but
":finally" up to the matching |:endtry| are executed before the matching |:finally| (if present), the
first. This process applies to all nested ":try"s commands following the ":finally" up to the matching
inside the ":while". The outermost ":endtry" then |:endtry| are executed first. This process applies to
jumps to the command after the ":endwhile". all nested ":try"s inside the loop. The outermost
":endtry" then jumps to the command after the loop.
:try *:try* *:endt* *:endtry* *E600* *E601* *E602* :try *:try* *:endt* *:endtry* *E600* *E601* *E602*
:endt[ry] Change the error handling for the commands between :endt[ry] Change the error handling for the commands between

View File

@@ -1,4 +1,4 @@
*options.txt* For Vim version 7.0aa. Last change: 2004 Dec 24 *options.txt* For Vim version 7.0aa. Last change: 2005 Jan 05
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@@ -5019,7 +5019,8 @@ A jump table for the options with a short description can be found at |Q_op|.
folds manually created folds, opened/closed folds and local folds manually created folds, opened/closed folds and local
fold options fold options
globals global variables that start with an uppercase letter globals global variables that start with an uppercase letter
and contain at least one lowercase letter. and contain at least one lowercase letter. Only
String and Number types are stored.
help the help window help the help window
localoptions options and mappings local to a window or buffer (not localoptions options and mappings local to a window or buffer (not
global values for local options) global values for local options)
@@ -6410,7 +6411,8 @@ A jump table for the options with a short description can be found at |Q_op|.
! When included, save and restore global variables that start ! When included, save and restore global variables that start
with an uppercase letter, and don't contain a lowercase with an uppercase letter, and don't contain a lowercase
letter. Thus "KEEPTHIS and "K_L_M" are stored, but "KeepThis" letter. Thus "KEEPTHIS and "K_L_M" are stored, but "KeepThis"
and "_K_L_M" are not. and "_K_L_M" are not. Only String and Number types are
stored.
" Maximum number of lines saved for each register. Old name of " Maximum number of lines saved for each register. Old name of
the '<' item, with the disadvantage that you need to put a the '<' item, with the disadvantage that you need to put a
backslash before the ", otherwise it will be recognized as the backslash before the ", otherwise it will be recognized as the

View File

@@ -1883,6 +1883,8 @@ $VIMRUNTIME starting.txt /*$VIMRUNTIME*
:emenu gui.txt /*:emenu* :emenu gui.txt /*:emenu*
:en eval.txt /*:en* :en eval.txt /*:en*
:endf eval.txt /*:endf* :endf eval.txt /*:endf*
:endfo eval.txt /*:endfo*
:endfor eval.txt /*:endfor*
:endfunction eval.txt /*:endfunction* :endfunction eval.txt /*:endfunction*
:endif eval.txt /*:endif* :endif eval.txt /*:endif*
:endt eval.txt /*:endt* :endt eval.txt /*:endt*
@@ -1934,6 +1936,7 @@ $VIMRUNTIME starting.txt /*$VIMRUNTIME*
:folddoopen fold.txt /*:folddoopen* :folddoopen fold.txt /*:folddoopen*
:foldo fold.txt /*:foldo* :foldo fold.txt /*:foldo*
:foldopen fold.txt /*:foldopen* :foldopen fold.txt /*:foldopen*
:for eval.txt /*:for*
:fu eval.txt /*:fu* :fu eval.txt /*:fu*
:function eval.txt /*:function* :function eval.txt /*:function*
:g repeat.txt /*:g* :g repeat.txt /*:g*
@@ -2039,6 +2042,7 @@ $VIMRUNTIME starting.txt /*$VIMRUNTIME*
:let-option eval.txt /*:let-option* :let-option eval.txt /*:let-option*
:let-register eval.txt /*:let-register* :let-register eval.txt /*:let-register*
:let-star eval.txt /*:let-star* :let-star eval.txt /*:let-star*
:let-unpack eval.txt /*:let-unpack*
:list various.txt /*:list* :list various.txt /*:list*
:lm map.txt /*:lm* :lm map.txt /*:lm*
:lmap map.txt /*:lmap* :lmap map.txt /*:lmap*
@@ -5298,6 +5302,7 @@ linewise motion.txt /*linewise*
linewise-register change.txt /*linewise-register* linewise-register change.txt /*linewise-register*
linewise-visual visual.txt /*linewise-visual* linewise-visual visual.txt /*linewise-visual*
lispindent() eval.txt /*lispindent()* lispindent() eval.txt /*lispindent()*
list-index eval.txt /*list-index*
list-repeat windows.txt /*list-repeat* list-repeat windows.txt /*list-repeat*
lite-syntax syntax.txt /*lite-syntax* lite-syntax syntax.txt /*lite-syntax*
lite.vim syntax.txt /*lite.vim* lite.vim syntax.txt /*lite.vim*
@@ -5871,6 +5876,7 @@ remote_foreground() eval.txt /*remote_foreground()*
remote_peek() eval.txt /*remote_peek()* remote_peek() eval.txt /*remote_peek()*
remote_read() eval.txt /*remote_read()* remote_read() eval.txt /*remote_read()*
remote_send() eval.txt /*remote_send()* remote_send() eval.txt /*remote_send()*
remove() eval.txt /*remove()*
remove-filetype filetype.txt /*remove-filetype* remove-filetype filetype.txt /*remove-filetype*
remove-option-flags options.txt /*remove-option-flags* remove-option-flags options.txt /*remove-option-flags*
rename() eval.txt /*rename()* rename() eval.txt /*rename()*

View File

@@ -6236,9 +6236,11 @@ ins_esc(count, cmdchar)
{ {
/* /*
* Don't append the ESC for "r<CR>" and "grx". * Don't append the ESC for "r<CR>" and "grx".
* When 'insertmode' is set only CTRL-L stops Insert mode. Needed for
* when "count" is non-zero.
*/ */
if (cmdchar != 'r' && cmdchar != 'v') if (cmdchar != 'r' && cmdchar != 'v')
AppendToRedobuff(ESC_STR); AppendToRedobuff(p_im ? (char_u *)"\014" : ESC_STR);
/* /*
* Repeating insert may take a long time. Check for * Repeating insert may take a long time. Check for

View File

@@ -17,6 +17,7 @@
static void free_msglist __ARGS((struct msglist *l)); static void free_msglist __ARGS((struct msglist *l));
static int throw_exception __ARGS((void *, int, char_u *)); static int throw_exception __ARGS((void *, int, char_u *));
static char_u *get_end_emsg __ARGS((struct condstack *cstack));
static void rewind_conditionals __ARGS((struct condstack *, static void rewind_conditionals __ARGS((struct condstack *,
int, int, int *)); int, int, int *));
@@ -863,7 +864,7 @@ ex_endif(eap)
did_endif = TRUE; did_endif = TRUE;
if (eap->cstack->cs_idx < 0 if (eap->cstack->cs_idx < 0
|| (eap->cstack->cs_flags[eap->cstack->cs_idx] & || (eap->cstack->cs_flags[eap->cstack->cs_idx] &
(CSF_WHILE | CSF_TRY))) (CSF_WHILE | CSF_FOR | CSF_TRY)))
eap->errmsg = (char_u *)N_("E580: :endif without :if"); eap->errmsg = (char_u *)N_("E580: :endif without :if");
else else
{ {
@@ -904,7 +905,8 @@ ex_else(eap)
&& !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE)); && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE));
if (cstack->cs_idx < 0 if (cstack->cs_idx < 0
|| (cstack->cs_flags[cstack->cs_idx] & (CSF_WHILE | CSF_TRY))) || (cstack->cs_flags[cstack->cs_idx]
& (CSF_WHILE | CSF_FOR | CSF_TRY)))
{ {
if (eap->cmdidx == CMD_else) if (eap->cmdidx == CMD_else)
{ {
@@ -976,7 +978,7 @@ ex_else(eap)
} }
/* /*
* Handle ":while". * Handle ":while" and ":for".
*/ */
void void
ex_while(eap) ex_while(eap)
@@ -988,45 +990,87 @@ ex_while(eap)
struct condstack *cstack = eap->cstack; struct condstack *cstack = eap->cstack;
if (cstack->cs_idx == CSTACK_LEN - 1) if (cstack->cs_idx == CSTACK_LEN - 1)
eap->errmsg = (char_u *)N_("E585: :while nesting too deep"); eap->errmsg = (char_u *)N_("E585: :while/:for nesting too deep");
else else
{ {
/* /*
* cs_had_while is set when we have jumped back from the matching * The loop flag is set when we have jumped back from the matching
* ":endwhile". When not set, need to initialise this cstack entry. * ":endwhile" or ":endfor". When not set, need to initialise this
* cstack entry.
*/ */
if (!cstack->cs_had_while) if ((cstack->cs_lflags & CSL_HAD_LOOP) == 0)
{ {
++cstack->cs_idx; ++cstack->cs_idx;
++cstack->cs_whilelevel; ++cstack->cs_looplevel;
cstack->cs_line[cstack->cs_idx] = -1; cstack->cs_line[cstack->cs_idx] = -1;
} }
cstack->cs_flags[cstack->cs_idx] = CSF_WHILE; cstack->cs_flags[cstack->cs_idx] =
eap->cmdidx == CMD_while ? CSF_WHILE : CSF_FOR;
/* /*
* Don't do something after an error, interrupt, or throw, or when there * Don't do something after an error, interrupt, or throw, or when
* is a surrounding conditional and it was not active. * there is a surrounding conditional and it was not active.
*/ */
skip = did_emsg || got_int || did_throw || (cstack->cs_idx > 0 skip = did_emsg || got_int || did_throw || (cstack->cs_idx > 0
&& !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE)); && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE));
result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip); if (eap->cmdidx == CMD_while)
/*
* If this cstack entry was just initialised and is active, set
* cs_had_while flag, so do_cmdline() will set the line number
* in cs_line[].
*/
if (!skip && !error && result)
{ {
cstack->cs_flags[cstack->cs_idx] |= CSF_ACTIVE | CSF_TRUE; /*
cstack->cs_had_while = !cstack->cs_had_while; * ":while bool-expr"
*/
result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
} }
else else
{ {
cstack->cs_had_while = FALSE; void *fi;
/* If the ":while" evaluates to FALSE, show the debug prompt at the
* ":endwhile" as if there was a ":break" in a ":while" evaluating /*
* to TRUE. */ * ":for var in list-expr"
*/
if ((cstack->cs_lflags & CSL_HAD_LOOP) != 0)
{
/* Jumping here from a ":continue" or ":endfor": use the
* previously evaluated list. */
fi = cstack->cs_fors[cstack->cs_idx];
error = FALSE;
}
else
{
/* Evaluate the argument and get the info in a structure. */
fi = eval_for_line(eap->arg, &error, &eap->nextcmd, skip);
cstack->cs_fors[cstack->cs_idx] = fi;
}
/* use the element at the start of the list and advance */
if (!error && fi != NULL && !skip)
result = next_for_item(fi, eap->arg);
else
result = FALSE;
if (!result)
{
free_for_info(fi);
cstack->cs_fors[cstack->cs_idx] = NULL;
}
}
/*
* If this cstack entry was just initialised and is active, set the
* loop flag, so do_cmdline() will set the line number in cs_line[].
* If executing the command a second time, clear the loop flag.
*/
if (!skip && !error && result)
{
cstack->cs_flags[cstack->cs_idx] |= (CSF_ACTIVE | CSF_TRUE);
cstack->cs_lflags ^= CSL_HAD_LOOP;
}
else
{
cstack->cs_lflags &= ~CSL_HAD_LOOP;
/* If the ":while" evaluates to FALSE or ":for" is past the end of
* the list, show the debug prompt at the ":endwhile"/":endfor" as
* if there was a ":break" in a ":while"/":for" evaluating to
* TRUE. */
if (!skip && !error) if (!skip && !error)
cstack->cs_flags[cstack->cs_idx] |= CSF_TRUE; cstack->cs_flags[cstack->cs_idx] |= CSF_TRUE;
} }
@@ -1043,25 +1087,25 @@ ex_continue(eap)
int idx; int idx;
struct condstack *cstack = eap->cstack; struct condstack *cstack = eap->cstack;
if (cstack->cs_whilelevel <= 0 || cstack->cs_idx < 0) if (cstack->cs_looplevel <= 0 || cstack->cs_idx < 0)
eap->errmsg = (char_u *)N_("E586: :continue without :while"); eap->errmsg = (char_u *)N_("E586: :continue without :while or :for");
else else
{ {
/* Try to find the matching ":while". This might stop at a try /* Try to find the matching ":while". This might stop at a try
* conditional not in its finally clause (which is then to be executed * conditional not in its finally clause (which is then to be executed
* next). Therefor, inactivate all conditionals except the ":while" * next). Therefor, inactivate all conditionals except the ":while"
* itself (if reached). */ * itself (if reached). */
idx = cleanup_conditionals(cstack, CSF_WHILE, FALSE); idx = cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, FALSE);
if ((cstack->cs_flags[idx] & CSF_WHILE)) if ((cstack->cs_flags[idx] & (CSF_WHILE | CSF_FOR)))
{ {
if (cstack->cs_idx > idx) if (cstack->cs_idx > idx)
rewind_conditionals(cstack, idx, CSF_TRY, &cstack->cs_trylevel); rewind_conditionals(cstack, idx, CSF_TRY, &cstack->cs_trylevel);
/* /*
* Set cs_had_continue, so do_cmdline() will jump back to the * Set CSL_HAD_CONT, so do_cmdline() will jump back to the
* matching ":while". * matching ":while".
*/ */
cstack->cs_had_continue = TRUE; /* let do_cmdline() handle it */ cstack->cs_lflags |= CSL_HAD_CONT; /* let do_cmdline() handle it */
} }
else else
{ {
@@ -1083,16 +1127,16 @@ ex_break(eap)
int idx; int idx;
struct condstack *cstack = eap->cstack; struct condstack *cstack = eap->cstack;
if (cstack->cs_whilelevel <= 0 || cstack->cs_idx < 0) if (cstack->cs_looplevel <= 0 || cstack->cs_idx < 0)
eap->errmsg = (char_u *)N_("E587: :break without :while"); eap->errmsg = (char_u *)N_("E587: :break without :while or :for");
else else
{ {
/* Inactivate conditionals until the matching ":while" or a try /* Inactivate conditionals until the matching ":while" or a try
* conditional not in its finally clause (which is then to be * conditional not in its finally clause (which is then to be
* executed next) is found. In the latter case, make the ":break" * executed next) is found. In the latter case, make the ":break"
* pending for execution at the ":endtry". */ * pending for execution at the ":endtry". */
idx = cleanup_conditionals(cstack, CSF_WHILE, TRUE); idx = cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, TRUE);
if (!(cstack->cs_flags[idx] & CSF_WHILE)) if (!(cstack->cs_flags[idx] & (CSF_WHILE | CSF_FOR)))
{ {
cstack->cs_pending[idx] = CSTP_BREAK; cstack->cs_pending[idx] = CSTP_BREAK;
report_make_pending(CSTP_BREAK, NULL); report_make_pending(CSTP_BREAK, NULL);
@@ -1101,7 +1145,7 @@ ex_break(eap)
} }
/* /*
* ":endwhile" * ":endwhile" and ":endfor"
*/ */
void void
ex_endwhile(eap) ex_endwhile(eap)
@@ -1109,45 +1153,64 @@ ex_endwhile(eap)
{ {
struct condstack *cstack = eap->cstack; struct condstack *cstack = eap->cstack;
int idx; int idx;
char_u *err;
int csf;
int fl;
if (cstack->cs_whilelevel <= 0 || cstack->cs_idx < 0) if (eap->cmdidx == CMD_endwhile)
eap->errmsg = e_while; {
err = e_while;
csf = CSF_WHILE;
}
else else
{ {
if (!(cstack->cs_flags[cstack->cs_idx] & CSF_WHILE)) err = e_for;
csf = CSF_FOR;
}
if (cstack->cs_looplevel <= 0 || cstack->cs_idx < 0)
eap->errmsg = err;
else
{ {
/* Try to find the matching ":while" and report what's missing. */ fl = cstack->cs_flags[cstack->cs_idx];
if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) if (!(fl & csf))
{
if (fl & CSF_WHILE)
eap->errmsg = (char_u *)_("E999: Using :endfor with :while");
else if (fl & CSF_FOR)
eap->errmsg = (char_u *)_("E999: Using :endwhile with :for");
else if (!(fl & CSF_TRY))
eap->errmsg = e_endif; eap->errmsg = e_endif;
else if (cstack->cs_flags[cstack->cs_idx] & CSF_FINALLY) else if (fl & CSF_FINALLY)
eap->errmsg = e_endtry; eap->errmsg = e_endtry;
/* Try to find the matching ":while" and report what's missing. */
for (idx = cstack->cs_idx; idx > 0; --idx) for (idx = cstack->cs_idx; idx > 0; --idx)
{ {
if ((cstack->cs_flags[idx] & CSF_TRY) fl = cstack->cs_flags[idx];
&& !(cstack->cs_flags[idx] & CSF_FINALLY)) if ((fl & CSF_TRY) && !(fl & CSF_FINALLY))
{ {
/* Give up at a try conditional not in its finally clause. /* Give up at a try conditional not in its finally clause.
* Ignore the ":endwhile". */ * Ignore the ":endwhile"/":endfor". */
eap->errmsg = e_while; eap->errmsg = err;
return; return;
} }
if (cstack->cs_flags[idx] & CSF_WHILE) if (fl & csf)
break; break;
} }
/* Cleanup and rewind all contained (and unclosed) conditionals. */ /* Cleanup and rewind all contained (and unclosed) conditionals. */
(void)cleanup_conditionals(cstack, CSF_WHILE, FALSE); (void)cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, FALSE);
rewind_conditionals(cstack, idx, CSF_TRY, &cstack->cs_trylevel); rewind_conditionals(cstack, idx, CSF_TRY, &cstack->cs_trylevel);
} }
/* /*
* When debugging or a breakpoint was encountered, display the debug * When debugging or a breakpoint was encountered, display the debug
* prompt (if not already done). This shows the user that an * prompt (if not already done). This shows the user that an
* ":enwhile" is executed when the ":while" was not TRUE or after * ":endwhile"/":endfor" is executed when the ":while" was not TRUE or
* a ":break". Handle a ">quit" debug command as if an interrupt * after a ":break". Handle a ">quit" debug command as if an
* had occurred before the ":endwhile". That is, throw an interrupt * interrupt had occurred before the ":endwhile"/":endfor". That is,
* exception if appropriate. Doing this here prevents that an * throw an interrupt exception if appropriate. Doing this here
* exception for a parsing error is discarded when throwing the * prevents that an exception for a parsing error is discarded when
* interrupt exception later on. * throwing the interrupt exception later on.
*/ */
else if (cstack->cs_flags[cstack->cs_idx] & CSF_TRUE else if (cstack->cs_flags[cstack->cs_idx] & CSF_TRUE
&& !(cstack->cs_flags[cstack->cs_idx] & CSF_ACTIVE) && !(cstack->cs_flags[cstack->cs_idx] & CSF_ACTIVE)
@@ -1155,10 +1218,10 @@ ex_endwhile(eap)
(void)do_intthrow(cstack); (void)do_intthrow(cstack);
/* /*
* Set cs_had_endwhile, so do_cmdline() will jump back to the matching * Set loop flag, so do_cmdline() will jump back to the matching
* ":while". * ":while" or ":for".
*/ */
cstack->cs_had_endwhile = TRUE; cstack->cs_lflags |= CSL_HAD_ENDLOOP;
} }
} }
@@ -1372,10 +1435,7 @@ ex_catch(eap)
{ {
/* Report what's missing if the matching ":try" is not in its /* Report what's missing if the matching ":try" is not in its
* finally clause. */ * finally clause. */
if (cstack->cs_flags[cstack->cs_idx] & CSF_WHILE) eap->errmsg = get_end_emsg(cstack);
eap->errmsg = e_endwhile;
else
eap->errmsg = e_endif;
skip = TRUE; skip = TRUE;
} }
for (idx = cstack->cs_idx; idx > 0; --idx) for (idx = cstack->cs_idx; idx > 0; --idx)
@@ -1389,7 +1449,8 @@ ex_catch(eap)
give_up = TRUE; give_up = TRUE;
} }
else if (cstack->cs_idx > idx) else if (cstack->cs_idx > idx)
rewind_conditionals(cstack, idx, CSF_WHILE, &cstack->cs_whilelevel); rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR,
&cstack->cs_looplevel);
} }
if (ends_excmd(*eap->arg)) /* no argument, catch all errors */ if (ends_excmd(*eap->arg)) /* no argument, catch all errors */
@@ -1523,11 +1584,7 @@ ex_finally(eap)
{ {
if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY))
{ {
/* Find the matching ":try" and report what's missing. */ eap->errmsg = get_end_emsg(cstack);
if (cstack->cs_flags[cstack->cs_idx] & CSF_WHILE)
eap->errmsg = e_endwhile;
else
eap->errmsg = e_endif;
for (idx = cstack->cs_idx - 1; idx > 0; --idx) for (idx = cstack->cs_idx - 1; idx > 0; --idx)
if (cstack->cs_flags[idx] & CSF_TRY) if (cstack->cs_flags[idx] & CSF_TRY)
break; break;
@@ -1546,7 +1603,8 @@ ex_finally(eap)
return; return;
} }
if (cstack->cs_idx > idx) if (cstack->cs_idx > idx)
rewind_conditionals(cstack, idx, CSF_WHILE, &cstack->cs_whilelevel); rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR,
&cstack->cs_looplevel);
/* /*
* Don't do something when the corresponding try block never got active * Don't do something when the corresponding try block never got active
@@ -1590,11 +1648,12 @@ ex_finally(eap)
* got_int is set). The pending values are restored by the * got_int is set). The pending values are restored by the
* ":endtry", except if there is a new error, interrupt, exception, * ":endtry", except if there is a new error, interrupt, exception,
* ":continue", ":break", ":return", or ":finish" in the following * ":continue", ":break", ":return", or ":finish" in the following
* finally clause. A missing ":endwhile" or ":endif" detected here * finally clause. A missing ":endwhile", ":endfor" or ":endif"
* is treated as if did_emsg and did_throw had already been set, * detected here is treated as if did_emsg and did_throw had
* respectively in case that the error is not converted to an * already been set, respectively in case that the error is not
* exception, did_throw had already been unset. We must not set * converted to an exception, did_throw had already been unset.
* did_emsg here since that would suppress the error message. * We must not set did_emsg here since that would suppress the
* error message.
*/ */
if (pending == CSTP_ERROR || did_emsg || got_int || did_throw) if (pending == CSTP_ERROR || did_emsg || got_int || did_throw)
{ {
@@ -1617,21 +1676,21 @@ ex_finally(eap)
* discarded if the finally clause is left by a ":continue", * discarded if the finally clause is left by a ":continue",
* ":break", ":return", ":finish", error, interrupt, or another * ":break", ":return", ":finish", error, interrupt, or another
* exception. When emsg() is called for a missing ":endif" or * exception. When emsg() is called for a missing ":endif" or
* a missing ":endwhile" detected here, the exception will be * a missing ":endwhile"/":endfor" detected here, the
* discarded. */ * exception will be discarded. */
if (did_throw && cstack->cs_exception[cstack->cs_idx] != if (did_throw && cstack->cs_exception[cstack->cs_idx] !=
current_exception) current_exception)
EMSG(_(e_internal)); EMSG(_(e_internal));
} }
/* /*
* Set cs_had_finally, so do_cmdline() will reset did_emsg, * Set CSL_HAD_FINA, so do_cmdline() will reset did_emsg,
* got_int, and did_throw and make the finally clause active. * got_int, and did_throw and make the finally clause active.
* This will happen after emsg() has been called for a missing * This will happen after emsg() has been called for a missing
* ":endif" or a missing ":endwhile" detected here, so that the * ":endif" or a missing ":endwhile"/":endfor" detected here, so
* following finally clause will be executed even then. * that the following finally clause will be executed even then.
*/ */
cstack->cs_had_finally = TRUE; cstack->cs_lflags |= CSL_HAD_FINA;
} }
} }
} }
@@ -1670,16 +1729,14 @@ ex_endtry(eap)
if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY))
{ {
eap->errmsg = get_end_emsg(cstack);
/* Find the matching ":try" and report what's missing. */ /* Find the matching ":try" and report what's missing. */
if (cstack->cs_flags[cstack->cs_idx] & CSF_WHILE)
eap->errmsg = e_endwhile;
else
eap->errmsg = e_endif;
idx = cstack->cs_idx; idx = cstack->cs_idx;
do do
--idx; --idx;
while (idx > 0 && !(cstack->cs_flags[idx] & CSF_TRY)); while (idx > 0 && !(cstack->cs_flags[idx] & CSF_TRY));
rewind_conditionals(cstack, idx, CSF_WHILE, &cstack->cs_whilelevel); rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR,
&cstack->cs_looplevel);
skip = TRUE; skip = TRUE;
/* /*
@@ -1977,15 +2034,16 @@ leave_cleanup(csp)
* Make conditionals inactive and discard what's pending in finally clauses * Make conditionals inactive and discard what's pending in finally clauses
* until the conditional type searched for or a try conditional not in its * until the conditional type searched for or a try conditional not in its
* finally clause is reached. If this is in an active catch clause, finish the * finally clause is reached. If this is in an active catch clause, finish the
* caught exception. Return the cstack index where the search stopped. Values * caught exception. Return the cstack index where the search stopped.
* used for "searched_cond" are CSF_WHILE or CSF_TRY or 0, the latter meaning * Values used for "searched_cond" are (CSF_WHILE | CSF_FOR) or CSF_TRY or 0,
* the innermost try conditional not in its finally clause. "inclusive" tells * the latter meaning the innermost try conditional not in its finally clause.
* whether the conditional searched for should be made inactive itself (a try * "inclusive" tells whether the conditional searched for should be made
* conditional not in its finally claused possibly find before is always made * inactive itself (a try conditional not in its finally claused possibly find
* inactive). If "inclusive" is TRUE and "searched_cond" is CSF_TRY|CSF_SILENT, * before is always made inactive). If "inclusive" is TRUE and
* the saved former value of "emsg_silent", if reset when the try conditional * "searched_cond" is CSF_TRY|CSF_SILENT, the saved former value of
* finally reached was entered, is restored (unsed by ex_endtry()). This is * "emsg_silent", if reset when the try conditional finally reached was
* normally done only when such a try conditional is left. * entered, is restored (unsed by ex_endtry()). This is normally done only
* when such a try conditional is left.
*/ */
int int
cleanup_conditionals(cstack, searched_cond, inclusive) cleanup_conditionals(cstack, searched_cond, inclusive)
@@ -2108,6 +2166,21 @@ cleanup_conditionals(cstack, searched_cond, inclusive)
return idx; return idx;
} }
/*
* Return an appropriate error message for a missing endwhile/endfor/endif.
*/
static char_u *
get_end_emsg(cstack)
struct condstack *cstack;
{
if (cstack->cs_flags[cstack->cs_idx] & CSF_WHILE)
return e_endwhile;
if (cstack->cs_flags[cstack->cs_idx] & CSF_FOR)
return e_endfor;
return e_endif;
}
/* /*
* Rewind conditionals until index "idx" is reached. "cond_type" and * Rewind conditionals until index "idx" is reached. "cond_type" and
* "cond_level" specify a conditional type and the address of a level variable * "cond_level" specify a conditional type and the address of a level variable
@@ -2141,16 +2214,17 @@ ex_endfunction(eap)
} }
/* /*
* Return TRUE if the string "p" looks like a ":while" command. * Return TRUE if the string "p" looks like a ":while" or ":for" command.
*/ */
int int
has_while_cmd(p) has_loop_cmd(p)
char_u *p; char_u *p;
{ {
p = skipwhite(p); p = skipwhite(p);
while (*p == ':') while (*p == ':')
p = skipwhite(p + 1); p = skipwhite(p + 1);
if (p[0] == 'w' && p[1] == 'h') if ((p[0] == 'w' && p[1] == 'h')
|| (p[0] == 'f' && p[1] == 'o' && p[2] == 'r'))
return TRUE; return TRUE;
return FALSE; return FALSE;
} }

View File

@@ -5459,7 +5459,7 @@ script_get(eap, cmd)
{ {
theline = eap->getline( theline = eap->getline(
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
eap->cstack->cs_whilelevel > 0 ? -1 : eap->cstack->cs_looplevel > 0 ? -1 :
#endif #endif
NUL, eap->cookie, 0); NUL, eap->cookie, 0);

View File

@@ -241,12 +241,12 @@ gui_mch_add_menu(vimmenu_T *menu, int idx)//{{{
{ {
idx++; // for tearoffs to be first in menus idx++; // for tearoffs to be first in menus
me = new QPopupMenu(parent->widget, QSTR(menu->name)); me = new QPopupMenu(parent->widget, QSTR(menu->name));
parent->widget->insertItem(QSTR(menu->name), me, (int)me, idx); parent->widget->insertItem(QSTR(menu->name), me, (long)me, idx);
} }
else else
{ {
me = new QPopupMenu(vmw->menuBar(), QSTR(menu->name)); me = new QPopupMenu(vmw->menuBar(), QSTR(menu->name));
vmw->menuBar()->insertItem(QSTR(menu->name), me, (int)me, idx); vmw->menuBar()->insertItem(QSTR(menu->name), me, (long)me, idx);
} }
me->setCaption((const char *)(menu->dname)); me->setCaption((const char *)(menu->dname));
@@ -296,7 +296,7 @@ gui_mch_add_menu_item(vimmenu_T *menu, int idx)//{{{
return; // failed return; // failed
vmw->toolBar()->insertButton( vmw->toolBar()->insertButton(
pix, pix,
(int)menu, // id (long)menu, // id
true, true,
QSTR(menu->strings[MENU_INDEX_TIP]), // tooltip or text QSTR(menu->strings[MENU_INDEX_TIP]), // tooltip or text
idx); idx);
@@ -311,7 +311,7 @@ gui_mch_add_menu_item(vimmenu_T *menu, int idx)//{{{
parent->widget->insertSeparator(); parent->widget->insertSeparator();
return; return;
} }
parent->widget->insertItem(QSTR(menu->name), (int)menu, idx); parent->widget->insertItem(QSTR(menu->name), (long)menu, idx);
#endif #endif
}//}}} }//}}}
@@ -390,12 +390,12 @@ gui_mch_destroy_menu(vimmenu_T *menu)//{{{
#ifdef FEAT_TOOLBAR #ifdef FEAT_TOOLBAR
if (menu->parent && menu_is_toolbar(menu->parent->name)) if (menu->parent && menu_is_toolbar(menu->parent->name))
{ {
vmw->toolBar()->removeItem((int)menu); vmw->toolBar()->removeItem((long)menu);
return; return;
} }
#endif #endif
if (menu->parent) if (menu->parent)
menu->parent->widget->removeItem((int)menu); menu->parent->widget->removeItem((long)menu);
if (menu->widget) if (menu->widget)
delete menu->widget; delete menu->widget;
menu->widget = 0; menu->widget = 0;

View File

@@ -1210,7 +1210,7 @@ gui_mch_menu_grey(vimmenu_T * menu, int grey)//{{{
{ {
if (!menu || !menu->parent || !menu->parent->widget) if (!menu || !menu->parent || !menu->parent->widget)
return; return;
menu->parent->widget->setItemEnabled((int)menu, !grey); menu->parent->widget->setItemEnabled((long)menu, !grey);
gui_mch_update(); gui_mch_update();
}//}}} }//}}}

View File

@@ -20,6 +20,9 @@ void *save_funccal __ARGS((void));
void restore_funccal __ARGS((void *fc)); void restore_funccal __ARGS((void *fc));
int eval_foldexpr __ARGS((char_u *arg, int *cp)); int eval_foldexpr __ARGS((char_u *arg, int *cp));
void ex_let __ARGS((exarg_T *eap)); void ex_let __ARGS((exarg_T *eap));
void *eval_for_line __ARGS((char_u *arg, int *errp, char_u **nextcmdp, int skip));
int next_for_item __ARGS((void *fi_void, char_u *arg));
void free_for_info __ARGS((void *fi_void));
void set_context_for_expression __ARGS((expand_T *xp, char_u *arg, cmdidx_T cmdidx)); void set_context_for_expression __ARGS((expand_T *xp, char_u *arg, cmdidx_T cmdidx));
void ex_call __ARGS((exarg_T *eap)); void ex_call __ARGS((exarg_T *eap));
void ex_unlet __ARGS((exarg_T *eap)); void ex_unlet __ARGS((exarg_T *eap));
@@ -47,9 +50,9 @@ void ex_function __ARGS((exarg_T *eap));
char_u *get_user_func_name __ARGS((expand_T *xp, int idx)); char_u *get_user_func_name __ARGS((expand_T *xp, int idx));
void ex_delfunction __ARGS((exarg_T *eap)); void ex_delfunction __ARGS((exarg_T *eap));
void ex_return __ARGS((exarg_T *eap)); void ex_return __ARGS((exarg_T *eap));
int do_return __ARGS((exarg_T *eap, int reanimate, int is_cmd, void *value)); int do_return __ARGS((exarg_T *eap, int reanimate, int is_cmd, void *rettv));
void discard_pending_return __ARGS((void *retvar)); void discard_pending_return __ARGS((void *rettv));
char_u *get_return_cmd __ARGS((void *retvar)); char_u *get_return_cmd __ARGS((void *rettv));
char_u *get_func_line __ARGS((int c, void *cookie, int indent)); char_u *get_func_line __ARGS((int c, void *cookie, int indent));
int func_has_ended __ARGS((void *cookie)); int func_has_ended __ARGS((void *cookie));
int func_has_abort __ARGS((void *cookie)); int func_has_abort __ARGS((void *cookie));

View File

@@ -595,34 +595,34 @@ struct eslist_elem
struct condstack struct condstack
{ {
char cs_flags[CSTACK_LEN]; /* CSF_ flags */ short cs_flags[CSTACK_LEN]; /* CSF_ flags */
char cs_pending[CSTACK_LEN]; /* CSTP_: what's pending in ":finally"*/ char cs_pending[CSTACK_LEN]; /* CSTP_: what's pending in ":finally"*/
union { union {
void *cs_pend_rv[CSTACK_LEN]; /* return typeval for pending return */ void *csp_rv[CSTACK_LEN]; /* return typeval for pending return */
void *cs_pend_ex[CSTACK_LEN]; /* exception for pending throw */ void *csp_ex[CSTACK_LEN]; /* exception for pending throw */
} cs_pend; } cs_pend;
int cs_line[CSTACK_LEN]; /* line number of ":while" line */ void *cs_fors[CSTACK_LEN]; /* info used by ":for" */
int cs_line[CSTACK_LEN]; /* line nr of ":while"/":for" line */
int cs_idx; /* current entry, or -1 if none */ int cs_idx; /* current entry, or -1 if none */
int cs_whilelevel; /* number of nested ":while"s */ int cs_looplevel; /* nr of nested ":while"s and ":for"s */
int cs_trylevel; /* number of nested ":try"s */ int cs_trylevel; /* nr of nested ":try"s */
eslist_T *cs_emsg_silent_list; /* saved values of "emsg_silent" */ eslist_T *cs_emsg_silent_list; /* saved values of "emsg_silent" */
char cs_had_while; /* just found ":while" */ char cs_lflags; /* loop flags: CSL_ flags */
char cs_had_continue; /* just found ":continue" */
char cs_had_endwhile; /* just found ":endwhile" */
char cs_had_finally; /* just found ":finally" */
}; };
# define cs_rettv cs_pend.cs_pend_rv # define cs_rettv cs_pend.csp_rv
# define cs_exception cs_pend.cs_pend_ex # define cs_exception cs_pend.csp_ex
# define CSF_TRUE 1 /* condition was TRUE */ # define CSF_TRUE 0x0001 /* condition was TRUE */
# define CSF_ACTIVE 2 /* current state is active */ # define CSF_ACTIVE 0x0002 /* current state is active */
# define CSF_ELSE 4 /* ":else" has been passed */ # define CSF_ELSE 0x0004 /* ":else" has been passed */
# define CSF_WHILE 8 /* is a ":while" */ # define CSF_WHILE 0x0008 /* is a ":while" */
# define CSF_TRY 16 /* is a ":try" */ # define CSF_FOR 0x0010 /* is a ":for" */
# define CSF_FINALLY 32 /* ":finally" has been passed */
# define CSF_THROWN 64 /* exception thrown to this try conditional */ # define CSF_TRY 0x0100 /* is a ":try" */
# define CSF_CAUGHT 128 /* exception caught by this try conditional */ # define CSF_FINALLY 0x0200 /* ":finally" has been passed */
# define CSF_SILENT 4 /* "emsg_silent" reset by ":try" */ # define CSF_THROWN 0x0400 /* exception thrown to this try conditional */
# define CSF_CAUGHT 0x0800 /* exception caught by this try conditional */
# define CSF_SILENT 0x1000 /* "emsg_silent" reset by ":try" */
/* Note that CSF_ELSE is only used when CSF_TRY and CSF_WHILE are unset /* Note that CSF_ELSE is only used when CSF_TRY and CSF_WHILE are unset
* (an ":if"), and CSF_SILENT is only used when CSF_TRY is set. */ * (an ":if"), and CSF_SILENT is only used when CSF_TRY is set. */
@@ -639,6 +639,14 @@ struct condstack
# define CSTP_RETURN 24 /* ":return" is pending */ # define CSTP_RETURN 24 /* ":return" is pending */
# define CSTP_FINISH 32 /* ":finish" is pending */ # define CSTP_FINISH 32 /* ":finish" is pending */
/*
* Flags for the cs_lflags item in struct condstack.
*/
# define CSL_HAD_LOOP 1 /* just found ":while" or ":for" */
# define CSL_HAD_ENDLOOP 2 /* just found ":endwhile" or ":endfor" */
# define CSL_HAD_CONT 4 /* just found ":continue" */
# define CSL_HAD_FINA 8 /* just found ":finally" */
/* /*
* A list of error messages that can be converted to an exception. "throw_msg" * A list of error messages that can be converted to an exception. "throw_msg"
* is only set in the first element of the list. Usually, it points to the * is only set in the first element of the list. Usually, it points to the

View File

@@ -36,5 +36,5 @@
#define VIM_VERSION_NODOT "vim70aa" #define VIM_VERSION_NODOT "vim70aa"
#define VIM_VERSION_SHORT "7.0aa" #define VIM_VERSION_SHORT "7.0aa"
#define VIM_VERSION_MEDIUM "7.0aa ALPHA" #define VIM_VERSION_MEDIUM "7.0aa ALPHA"
#define VIM_VERSION_LONG "VIM - Vi IMproved 7.0aa ALPHA (2004 Jan 4)" #define VIM_VERSION_LONG "VIM - Vi IMproved 7.0aa ALPHA (2004 Jan 5)"
#define VIM_VERSION_LONG_DATE "VIM - Vi IMproved 7.0aa ALPHA (2004 Jan 4, compiled " #define VIM_VERSION_LONG_DATE "VIM - Vi IMproved 7.0aa ALPHA (2004 Jan 5, compiled "