aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/private/helpers.c
diff options
context:
space:
mode:
authorZyX <kp-pav@yandex.ru>2017-07-01 15:34:25 +0300
committerZyX <kp-pav@yandex.ru>2017-07-01 15:34:25 +0300
commit7ab152aaa58f493e54d03a15960b8a288196e588 (patch)
tree98bdee4ca0c37d1b71b70fe0db4fedb3c4ef1f64 /src/nvim/api/private/helpers.c
parentea75966e4232dc4a3693cbc4a572f2116c49b138 (diff)
downloadrneovim-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.c46
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)
{