aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/private/helpers.c
diff options
context:
space:
mode:
authorJosh Rahm <rahm@google.com>2022-07-18 19:37:18 +0000
committerJosh Rahm <rahm@google.com>2022-07-18 19:37:18 +0000
commit308e1940dcd64aa6c344c403d4f9e0dda58d9c5c (patch)
tree35fe43e01755e0f312650667004487a44d6b7941 /src/nvim/api/private/helpers.c
parent96a00c7c588b2f38a2424aeeb4ea3581d370bf2d (diff)
parente8c94697bcbe23a5c7b07c292b90a6b70aadfa87 (diff)
downloadrneovim-308e1940dcd64aa6c344c403d4f9e0dda58d9c5c.tar.gz
rneovim-308e1940dcd64aa6c344c403d4f9e0dda58d9c5c.tar.bz2
rneovim-308e1940dcd64aa6c344c403d4f9e0dda58d9c5c.zip
Merge remote-tracking branch 'upstream/master' into rahm
Diffstat (limited to 'src/nvim/api/private/helpers.c')
-rw-r--r--src/nvim/api/private/helpers.c833
1 files changed, 121 insertions, 712 deletions
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index f9603acbda..fad75d55be 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -16,12 +16,12 @@
#include "nvim/assert.h"
#include "nvim/buffer.h"
#include "nvim/charset.h"
-#include "nvim/decoration.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/ex_cmds_defs.h"
#include "nvim/extmark.h"
#include "nvim/fileio.h"
-#include "nvim/getchar.h"
+#include "nvim/highlight_group.h"
#include "nvim/lib/kvec.h"
#include "nvim/lua/executor.h"
#include "nvim/map.h"
@@ -30,9 +30,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/msgpack_rpc/helpers.h"
-#include "nvim/option.h"
-#include "nvim/option_defs.h"
-#include "nvim/syntax.h"
#include "nvim/ui.h"
#include "nvim/version.h"
#include "nvim/vim.h"
@@ -111,7 +108,7 @@ bool try_leave(const TryState *const tstate, Error *const err)
/// try_enter()/try_leave() pair should be used instead.
void try_start(void)
{
- ++trylevel;
+ trylevel++;
}
/// End try block, set the error message if any and return true if an error
@@ -139,10 +136,10 @@ bool try_end(Error *err)
got_int = false;
} else if (msg_list != NULL && *msg_list != NULL) {
int should_free;
- char *msg = (char *)get_exception_string(*msg_list,
- ET_ERROR,
- NULL,
- &should_free);
+ char *msg = get_exception_string(*msg_list,
+ ET_ERROR,
+ NULL,
+ &should_free);
api_set_error(err, kErrorTypeException, "%s", msg);
free_global_msglist();
@@ -261,157 +258,6 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva
return rv;
}
-/// Gets the value of a global or local(buffer, window) option.
-///
-/// @param from If `type` is `SREQ_WIN` or `SREQ_BUF`, this must be a pointer
-/// to the window or buffer.
-/// @param type One of `SREQ_GLOBAL`, `SREQ_WIN` or `SREQ_BUF`
-/// @param name The option name
-/// @param[out] err Details of an error that may have occurred
-/// @return the option value
-Object get_option_from(void *from, int type, String name, Error *err)
-{
- Object rv = OBJECT_INIT;
-
- if (name.size == 0) {
- api_set_error(err, kErrorTypeValidation, "Empty option name");
- return rv;
- }
-
- // Return values
- int64_t numval;
- char *stringval = NULL;
- int flags = get_option_value_strict(name.data, &numval, &stringval,
- type, from);
-
- if (!flags) {
- api_set_error(err, kErrorTypeValidation, "Invalid option name: '%s'",
- name.data);
- return rv;
- }
-
- if (flags & SOPT_BOOL) {
- rv.type = kObjectTypeBoolean;
- rv.data.boolean = numval ? true : false;
- } else if (flags & SOPT_NUM) {
- rv.type = kObjectTypeInteger;
- rv.data.integer = numval;
- } else if (flags & SOPT_STRING) {
- if (stringval) {
- rv.type = kObjectTypeString;
- rv.data.string.data = stringval;
- rv.data.string.size = strlen(stringval);
- } else {
- api_set_error(err, kErrorTypeException,
- "Failed to get value for option '%s'",
- name.data);
- }
- } else {
- api_set_error(err,
- kErrorTypeException,
- "Unknown type for option '%s'",
- name.data);
- }
-
- return rv;
-}
-
-/// Sets the value of a global or local(buffer, window) option.
-///
-/// @param to If `type` is `SREQ_WIN` or `SREQ_BUF`, this must be a pointer
-/// to the window or buffer.
-/// @param type One of `SREQ_GLOBAL`, `SREQ_WIN` or `SREQ_BUF`
-/// @param name The option name
-/// @param[out] err Details of an error that may have occurred
-void set_option_to(uint64_t channel_id, void *to, int type, String name, Object value, Error *err)
-{
- if (name.size == 0) {
- api_set_error(err, kErrorTypeValidation, "Empty option name");
- return;
- }
-
- int flags = get_option_value_strict(name.data, NULL, NULL, type, to);
-
- if (flags == 0) {
- api_set_error(err, kErrorTypeValidation, "Invalid option name '%s'",
- name.data);
- return;
- }
-
- if (value.type == kObjectTypeNil) {
- if (type == SREQ_GLOBAL) {
- api_set_error(err, kErrorTypeException, "Cannot unset option '%s'",
- name.data);
- return;
- } else if (!(flags & SOPT_GLOBAL)) {
- api_set_error(err,
- kErrorTypeException,
- "Cannot unset option '%s' "
- "because it doesn't have a global value",
- name.data);
- return;
- } else {
- unset_global_local_option(name.data, to);
- return;
- }
- }
-
- int numval = 0;
- char *stringval = NULL;
-
- if (flags & SOPT_BOOL) {
- if (value.type != kObjectTypeBoolean) {
- api_set_error(err,
- kErrorTypeValidation,
- "Option '%s' requires a Boolean value",
- name.data);
- return;
- }
-
- numval = value.data.boolean;
- } else if (flags & SOPT_NUM) {
- if (value.type != kObjectTypeInteger) {
- api_set_error(err, kErrorTypeValidation,
- "Option '%s' requires an integer value",
- name.data);
- return;
- }
-
- if (value.data.integer > INT_MAX || value.data.integer < INT_MIN) {
- api_set_error(err, kErrorTypeValidation,
- "Value for option '%s' is out of range",
- name.data);
- return;
- }
-
- numval = (int)value.data.integer;
- } else {
- if (value.type != kObjectTypeString) {
- api_set_error(err, kErrorTypeValidation,
- "Option '%s' requires a string value",
- name.data);
- return;
- }
-
- stringval = value.data.string.data;
- }
-
- const sctx_T save_current_sctx = current_sctx;
- current_sctx.sc_sid =
- channel_id == LUA_INTERNAL_CALL ? SID_LUA : SID_API_CLIENT;
- current_sctx.sc_lnum = 0;
- current_channel_id = channel_id;
-
- const int opt_flags = (type == SREQ_WIN && !(flags & SOPT_GLOBAL))
- ? 0 : (type == SREQ_GLOBAL)
- ? OPT_GLOBAL : OPT_LOCAL;
- set_option_value_for(name.data, numval, stringval,
- opt_flags, type, to, err);
-
- current_sctx = save_current_sctx;
-}
-
-
buf_T *find_buffer_by_handle(Buffer buffer, Error *err)
{
if (buffer == 0) {
@@ -493,6 +339,16 @@ String cstr_to_string(const char *str)
};
}
+/// Copies a String to an allocated, NUL-terminated C string.
+///
+/// @param str the String to copy
+/// @return the resulting C string
+char *string_to_cstr(String str)
+ FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ return xstrndup(str.data, str.size);
+}
+
/// Copies buffer to an allocated String.
/// The resulting string is also NUL-terminated, to facilitate interoperating
/// with code using C strings.
@@ -584,145 +440,6 @@ Array string_to_array(const String input, bool crlf)
return ret;
}
-/// Set, tweak, or remove a mapping in a mode. Acts as the implementation for
-/// functions like @ref nvim_buf_set_keymap.
-///
-/// Arguments are handled like @ref nvim_set_keymap unless noted.
-/// @param buffer Buffer handle for a specific buffer, or 0 for the current
-/// buffer, or -1 to signify global behavior ("all buffers")
-/// @param is_unmap When true, removes the mapping that matches {lhs}.
-void modify_keymap(Buffer buffer, bool is_unmap, String mode, String lhs, String rhs,
- Dict(keymap) *opts, Error *err)
-{
- LuaRef lua_funcref = LUA_NOREF;
- bool global = (buffer == -1);
- if (global) {
- buffer = 0;
- }
- buf_T *target_buf = find_buffer_by_handle(buffer, err);
-
- if (!target_buf) {
- return;
- }
-
- if (opts != NULL && opts->callback.type == kObjectTypeLuaRef) {
- lua_funcref = opts->callback.data.luaref;
- opts->callback.data.luaref = LUA_NOREF;
- }
- MapArguments parsed_args = MAP_ARGUMENTS_INIT;
- if (opts) {
-#define KEY_TO_BOOL(name) \
- parsed_args.name = api_object_to_bool(opts->name, #name, false, err); \
- if (ERROR_SET(err)) { \
- goto fail_and_free; \
- }
-
- KEY_TO_BOOL(nowait);
- KEY_TO_BOOL(noremap);
- KEY_TO_BOOL(silent);
- KEY_TO_BOOL(script);
- KEY_TO_BOOL(expr);
- KEY_TO_BOOL(unique);
-#undef KEY_TO_BOOL
- }
- parsed_args.buffer = !global;
-
- set_maparg_lhs_rhs((char_u *)lhs.data, lhs.size,
- (char_u *)rhs.data, rhs.size, lua_funcref,
- CPO_TO_CPO_FLAGS, &parsed_args);
- if (opts != NULL && opts->desc.type == kObjectTypeString) {
- parsed_args.desc = xstrdup(opts->desc.data.string.data);
- } else {
- parsed_args.desc = NULL;
- }
- if (parsed_args.lhs_len > MAXMAPLEN) {
- api_set_error(err, kErrorTypeValidation, "LHS exceeds maximum map length: %s", lhs.data);
- goto fail_and_free;
- }
-
- if (mode.size > 1) {
- api_set_error(err, kErrorTypeValidation, "Shortname is too long: %s", mode.data);
- goto fail_and_free;
- }
- int mode_val; // integer value of the mapping mode, to be passed to do_map()
- char_u *p = (char_u *)((mode.size) ? mode.data : "m");
- if (STRNCMP(p, "!", 2) == 0) {
- mode_val = get_map_mode(&p, true); // mapmode-ic
- } else {
- mode_val = get_map_mode(&p, false);
- if ((mode_val == VISUAL + SELECTMODE + NORMAL + OP_PENDING)
- && mode.size > 0) {
- // get_map_mode() treats unrecognized mode shortnames as ":map".
- // This is an error unless the given shortname was empty string "".
- api_set_error(err, kErrorTypeValidation, "Invalid mode shortname: \"%s\"", (char *)p);
- goto fail_and_free;
- }
- }
-
- if (parsed_args.lhs_len == 0) {
- api_set_error(err, kErrorTypeValidation, "Invalid (empty) LHS");
- goto fail_and_free;
- }
-
- bool is_noremap = parsed_args.noremap;
- assert(!(is_unmap && is_noremap));
-
- if (!is_unmap && lua_funcref == LUA_NOREF
- && (parsed_args.rhs_len == 0 && !parsed_args.rhs_is_noop)) {
- if (rhs.size == 0) { // assume that the user wants RHS to be a <Nop>
- parsed_args.rhs_is_noop = true;
- } else {
- // the given RHS was nonempty and not a <Nop>, but was parsed as if it
- // were empty?
- assert(false && "Failed to parse nonempty RHS!");
- api_set_error(err, kErrorTypeValidation, "Parsing of nonempty RHS failed: %s", rhs.data);
- goto fail_and_free;
- }
- } else if (is_unmap && (parsed_args.rhs_len || parsed_args.rhs_lua != LUA_NOREF)) {
- if (parsed_args.rhs_len) {
- api_set_error(err, kErrorTypeValidation,
- "Gave nonempty RHS in unmap command: %s", parsed_args.rhs);
- } else {
- api_set_error(err, kErrorTypeValidation, "Gave nonempty RHS for unmap");
- }
- goto fail_and_free;
- }
-
- // buf_do_map() reads noremap/unmap as its own argument.
- int maptype_val = 0;
- if (is_unmap) {
- maptype_val = 1;
- } else if (is_noremap) {
- maptype_val = 2;
- }
-
- switch (buf_do_map(maptype_val, &parsed_args, mode_val, 0, target_buf)) {
- case 0:
- break;
- case 1:
- api_set_error(err, kErrorTypeException, (char *)e_invarg, 0);
- goto fail_and_free;
- case 2:
- api_set_error(err, kErrorTypeException, (char *)e_nomap, 0);
- goto fail_and_free;
- case 5:
- api_set_error(err, kErrorTypeException,
- "E227: mapping already exists for %s", parsed_args.lhs);
- goto fail_and_free;
- default:
- assert(false && "Unrecognized return code!");
- goto fail_and_free;
- } // switch
-
- parsed_args.rhs_lua = LUA_NOREF; // don't clear ref on success
-fail_and_free:
- NLUA_CLEAR_REF(parsed_args.rhs_lua);
- xfree(parsed_args.rhs);
- xfree(parsed_args.orig_rhs);
- XFREE_CLEAR(parsed_args.desc);
- return;
-}
-
/// Collects `n` buffer lines into array `l`, optionally replacing newlines
/// with NUL.
///
@@ -759,6 +476,52 @@ bool buf_collect_lines(buf_T *buf, size_t n, int64_t start, bool replace_nl, Arr
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 rv = STRING_INIT;
+
+ if (lnum >= MAXLNUM) {
+ api_set_error(err, kErrorTypeValidation, "Line index is too high");
+ return rv;
+ }
+
+ const char *bufstr = (char *)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;
+ end_col = end_col < 0 ? (int64_t)line_length + end_col + 1 : end_col;
+
+ if (start_col >= MAXCOL || end_col >= MAXCOL) {
+ api_set_error(err, kErrorTypeValidation, "Column index is too high");
+ return rv;
+ }
+
+ if (start_col > end_col) {
+ api_set_error(err, kErrorTypeValidation, "start_col must be less than end_col");
+ return rv;
+ }
+
+ if ((size_t)start_col >= line_length) {
+ 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;
+}
void api_free_string(String value)
{
@@ -769,6 +532,29 @@ void api_free_string(String value)
xfree(value.data);
}
+Array arena_array(Arena *arena, size_t max_size)
+{
+ Array arr = ARRAY_DICT_INIT;
+ kv_fixsize_arena(arena, arr, max_size);
+ return arr;
+}
+
+Dictionary arena_dict(Arena *arena, size_t max_size)
+{
+ Dictionary dict = ARRAY_DICT_INIT;
+ kv_fixsize_arena(arena, dict, max_size);
+ return dict;
+}
+
+String arena_string(Arena *arena, String str)
+{
+ if (str.size) {
+ return cbuf_as_string(arena_memdupz(arena, str.data, str.size), str.size);
+ } else {
+ return (String)STRING_INIT;
+ }
+}
+
void api_free_object(Object value)
{
switch (value.type) {
@@ -987,63 +773,6 @@ Object copy_object(Object obj)
}
}
-static void set_option_value_for(char *key, int numval, char *stringval, int opt_flags,
- int opt_type, void *from, Error *err)
-{
- win_T *save_curwin = NULL;
- tabpage_T *save_curtab = NULL;
- aco_save_T aco;
-
- try_start();
- switch (opt_type)
- {
- case SREQ_WIN:
- if (switch_win_noblock(&save_curwin, &save_curtab, (win_T *)from,
- win_find_tabpage((win_T *)from), true)
- == FAIL) {
- restore_win_noblock(save_curwin, save_curtab, true);
- if (try_end(err)) {
- return;
- }
- api_set_error(err,
- kErrorTypeException,
- "Problem while switching windows");
- return;
- }
- set_option_value_err(key, numval, stringval, opt_flags, err);
- restore_win_noblock(save_curwin, save_curtab, true);
- break;
- case SREQ_BUF:
- aucmd_prepbuf(&aco, (buf_T *)from);
- set_option_value_err(key, numval, stringval, opt_flags, err);
- aucmd_restbuf(&aco);
- break;
- case SREQ_GLOBAL:
- set_option_value_err(key, numval, stringval, opt_flags, err);
- break;
- }
-
- if (ERROR_SET(err)) {
- return;
- }
-
- try_end(err);
-}
-
-
-static void set_option_value_err(char *key, int numval, char *stringval, int opt_flags, Error *err)
-{
- char *errmsg;
-
- if ((errmsg = set_option_value(key, numval, stringval, opt_flags))) {
- if (try_end(err)) {
- return;
- }
-
- api_set_error(err, kErrorTypeException, "%s", errmsg);
- }
-}
-
void api_set_error(Error *err, ErrorType errType, const char *format, ...)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PRINTF(3, 4)
{
@@ -1064,171 +793,6 @@ void api_set_error(Error *err, ErrorType errType, const char *format, ...)
err->type = errType;
}
-/// Get an array containing dictionaries describing mappings
-/// based on mode and buffer id
-///
-/// @param mode The abbreviation for the mode
-/// @param buf The buffer to get the mapping array. NULL for global
-/// @param from_lua Whether it is called from internal lua api.
-/// @returns Array of maparg()-like dictionaries describing mappings
-ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf, bool from_lua)
-{
- Array mappings = ARRAY_DICT_INIT;
- dict_T *const dict = tv_dict_alloc();
-
- // Convert the string mode to the integer mode
- // that is stored within each mapblock
- char_u *p = (char_u *)mode.data;
- int int_mode = get_map_mode(&p, 0);
-
- // Determine the desired buffer value
- long buffer_value = (buf == NULL) ? 0 : buf->handle;
-
- for (int i = 0; i < MAX_MAPHASH; i++) {
- for (const mapblock_T *current_maphash = get_maphash(i, buf);
- current_maphash;
- current_maphash = current_maphash->m_next) {
- // Check for correct mode
- if (int_mode & current_maphash->m_mode) {
- mapblock_fill_dict(dict, current_maphash, buffer_value, false);
- Object api_dict = vim_to_object((typval_T[]) { { .v_type = VAR_DICT,
- .vval.v_dict = dict } });
- if (from_lua) {
- Dictionary d = api_dict.data.dictionary;
- for (size_t j = 0; j < d.size; j++) {
- if (strequal("callback", d.items[j].key.data)) {
- d.items[j].value.type = kObjectTypeLuaRef;
- d.items[j].value.data.luaref = api_new_luaref((LuaRef)d.items[j].value.data.integer);
- break;
- }
- }
- }
- ADD(mappings, api_dict);
- tv_dict_clear(dict);
- }
- }
- }
- tv_dict_free(dict);
-
- return mappings;
-}
-
-/// Gets the line and column of an extmark.
-///
-/// Extmarks may be queried by position, name or even special names
-/// in the future such as "cursor".
-///
-/// @param[out] lnum extmark line
-/// @param[out] colnr extmark column
-///
-/// @return true if the extmark was found, else false
-bool extmark_get_index_from_obj(buf_T *buf, Integer ns_id, Object obj, int
- *row, colnr_T *col, Error *err)
-{
- // Check if it is mark id
- if (obj.type == kObjectTypeInteger) {
- Integer id = obj.data.integer;
- if (id == 0) {
- *row = 0;
- *col = 0;
- return true;
- } else if (id == -1) {
- *row = MAXLNUM;
- *col = MAXCOL;
- return true;
- } else if (id < 0) {
- api_set_error(err, kErrorTypeValidation, "Mark id must be positive");
- return false;
- }
-
- ExtmarkInfo extmark = extmark_from_id(buf, (uint64_t)ns_id, (uint64_t)id);
- if (extmark.row >= 0) {
- *row = extmark.row;
- *col = extmark.col;
- return true;
- } else {
- api_set_error(err, kErrorTypeValidation, "No mark with requested id");
- return false;
- }
-
- // Check if it is a position
- } else if (obj.type == kObjectTypeArray) {
- Array pos = obj.data.array;
- if (pos.size != 2
- || pos.items[0].type != kObjectTypeInteger
- || pos.items[1].type != kObjectTypeInteger) {
- api_set_error(err, kErrorTypeValidation,
- "Position must have 2 integer elements");
- return false;
- }
- Integer pos_row = pos.items[0].data.integer;
- Integer pos_col = pos.items[1].data.integer;
- *row = (int)(pos_row >= 0 ? pos_row : MAXLNUM);
- *col = (colnr_T)(pos_col >= 0 ? pos_col : MAXCOL);
- return true;
- } else {
- api_set_error(err, kErrorTypeValidation,
- "Position must be a mark id Integer or position Array");
- return false;
- }
-}
-
-VirtText parse_virt_text(Array chunks, Error *err, int *width)
-{
- VirtText virt_text = KV_INITIAL_VALUE;
- int w = 0;
- for (size_t i = 0; i < chunks.size; i++) {
- if (chunks.items[i].type != kObjectTypeArray) {
- api_set_error(err, kErrorTypeValidation, "Chunk is not an array");
- goto free_exit;
- }
- Array chunk = chunks.items[i].data.array;
- if (chunk.size == 0 || chunk.size > 2
- || chunk.items[0].type != kObjectTypeString) {
- api_set_error(err, kErrorTypeValidation,
- "Chunk is not an array with one or two strings");
- goto free_exit;
- }
-
- String str = chunk.items[0].data.string;
-
- int hl_id = 0;
- if (chunk.size == 2) {
- Object hl = chunk.items[1];
- if (hl.type == kObjectTypeArray) {
- Array arr = hl.data.array;
- for (size_t j = 0; j < arr.size; j++) {
- hl_id = object_to_hl_id(arr.items[j], "virt_text highlight", err);
- if (ERROR_SET(err)) {
- goto free_exit;
- }
- if (j < arr.size-1) {
- kv_push(virt_text, ((VirtTextChunk){ .text = NULL,
- .hl_id = hl_id }));
- }
- }
- } else {
- hl_id = object_to_hl_id(hl, "virt_text highlight", err);
- if (ERROR_SET(err)) {
- goto free_exit;
- }
- }
- }
-
- char *text = transstr(str.size > 0 ? str.data : "", false); // allocates
- w += (int)mb_string2cells((char_u *)text);
-
- kv_push(virt_text, ((VirtTextChunk){ .text = text, .hl_id = hl_id }));
- }
-
- *width = w;
- return virt_text;
-
-free_exit:
- clear_virttext(&virt_text);
- return virt_text;
-}
-
/// Force obj to bool.
/// If it fails, returns false and sets err
/// @param obj The object to coerce to a boolean
@@ -1253,7 +817,7 @@ int object_to_hl_id(Object obj, const char *what, Error *err)
{
if (obj.type == kObjectTypeString) {
String str = obj.data.string;
- return str.size ? syn_check_group(str.data, (int)str.size) : 0;
+ return str.size ? syn_check_group(str.data, str.size) : 0;
} else if (obj.type == kObjectTypeInteger) {
return MAX((int)obj.data.integer, 0);
} else {
@@ -1287,7 +851,7 @@ HlMessage parse_hl_msg(Array chunks, Error *err)
String hl = chunk.items[1].data.string;
if (hl.size > 0) {
// TODO(bfredl): use object_to_hl_id and allow integer
- int hl_id = syn_check_group(hl.data, (int)hl.size);
+ int hl_id = syn_check_group(hl.data, hl.size);
attr = hl_id > 0 ? syn_id2attr(hl_id) : 0;
}
}
@@ -1297,8 +861,8 @@ HlMessage parse_hl_msg(Array chunks, Error *err)
return hl_msg;
free_exit:
- clear_hl_msg(&hl_msg);
- return hl_msg;
+ hl_msg_free(hl_msg);
+ return (HlMessage)KV_INITIAL_VALUE;
}
bool api_dict_to_keydict(void *rv, field_hash hashy, Dictionary dict, Error *err)
@@ -1350,8 +914,9 @@ bool set_mark(buf_T *buf, String name, Integer line, Integer col, Error *err)
return res;
}
}
- pos_T pos = { line, (int)col, (int)col };
- res = setmark_pos(*name.data, &pos, buf->handle);
+ assert(INT32_MIN <= line && line <= INT32_MAX);
+ pos_T pos = { (linenr_T)line, (int)col, (int)col };
+ res = setmark_pos(*name.data, &pos, buf->handle, NULL);
if (!res) {
if (deleting) {
api_set_error(err, kErrorTypeException,
@@ -1365,199 +930,43 @@ bool set_mark(buf_T *buf, String name, Integer line, Integer col, Error *err)
}
/// Get default statusline highlight for window
-const char *get_default_stl_hl(win_T *wp)
+const char *get_default_stl_hl(win_T *wp, bool use_winbar)
{
if (wp == NULL) {
return "TabLineFill";
- } else if (wp == curwin) {
- return "StatusLine";
+ } else if (use_winbar) {
+ return (wp == curwin) ? "WinBar" : "WinBarNC";
} else {
- return "StatusLineNC";
+ return (wp == curwin) ? "StatusLine" : "StatusLineNC";
}
}
-void add_user_command(String name, Object command, Dict(user_command) *opts, int flags, Error *err)
+int find_sid(uint64_t channel_id)
{
- uint32_t argt = 0;
- long def = -1;
- cmd_addr_T addr_type_arg = ADDR_NONE;
- int compl = EXPAND_NOTHING;
- char *compl_arg = NULL;
- char *rep = NULL;
- LuaRef luaref = LUA_NOREF;
- LuaRef compl_luaref = LUA_NOREF;
-
- if (mb_islower(name.data[0])) {
- api_set_error(err, kErrorTypeValidation, "'name' must begin with an uppercase letter");
- goto err;
- }
-
- if (HAS_KEY(opts->range) && HAS_KEY(opts->count)) {
- api_set_error(err, kErrorTypeValidation, "'range' and 'count' are mutually exclusive");
- goto err;
- }
-
- if (opts->nargs.type == kObjectTypeInteger) {
- switch (opts->nargs.data.integer) {
- case 0:
- // Default value, nothing to do
- break;
- case 1:
- argt |= EX_EXTRA | EX_NOSPC | EX_NEEDARG;
- break;
- default:
- api_set_error(err, kErrorTypeValidation, "Invalid value for 'nargs'");
- goto err;
- }
- } else if (opts->nargs.type == kObjectTypeString) {
- if (opts->nargs.data.string.size > 1) {
- api_set_error(err, kErrorTypeValidation, "Invalid value for 'nargs'");
- goto err;
- }
-
- switch (opts->nargs.data.string.data[0]) {
- case '*':
- argt |= EX_EXTRA;
- break;
- case '?':
- argt |= EX_EXTRA | EX_NOSPC;
- break;
- case '+':
- argt |= EX_EXTRA | EX_NEEDARG;
- break;
- default:
- api_set_error(err, kErrorTypeValidation, "Invalid value for 'nargs'");
- goto err;
- }
- } else if (HAS_KEY(opts->nargs)) {
- api_set_error(err, kErrorTypeValidation, "Invalid value for 'nargs'");
- goto err;
- }
-
- if (HAS_KEY(opts->complete) && !argt) {
- api_set_error(err, kErrorTypeValidation, "'complete' used without 'nargs'");
- goto err;
- }
-
- if (opts->range.type == kObjectTypeBoolean) {
- if (opts->range.data.boolean) {
- argt |= EX_RANGE;
- addr_type_arg = ADDR_LINES;
- }
- } else if (opts->range.type == kObjectTypeString) {
- if (opts->range.data.string.data[0] == '%' && opts->range.data.string.size == 1) {
- argt |= EX_RANGE | EX_DFLALL;
- addr_type_arg = ADDR_LINES;
- } else {
- api_set_error(err, kErrorTypeValidation, "Invalid value for 'range'");
- goto err;
- }
- } else if (opts->range.type == kObjectTypeInteger) {
- argt |= EX_RANGE | EX_ZEROR;
- def = opts->range.data.integer;
- addr_type_arg = ADDR_LINES;
- } else if (HAS_KEY(opts->range)) {
- api_set_error(err, kErrorTypeValidation, "Invalid value for 'range'");
- goto err;
- }
-
- if (opts->count.type == kObjectTypeBoolean) {
- if (opts->count.data.boolean) {
- argt |= EX_COUNT | EX_ZEROR | EX_RANGE;
- addr_type_arg = ADDR_OTHER;
- def = 0;
- }
- } else if (opts->count.type == kObjectTypeInteger) {
- argt |= EX_COUNT | EX_ZEROR | EX_RANGE;
- addr_type_arg = ADDR_OTHER;
- def = opts->count.data.integer;
- } else if (HAS_KEY(opts->count)) {
- api_set_error(err, kErrorTypeValidation, "Invalid value for 'count'");
- goto err;
- }
-
- if (opts->addr.type == kObjectTypeString) {
- if (parse_addr_type_arg((char_u *)opts->addr.data.string.data, (int)opts->addr.data.string.size,
- &addr_type_arg) != OK) {
- api_set_error(err, kErrorTypeValidation, "Invalid value for 'addr'");
- goto err;
- }
-
- if (addr_type_arg != ADDR_LINES) {
- argt |= EX_ZEROR;
- }
- } else if (HAS_KEY(opts->addr)) {
- api_set_error(err, kErrorTypeValidation, "Invalid value for 'addr'");
- goto err;
- }
-
- if (api_object_to_bool(opts->bang, "bang", false, err)) {
- argt |= EX_BANG;
- } else if (ERROR_SET(err)) {
- goto err;
- }
-
- if (api_object_to_bool(opts->bar, "bar", false, err)) {
- argt |= EX_TRLBAR;
- } else if (ERROR_SET(err)) {
- goto err;
- }
-
-
- if (api_object_to_bool(opts->register_, "register", false, err)) {
- argt |= EX_REGSTR;
- } else if (ERROR_SET(err)) {
- goto err;
- }
-
- bool force = api_object_to_bool(opts->force, "force", true, err);
- if (ERROR_SET(err)) {
- goto err;
- }
-
- if (opts->complete.type == kObjectTypeLuaRef) {
- compl = EXPAND_USER_LUA;
- compl_luaref = api_new_luaref(opts->complete.data.luaref);
- } else if (opts->complete.type == kObjectTypeString) {
- if (parse_compl_arg((char_u *)opts->complete.data.string.data,
- (int)opts->complete.data.string.size, &compl, &argt,
- (char_u **)&compl_arg) != OK) {
- api_set_error(err, kErrorTypeValidation, "Invalid value for 'complete'");
- goto err;
- }
- } else if (HAS_KEY(opts->complete)) {
- api_set_error(err, kErrorTypeValidation, "Invalid value for 'complete'");
- goto err;
- }
-
- switch (command.type) {
- case kObjectTypeLuaRef:
- luaref = api_new_luaref(command.data.luaref);
- if (opts->desc.type == kObjectTypeString) {
- rep = opts->desc.data.string.data;
- } else {
- snprintf((char *)IObuff, IOSIZE, "<Lua function %d>", luaref);
- rep = (char *)IObuff;
- }
- break;
- case kObjectTypeString:
- rep = command.data.string.data;
- break;
+ switch (channel_id) {
+ case VIML_INTERNAL_CALL:
+ // TODO(autocmd): Figure out what this should be
+ // return SID_API_CLIENT;
+ case LUA_INTERNAL_CALL:
+ return SID_LUA;
default:
- api_set_error(err, kErrorTypeValidation, "'command' must be a string or Lua function");
- goto err;
- }
-
- if (uc_add_command((char_u *)name.data, name.size, (char_u *)rep, argt, def, flags,
- compl, (char_u *)compl_arg, compl_luaref, addr_type_arg, luaref,
- force) != OK) {
- api_set_error(err, kErrorTypeException, "Failed to create user command");
- goto err;
+ return SID_API_CLIENT;
}
+}
- return;
-
-err:
- NLUA_CLEAR_REF(luaref);
- NLUA_CLEAR_REF(compl_luaref);
+/// Sets sctx for API calls.
+///
+/// @param channel_id api clients id. Used to determine if it's a internal
+/// call or a rpc call.
+/// @return returns previous value of current_sctx. To be used
+/// to be used for restoring sctx to previous state.
+sctx_T api_set_sctx(uint64_t channel_id)
+{
+ sctx_T old_current_sctx = current_sctx;
+ if (channel_id != VIML_INTERNAL_CALL) {
+ current_sctx.sc_sid =
+ channel_id == LUA_INTERNAL_CALL ? SID_LUA : SID_API_CLIENT;
+ current_sctx.sc_lnum = 0;
+ }
+ return old_current_sctx;
}