diff options
author | ZyX <kp-pav@yandex.ru> | 2017-07-01 15:34:25 +0300 |
---|---|---|
committer | ZyX <kp-pav@yandex.ru> | 2017-07-01 15:34:25 +0300 |
commit | 7ab152aaa58f493e54d03a15960b8a288196e588 (patch) | |
tree | 98bdee4ca0c37d1b71b70fe0db4fedb3c4ef1f64 /src/nvim/api/private/helpers.c | |
parent | ea75966e4232dc4a3693cbc4a572f2116c49b138 (diff) | |
download | rneovim-7ab152aaa58f493e54d03a15960b8a288196e588.tar.gz rneovim-7ab152aaa58f493e54d03a15960b8a288196e588.tar.bz2 rneovim-7ab152aaa58f493e54d03a15960b8a288196e588.zip |
ex_getln: Save and restore try state
Problem: when processing cycle such as
:for pat in [' \ze*', ' \zs*']
: try
: let l = matchlist('x x', pat)
: $put ='E888 NOT detected for ' . pat
: catch
: $put ='E888 detected for ' . pat
: endtry
:endfor
`:let l = …` throwing an error causes this error to be caught after
color_cmdline attempts to get callback for highlighting next line (the one with
`$put = 'E888 NOT…`). Saving/restoring state prevents this from happening.
Diffstat (limited to 'src/nvim/api/private/helpers.c')
-rw-r--r-- | src/nvim/api/private/helpers.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index d401ae52a0..883a5a2fd1 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -37,6 +37,52 @@ typedef struct { # include "api/private/ui_events_metadata.generated.h" #endif +/// Start block that may cause VimL exceptions while evaluating another code +/// +/// Used when caller is supposed to be operating when other VimL code is being +/// processed and that “other VimL code” must not be affected. +/// +/// @param[out] tstate Location where try state should be saved. +void try_enter(TryState *const tstate) +{ + *tstate = (TryState) { + .trylevel = trylevel, + .got_int = got_int, + .did_throw = did_throw, + .msg_list = (const struct msglist *const *)msg_list, + .private_msg_list = NULL, + }; + trylevel = 1; + got_int = false; + did_throw = false; + msg_list = &tstate->private_msg_list; +} + +/// End try block, set the error message if any and restore previous state +/// +/// @warning Return is consistent with most functions (false on error), not with +/// try_end (true on error). +/// +/// @param[in] tstate Previous state to restore. +/// @param[out] err Location where error should be saved. +/// +/// @return false if error occurred, true otherwise. +bool try_leave(const TryState *const tstate, Error *const err) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + const bool ret = !try_end(err); + assert(trylevel == 0); + assert(!got_int); + assert(!did_throw); + assert(msg_list == &tstate->private_msg_list); + assert(*msg_list == NULL); + trylevel = tstate->trylevel; + got_int = tstate->got_int; + did_throw = tstate->did_throw; + msg_list = (struct msglist **)tstate->msg_list; + return ret; +} + /// Start block that may cause vimscript exceptions void try_start(void) { |