aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/private/helpers.c
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2017-08-16 00:20:37 +0200
committerJustin M. Keyes <justinkz@gmail.com>2017-08-16 00:20:37 +0200
commitbb70eec17782501db35683f48136fcced9eae259 (patch)
tree2c0185c522e0c32f6a553098dc706a9ac26cb8be /src/nvim/api/private/helpers.c
parentab72063a52248cc5c173424d82cfee001a40e93c (diff)
parent19a28352a925b0a8502d57ec4f42b1412639aa6c (diff)
downloadrneovim-bb70eec17782501db35683f48136fcced9eae259.tar.gz
rneovim-bb70eec17782501db35683f48136fcced9eae259.tar.bz2
rneovim-bb70eec17782501db35683f48136fcced9eae259.zip
Merge #6364 'command-line color hook'
Diffstat (limited to 'src/nvim/api/private/helpers.c')
-rw-r--r--src/nvim/api/private/helpers.c69
1 files changed, 68 insertions, 1 deletions
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 1ed2bc013e..e736e29e2d 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -37,7 +37,72 @@ 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) {
+ .current_exception = current_exception,
+ .msg_list = (const struct msglist *const *)msg_list,
+ .private_msg_list = NULL,
+ .trylevel = trylevel,
+ .got_int = got_int,
+ .did_throw = did_throw,
+ .need_rethrow = need_rethrow,
+ .did_emsg = did_emsg,
+ };
+ msg_list = &tstate->private_msg_list;
+ current_exception = NULL;
+ trylevel = 1;
+ got_int = false;
+ did_throw = false;
+ need_rethrow = false;
+ did_emsg = false;
+}
+
+/// 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(!need_rethrow);
+ assert(!got_int);
+ assert(!did_throw);
+ assert(!did_emsg);
+ assert(msg_list == &tstate->private_msg_list);
+ assert(*msg_list == NULL);
+ assert(current_exception == NULL);
+ msg_list = (struct msglist **)tstate->msg_list;
+ current_exception = tstate->current_exception;
+ trylevel = tstate->trylevel;
+ got_int = tstate->got_int;
+ did_throw = tstate->did_throw;
+ need_rethrow = tstate->need_rethrow;
+ did_emsg = tstate->did_emsg;
+ return ret;
+}
+
/// Start block that may cause vimscript exceptions
+///
+/// Each try_start() call should be mirrored by try_end() call.
+///
+/// To be used as a replacement of `:try … catch … endtry` in C code, in cases
+/// when error flag could not already be set. If there may be pending error
+/// state at the time try_start() is executed which needs to be preserved,
+/// try_enter()/try_leave() pair should be used instead.
void try_start(void)
{
++trylevel;
@@ -50,7 +115,9 @@ void try_start(void)
/// @return true if an error occurred
bool try_end(Error *err)
{
- --trylevel;
+ // Note: all globals manipulated here should be saved/restored in
+ // try_enter/try_leave.
+ trylevel--;
// Without this it stops processing all subsequent VimL commands and
// generates strange error messages if I e.g. try calling Test() in a