aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/private/helpers.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-01-25 18:31:31 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-01-25 18:31:31 +0000
commit9243becbedbb6a1592208051f8fa2b090dcc5e7d (patch)
tree607c2a862ec3f4399b8766383f6f8e04c4aa43b4 /src/nvim/api/private/helpers.c
parent9e40b6e9e1bc67f2d856adb837ee64dd0e25b717 (diff)
parent3c48d3c83fc21dbc0841f9210f04bdb073d73cd1 (diff)
downloadrneovim-usermarks.tar.gz
rneovim-usermarks.tar.bz2
rneovim-usermarks.zip
Merge remote-tracking branch 'upstream/master' into usermarksusermarks
Diffstat (limited to 'src/nvim/api/private/helpers.c')
-rw-r--r--src/nvim/api/private/helpers.c150
1 files changed, 75 insertions, 75 deletions
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index c466fc53e1..519f2cc5bf 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -3,37 +3,36 @@
#include <assert.h>
#include <inttypes.h>
+#include <limits.h>
+#include <msgpack/unpack.h>
+#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "klib/kvec.h"
#include "nvim/api/private/converter.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
-#include "nvim/api/vim.h"
#include "nvim/ascii.h"
-#include "nvim/assert.h"
-#include "nvim/buffer.h"
-#include "nvim/charset.h"
-#include "nvim/eval.h"
+#include "nvim/buffer_defs.h"
#include "nvim/eval/typval.h"
-#include "nvim/ex_cmds_defs.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/ex_eval.h"
-#include "nvim/extmark.h"
+#include "nvim/garray.h"
#include "nvim/highlight_group.h"
-#include "nvim/lib/kvec.h"
#include "nvim/lua/executor.h"
#include "nvim/map.h"
-#include "nvim/map_defs.h"
#include "nvim/mark.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
+#include "nvim/message.h"
#include "nvim/msgpack_rpc/helpers.h"
+#include "nvim/pos.h"
#include "nvim/ui.h"
#include "nvim/version.h"
-#include "nvim/vim.h"
-#include "nvim/window.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/private/funcs_metadata.generated.h"
@@ -58,6 +57,7 @@ void try_enter(TryState *const tstate)
.private_msg_list = NULL,
.trylevel = trylevel,
.got_int = got_int,
+ .did_throw = did_throw,
.need_rethrow = need_rethrow,
.did_emsg = did_emsg,
};
@@ -65,6 +65,7 @@ void try_enter(TryState *const tstate)
current_exception = NULL;
trylevel = 1;
got_int = false;
+ did_throw = false;
need_rethrow = false;
did_emsg = false;
}
@@ -85,6 +86,7 @@ bool try_leave(const TryState *const tstate, Error *const 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);
@@ -93,6 +95,7 @@ bool try_leave(const TryState *const tstate, Error *const err)
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;
@@ -127,7 +130,7 @@ bool try_end(Error *err)
force_abort = false;
if (got_int) {
- if (current_exception) {
+ if (did_throw) {
// If we got an interrupt, discard the current exception
discard_current_exception();
}
@@ -146,8 +149,19 @@ bool try_end(Error *err)
if (should_free) {
xfree(msg);
}
- } else if (current_exception) {
- api_set_error(err, kErrorTypeException, "%s", current_exception->value);
+ } else if (did_throw) {
+ if (*current_exception->throw_name != NUL) {
+ if (current_exception->throw_lnum != 0) {
+ api_set_error(err, kErrorTypeException, "%s, line %" PRIdLINENR ": %s",
+ current_exception->throw_name, current_exception->throw_lnum,
+ current_exception->value);
+ } else {
+ api_set_error(err, kErrorTypeException, "%s: %s",
+ current_exception->throw_name, current_exception->value);
+ }
+ } else {
+ api_set_error(err, kErrorTypeException, "%s", current_exception->value);
+ }
discard_current_exception();
}
@@ -214,6 +228,8 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva
return rv;
}
+ bool watched = tv_dict_is_watched(dict);
+
if (del) {
// Delete the key
if (di == NULL) {
@@ -221,6 +237,10 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva
api_set_error(err, kErrorTypeValidation, "Key not found: %s",
key.data);
} else {
+ // Notify watchers
+ if (watched) {
+ tv_dict_watcher_notify(dict, key.data, NULL, &di->di_tv);
+ }
// Return the old value
if (retval) {
rv = vim_to_object(&di->di_tv);
@@ -237,11 +257,16 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva
return rv;
}
+ typval_T oldtv = TV_INITIAL_VALUE;
+
if (di == NULL) {
// Need to create an entry
di = tv_dict_item_alloc_len(key.data, key.size);
tv_dict_add(dict, di);
} else {
+ if (watched) {
+ tv_copy(&di->di_tv, &oldtv);
+ }
// Return the old value
if (retval) {
rv = vim_to_object(&di->di_tv);
@@ -251,6 +276,13 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva
// Update the value
tv_copy(&tv, &di->di_tv);
+
+ // Notify watchers
+ if (watched) {
+ tv_dict_watcher_notify(dict, key.data, &tv, &oldtv);
+ tv_clear(&oldtv);
+ }
+
// Clear the temporary variable
tv_clear(&tv);
}
@@ -369,7 +401,13 @@ String cbuf_to_string(const char *buf, size_t size)
String cstrn_to_string(const char *str, size_t maxsize)
FUNC_ATTR_NONNULL_ALL
{
- return cbuf_to_string(str, STRNLEN(str, maxsize));
+ return cbuf_to_string(str, strnlen(str, maxsize));
+}
+
+String cstrn_as_string(char *str, size_t maxsize)
+ FUNC_ATTR_NONNULL_ALL
+{
+ return cbuf_as_string(str, strnlen(str, maxsize));
}
/// Creates a String using the given C string. Unlike
@@ -440,53 +478,15 @@ Array string_to_array(const String input, bool crlf)
return ret;
}
-/// Collects `n` buffer lines into array `l`, optionally replacing newlines
-/// with NUL.
-///
-/// @param buf Buffer to get lines from
-/// @param n Number of lines to collect
-/// @param replace_nl Replace newlines ("\n") with NUL
-/// @param start Line number to start from
-/// @param[out] l Lines are copied here
-/// @param err[out] Error, if any
-/// @return true unless `err` was set
-bool buf_collect_lines(buf_T *buf, size_t n, int64_t start, bool replace_nl, Array *l, Error *err)
-{
- for (size_t i = 0; i < n; i++) {
- int64_t lnum = start + (int64_t)i;
-
- if (lnum >= MAXLNUM) {
- if (err != NULL) {
- api_set_error(err, kErrorTypeValidation, "Line index is too high");
- }
- return false;
- }
-
- const char *bufstr = (char *)ml_get_buf(buf, (linenr_T)lnum, false);
- Object str = STRING_OBJ(cstr_to_string(bufstr));
-
- if (replace_nl) {
- // Vim represents NULs as NLs, but this may confuse clients.
- strchrsub(str.data.string.data, '\n', '\0');
- }
-
- l->items[i] = str;
- }
-
- return true;
-}
-
/// Returns a substring of a buffer line
///
/// @param buf Buffer handle
/// @param lnum Line number (1-based)
/// @param start_col Starting byte offset into line (0-based)
/// @param end_col Ending byte offset into line (0-based, exclusive)
-/// @param replace_nl Replace newlines ('\n') with null ('\0')
/// @param err Error object
/// @return The text between start_col and end_col on line lnum of buffer buf
-String buf_get_text(buf_T *buf, int64_t lnum, int64_t start_col, int64_t end_col, bool replace_nl,
- Error *err)
+String buf_get_text(buf_T *buf, int64_t lnum, int64_t start_col, int64_t end_col, Error *err)
{
String rv = STRING_INIT;
@@ -495,7 +495,7 @@ String buf_get_text(buf_T *buf, int64_t lnum, int64_t start_col, int64_t end_col
return rv;
}
- const char *bufstr = (char *)ml_get_buf(buf, (linenr_T)lnum, false);
+ char *bufstr = ml_get_buf(buf, (linenr_T)lnum, false);
size_t line_length = strlen(bufstr);
start_col = start_col < 0 ? (int64_t)line_length + start_col + 1 : start_col;
@@ -515,12 +515,7 @@ String buf_get_text(buf_T *buf, int64_t lnum, int64_t start_col, int64_t end_col
return rv;
}
- rv = cstrn_to_string(&bufstr[start_col], (size_t)(end_col - start_col));
- if (replace_nl) {
- strchrsub(rv.data, '\n', '\0');
- }
-
- return rv;
+ return cstrn_as_string(&bufstr[start_col], (size_t)(end_col - start_col));
}
void api_free_string(String value)
@@ -618,6 +613,7 @@ void api_clear_error(Error *value)
value->type = kErrorTypeNone;
}
+/// @returns a shared value. caller must not modify it!
Dictionary api_metadata(void)
{
static Dictionary metadata = ARRAY_DICT_INIT;
@@ -630,7 +626,7 @@ Dictionary api_metadata(void)
init_type_metadata(&metadata);
}
- return copy_object(DICTIONARY_OBJ(metadata)).data.dictionary;
+ return metadata;
}
static void init_function_metadata(Dictionary *metadata)
@@ -715,36 +711,40 @@ static void init_type_metadata(Dictionary *metadata)
PUT(*metadata, "types", DICTIONARY_OBJ(types));
}
-String copy_string(String str)
+// all the copy_[object] functions allow arena=NULL,
+// then global allocations are used, and the resulting object
+// should be freed with an api_free_[object] function
+
+String copy_string(String str, Arena *arena)
{
if (str.data != NULL) {
- return (String){ .data = xmemdupz(str.data, str.size), .size = str.size };
+ return (String){ .data = arena_memdupz(arena, str.data, str.size), .size = str.size };
} else {
return (String)STRING_INIT;
}
}
-Array copy_array(Array array)
+Array copy_array(Array array, Arena *arena)
{
- Array rv = ARRAY_DICT_INIT;
+ Array rv = arena_array(arena, array.size);
for (size_t i = 0; i < array.size; i++) {
- ADD(rv, copy_object(array.items[i]));
+ ADD(rv, copy_object(array.items[i], arena));
}
return rv;
}
-Dictionary copy_dictionary(Dictionary dict)
+Dictionary copy_dictionary(Dictionary dict, Arena *arena)
{
- Dictionary rv = ARRAY_DICT_INIT;
+ Dictionary rv = arena_dict(arena, dict.size);
for (size_t i = 0; i < dict.size; i++) {
KeyValuePair item = dict.items[i];
- PUT(rv, item.key.data, copy_object(item.value));
+ PUT_C(rv, copy_string(item.key, arena).data, copy_object(item.value, arena));
}
return rv;
}
/// Creates a deep clone of an object
-Object copy_object(Object obj)
+Object copy_object(Object obj, Arena *arena)
{
switch (obj.type) {
case kObjectTypeBuffer:
@@ -757,13 +757,13 @@ Object copy_object(Object obj)
return obj;
case kObjectTypeString:
- return STRING_OBJ(copy_string(obj.data.string));
+ return STRING_OBJ(copy_string(obj.data.string, arena));
case kObjectTypeArray:
- return ARRAY_OBJ(copy_array(obj.data.array));
+ return ARRAY_OBJ(copy_array(obj.data.array, arena));
case kObjectTypeDictionary:
- return DICTIONARY_OBJ(copy_dictionary(obj.data.dictionary));
+ return DICTIONARY_OBJ(copy_dictionary(obj.data.dictionary, arena));
case kObjectTypeLuaRef:
return LUAREF_OBJ(api_new_luaref(obj.data.luaref));
@@ -844,7 +844,7 @@ HlMessage parse_hl_msg(Array chunks, Error *err)
goto free_exit;
}
- String str = copy_string(chunk.items[0].data.string);
+ String str = copy_string(chunk.items[0].data.string, NULL);
int attr = 0;
if (chunk.size == 2) {