diff options
Diffstat (limited to 'src/nvim/api')
-rw-r--r-- | src/nvim/api/deprecated.c | 11 | ||||
-rw-r--r-- | src/nvim/api/extmark.c | 162 | ||||
-rw-r--r-- | src/nvim/api/keysets.lua | 2 | ||||
-rw-r--r-- | src/nvim/api/private/converter.c | 21 | ||||
-rw-r--r-- | src/nvim/api/private/helpers.c | 13 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 25 |
6 files changed, 162 insertions, 72 deletions
diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c index 76b699800e..18243fec2b 100644 --- a/src/nvim/api/deprecated.c +++ b/src/nvim/api/deprecated.c @@ -130,7 +130,7 @@ Integer nvim_buf_set_virtual_text(Buffer buffer, Integer src_id, Integer line, A return 0; } - uint64_t ns_id = src2ns(&src_id); + uint32_t ns_id = src2ns(&src_id); int width; VirtText virt_text = parse_virt_text(chunks, err, &width); @@ -148,11 +148,12 @@ Integer nvim_buf_set_virtual_text(Buffer buffer, Integer src_id, Integer line, A return src_id; } - Decoration *decor = xcalloc(1, sizeof(*decor)); - decor->virt_text = virt_text; - decor->virt_text_width = width; + Decoration decor = DECORATION_INIT; + decor.virt_text = virt_text; + decor.virt_text_width = width; + decor.priority = 0; - extmark_set(buf, ns_id, NULL, (int)line, 0, -1, -1, decor, true, + extmark_set(buf, ns_id, NULL, (int)line, 0, -1, -1, &decor, true, false, kExtmarkNoUndo); return src_id; } diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index 742b953c2a..3a968f07ab 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -85,12 +85,12 @@ const char *describe_ns(NS ns_id) } // Is the Namespace in use? -static bool ns_initialized(uint64_t ns) +static bool ns_initialized(uint32_t ns) { if (ns < 1) { return false; } - return ns < (uint64_t)next_namespace_id; + return ns < (uint32_t)next_namespace_id; } @@ -106,22 +106,55 @@ static Array extmark_to_array(ExtmarkInfo extmark, bool id, bool add_dict) if (add_dict) { Dictionary dict = ARRAY_DICT_INIT; + PUT(dict, "right_gravity", BOOLEAN_OBJ(extmark.right_gravity)); + if (extmark.end_row >= 0) { PUT(dict, "end_row", INTEGER_OBJ(extmark.end_row)); PUT(dict, "end_col", INTEGER_OBJ(extmark.end_col)); + PUT(dict, "end_right_gravity", BOOLEAN_OBJ(extmark.end_right_gravity)); } - if (extmark.decor) { - Decoration *decor = extmark.decor; - if (decor->hl_id) { - String name = cstr_to_string((const char *)syn_id2name(decor->hl_id)); - PUT(dict, "hl_group", STRING_OBJ(name)); + Decoration *decor = &extmark.decor; + if (decor->hl_id) { + String name = cstr_to_string((const char *)syn_id2name(decor->hl_id)); + PUT(dict, "hl_group", STRING_OBJ(name)); + PUT(dict, "hl_eol", BOOLEAN_OBJ(decor->hl_eol)); + } + if (decor->hl_mode) { + PUT(dict, "hl_mode", STRING_OBJ(cstr_to_string(hl_mode_str[decor->hl_mode]))); + } + + if (kv_size(decor->virt_text)) { + Array chunks = ARRAY_DICT_INIT; + for (size_t i = 0; i < decor->virt_text.size; i++) { + Array chunk = ARRAY_DICT_INIT; + VirtTextChunk *vtc = &decor->virt_text.items[i]; + ADD(chunk, STRING_OBJ(cstr_to_string(vtc->text))); + if (vtc->hl_id > 0) { + ADD(chunk, + STRING_OBJ(cstr_to_string((const char *)syn_id2name(vtc->hl_id)))); + } + ADD(chunks, ARRAY_OBJ(chunk)); } - if (kv_size(decor->virt_text)) { + PUT(dict, "virt_text", ARRAY_OBJ(chunks)); + PUT(dict, "virt_text_hide", BOOLEAN_OBJ(decor->virt_text_hide)); + if (decor->virt_text_pos == kVTWinCol) { + PUT(dict, "virt_text_win_col", INTEGER_OBJ(decor->col)); + } + PUT(dict, "virt_text_pos", + STRING_OBJ(cstr_to_string(virt_text_pos_str[decor->virt_text_pos]))); + } + + if (kv_size(decor->virt_lines)) { + Array all_chunks = ARRAY_DICT_INIT; + bool virt_lines_leftcol = false; + for (size_t i = 0; i < decor->virt_lines.size; i++) { Array chunks = ARRAY_DICT_INIT; - for (size_t i = 0; i < decor->virt_text.size; i++) { + VirtText *vt = &decor->virt_lines.items[i].line; + virt_lines_leftcol = decor->virt_lines.items[i].left_col; + for (size_t j = 0; j < vt->size; j++) { Array chunk = ARRAY_DICT_INIT; - VirtTextChunk *vtc = &decor->virt_text.items[i]; + VirtTextChunk *vtc = &vt->items[j]; ADD(chunk, STRING_OBJ(cstr_to_string(vtc->text))); if (vtc->hl_id > 0) { ADD(chunk, @@ -129,9 +162,14 @@ static Array extmark_to_array(ExtmarkInfo extmark, bool id, bool add_dict) } ADD(chunks, ARRAY_OBJ(chunk)); } - PUT(dict, "virt_text", ARRAY_OBJ(chunks)); + ADD(all_chunks, ARRAY_OBJ(chunks)); } + PUT(dict, "virt_lines", ARRAY_OBJ(all_chunks)); + PUT(dict, "virt_lines_above", BOOLEAN_OBJ(decor->virt_lines_above)); + PUT(dict, "virt_lines_leftcol", BOOLEAN_OBJ(virt_lines_leftcol)); + } + if (decor->hl_id || kv_size(decor->virt_text)) { PUT(dict, "priority", INTEGER_OBJ(decor->priority)); } @@ -166,7 +204,7 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, return rv; } - if (!ns_initialized((uint64_t)ns_id)) { + if (!ns_initialized((uint32_t)ns_id)) { api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); return rv; } @@ -191,7 +229,7 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, } - ExtmarkInfo extmark = extmark_from_id(buf, (uint64_t)ns_id, (uint64_t)id); + ExtmarkInfo extmark = extmark_from_id(buf, (uint32_t)ns_id, (uint32_t)id); if (extmark.row < 0) { return rv; } @@ -252,7 +290,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e return rv; } - if (!ns_initialized((uint64_t)ns_id)) { + if (!ns_initialized((uint32_t)ns_id)) { api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); return rv; } @@ -310,7 +348,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e } - ExtmarkInfoArray marks = extmark_get(buf, (uint64_t)ns_id, l_row, l_col, + ExtmarkInfoArray marks = extmark_get(buf, (uint32_t)ns_id, l_row, l_col, u_row, u_col, (int64_t)limit, reverse); for (size_t i = 0; i < kv_size(marks); i++) { @@ -404,6 +442,10 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e /// for left). Defaults to false. /// - priority: a priority value for the highlight group. For /// example treesitter highlighting uses a value of 100. +/// - strict: boolean that indicates extmark should not be placed +/// if the line or column value is past the end of the +/// buffer or end of the line respectively. Defaults to true. +/// /// @param[out] err Error details, if any /// @return Id of the created/updated extmark Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer col, @@ -417,14 +459,14 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer goto error; } - if (!ns_initialized((uint64_t)ns_id)) { + if (!ns_initialized((uint32_t)ns_id)) { api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); goto error; } - uint64_t id = 0; + uint32_t id = 0; if (opts->id.type == kObjectTypeInteger && opts->id.data.integer > 0) { - id = (uint64_t)opts->id.data.integer; + id = (uint32_t)opts->id.data.integer; } else if (HAS_KEY(opts->id)) { api_set_error(err, kErrorTypeValidation, "id is not a positive integer"); goto error; @@ -441,9 +483,18 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer opts->end_row = opts->end_line; } +#define OPTION_TO_BOOL(target, name, val) \ + target = api_object_to_bool(opts->name, #name, val, err); \ + if (ERROR_SET(err)) { \ + goto error; \ + } + + bool strict = true; + OPTION_TO_BOOL(strict, strict, true); + if (opts->end_row.type == kObjectTypeInteger) { Integer val = opts->end_row.data.integer; - if (val < 0 || val > buf->b_ml.ml_line_count) { + if (val < 0 || (val > buf->b_ml.ml_line_count && strict)) { api_set_error(err, kErrorTypeValidation, "end_row value outside range"); goto error; } else { @@ -512,12 +563,6 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer goto error; } -#define OPTION_TO_BOOL(target, name, val) \ - target = api_object_to_bool(opts->name, #name, val, err); \ - if (ERROR_SET(err)) { \ - goto error; \ - } - OPTION_TO_BOOL(decor.virt_text_hide, virt_text_hide, false); OPTION_TO_BOOL(decor.hl_eol, hl_eol, false); @@ -596,16 +641,30 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer bool ephemeral = false; OPTION_TO_BOOL(ephemeral, ephemeral, false); - if (line < 0 || line > buf->b_ml.ml_line_count) { + if (line < 0) { api_set_error(err, kErrorTypeValidation, "line value outside range"); goto error; + } else if (line > buf->b_ml.ml_line_count) { + if (strict) { + api_set_error(err, kErrorTypeValidation, "line value outside range"); + goto error; + } else { + line = buf->b_ml.ml_line_count; + } } else if (line < buf->b_ml.ml_line_count) { len = ephemeral ? MAXCOL : STRLEN(ml_get_buf(buf, (linenr_T)line+1, false)); } if (col == -1) { col = (Integer)len; - } else if (col < -1 || col > (Integer)len) { + } else if (col > (Integer)len) { + if (strict) { + api_set_error(err, kErrorTypeValidation, "col value outside range"); + goto error; + } else { + col = (Integer)len; + } + } else if (col < -1) { api_set_error(err, kErrorTypeValidation, "col value outside range"); goto error; } @@ -621,27 +680,17 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer line2 = (int)line; } if (col2 > (Integer)len) { - api_set_error(err, kErrorTypeValidation, "end_col value outside range"); - goto error; + if (strict) { + api_set_error(err, kErrorTypeValidation, "end_col value outside range"); + goto error; + } else { + col2 = (int)len; + } } } else if (line2 >= 0) { col2 = 0; } - Decoration *d = NULL; - - if (ephemeral) { - d = &decor; - } else if (kv_size(decor.virt_text) || kv_size(decor.virt_lines) - || decor.priority != DECOR_PRIORITY_BASE - || decor.hl_eol) { - // TODO(bfredl): this is a bit sketchy. eventually we should - // have predefined decorations for both marks/ephemerals - d = xcalloc(1, sizeof(*d)); - *d = decor; - } else if (decor.hl_id) { - d = decor_hl(decor.hl_id); - } // TODO(bfredl): synergize these two branches even more if (ephemeral && decor_state.buf == buf) { @@ -652,12 +701,8 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer goto error; } - extmark_set(buf, (uint64_t)ns_id, &id, (int)line, (colnr_T)col, line2, col2, - d, right_gravity, end_right_gravity, kExtmarkNoUndo); - - if (kv_size(decor.virt_lines)) { - redraw_buf_line_later(buf, MIN(buf->b_ml.ml_line_count, line+1+(decor.virt_lines_above?0:1))); - } + extmark_set(buf, (uint32_t)ns_id, &id, (int)line, (colnr_T)col, line2, col2, + &decor, right_gravity, end_right_gravity, kExtmarkNoUndo); } return (Integer)id; @@ -682,23 +727,23 @@ Boolean nvim_buf_del_extmark(Buffer buffer, Integer ns_id, Integer id, Error *er if (!buf) { return false; } - if (!ns_initialized((uint64_t)ns_id)) { + if (!ns_initialized((uint32_t)ns_id)) { api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); return false; } - return extmark_del(buf, (uint64_t)ns_id, (uint64_t)id); + return extmark_del(buf, (uint32_t)ns_id, (uint32_t)id); } -uint64_t src2ns(Integer *src_id) +uint32_t src2ns(Integer *src_id) { if (*src_id == 0) { *src_id = nvim_create_namespace((String)STRING_INIT); } if (*src_id < 0) { - return UINT64_MAX; + return (((uint32_t)1) << 31) - 1; } else { - return (uint64_t)(*src_id); + return (uint32_t)(*src_id); } } @@ -753,7 +798,7 @@ Integer nvim_buf_add_highlight(Buffer buffer, Integer ns_id, String hl_group, In col_end = MAXCOL; } - uint64_t ns = src2ns(&ns_id); + uint32_t ns = src2ns(&ns_id); if (!(line < buf->b_ml.ml_line_count)) { // safety check, we can't add marks outside the range @@ -773,10 +818,13 @@ Integer nvim_buf_add_highlight(Buffer buffer, Integer ns_id, String hl_group, In end_line++; } + Decoration decor = DECORATION_INIT; + decor.hl_id = hl_id; + extmark_set(buf, ns, NULL, (int)line, (colnr_T)col_start, end_line, (colnr_T)col_end, - decor_hl(hl_id), true, false, kExtmarkNoUndo); + &decor, true, false, kExtmarkNoUndo); return ns_id; } @@ -808,7 +856,7 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start, if (line_end < 0 || line_end > MAXLNUM) { line_end = MAXLNUM; } - extmark_clear(buf, (ns_id < 0 ? 0 : (uint64_t)ns_id), + extmark_clear(buf, (ns_id < 0 ? 0 : (uint32_t)ns_id), (int)line_start, 0, (int)line_end-1, MAXCOL); } diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua index 97ee885ff6..7d521bbf25 100644 --- a/src/nvim/api/keysets.lua +++ b/src/nvim/api/keysets.lua @@ -21,6 +21,7 @@ return { "virt_lines"; "virt_lines_above"; "virt_lines_leftcol"; + "strict"; }; keymap = { "noremap"; @@ -43,6 +44,7 @@ return { "count"; "desc"; "force"; + "keepscript"; "nargs"; "range"; "register"; diff --git a/src/nvim/api/private/converter.c b/src/nvim/api/private/converter.c index 36da6c13a9..3d4ff202fe 100644 --- a/src/nvim/api/private/converter.c +++ b/src/nvim/api/private/converter.c @@ -10,6 +10,9 @@ #include "nvim/api/private/helpers.h" #include "nvim/assert.h" #include "nvim/eval/typval.h" +#include "nvim/eval/userfunc.h" +#include "nvim/lua/converter.h" +#include "nvim/lua/executor.h" /// Helper structure for vim_to_object typedef struct { @@ -228,6 +231,14 @@ static inline void typval_encode_dict_end(EncodedData *const edata) /// @return The converted value Object vim_to_object(typval_T *obj) { + if (obj->v_type == VAR_FUNC) { + ufunc_T *fp = find_func(obj->vval.v_string); + assert(fp != NULL); + if (fp->uf_cb == nlua_CFunction_func_call) { + LuaRef ref = api_new_luaref(((LuaCFunctionState *)fp->uf_cb_state)->lua_callable.func_ref); + return LUAREF_OBJ(ref); + } + } EncodedData edata; kvi_init(edata.stack); const int evo_ret = encode_vim_to_object(&edata, obj, @@ -340,6 +351,16 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err) tv->vval.v_dict = dict; break; } + + case kObjectTypeLuaRef: { + LuaCFunctionState *state = xmalloc(sizeof(LuaCFunctionState)); + state->lua_callable.func_ref = api_new_luaref(obj.data.luaref); + char_u *name = register_cfunc(&nlua_CFunction_func_call, &nlua_CFunction_func_free, state); + tv->v_type = VAR_FUNC; + tv->vval.v_string = vim_strsave(name); + break; + } + default: abort(); } diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 38a82343c3..f540f8f7ee 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -1141,7 +1141,7 @@ bool extmark_get_index_from_obj(buf_T *buf, Integer ns_id, Object obj, int return false; } - ExtmarkInfo extmark = extmark_from_id(buf, (uint64_t)ns_id, (uint64_t)id); + ExtmarkInfo extmark = extmark_from_id(buf, (uint32_t)ns_id, (uint32_t)id); if (extmark.row >= 0) { *row = extmark.row; *col = extmark.col; @@ -1387,6 +1387,11 @@ void add_user_command(String name, Object command, Dict(user_command) *opts, int 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; @@ -1505,6 +1510,12 @@ void add_user_command(String name, Object command, Dict(user_command) *opts, int goto err; } + if (api_object_to_bool(opts->keepscript, "keepscript", false, err)) { + argt |= EX_KEEPSCRIPT; + } else if (ERROR_SET(err)) { + goto err; + } + bool force = api_object_to_bool(opts->force, "force", true, err); if (ERROR_SET(err)) { goto err; diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 59db12f2c0..7c194935ce 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -187,21 +187,23 @@ static void on_redraw_event(void **argv) /// On execution error: does not fail, but updates v:errmsg. /// /// To input sequences like <C-o> use |nvim_replace_termcodes()| (typically -/// with escape_csi=true) to replace |keycodes|, then pass the result to +/// with escape_ks=false) to replace |keycodes|, then pass the result to /// nvim_feedkeys(). /// /// Example: /// <pre> /// :let key = nvim_replace_termcodes("<C-o>", v:true, v:false, v:true) -/// :call nvim_feedkeys(key, 'n', v:true) +/// :call nvim_feedkeys(key, 'n', v:false) /// </pre> /// /// @param keys to be typed /// @param mode behavior flags, see |feedkeys()| -/// @param escape_csi If true, escape K_SPECIAL/CSI bytes in `keys` +/// @param escape_ks If true, escape K_SPECIAL bytes in `keys` +/// This should be false if you already used +/// |nvim_replace_termcodes()|, and true otherwise. /// @see feedkeys() -/// @see vim_strsave_escape_csi -void nvim_feedkeys(String keys, String mode, Boolean escape_csi) +/// @see vim_strsave_escape_ks +void nvim_feedkeys(String keys, String mode, Boolean escape_ks) FUNC_API_SINCE(1) { bool remap = true; @@ -232,10 +234,10 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi) } char *keys_esc; - if (escape_csi) { - // Need to escape K_SPECIAL and CSI before putting the string in the + if (escape_ks) { + // Need to escape K_SPECIAL before putting the string in the // typeahead buffer. - keys_esc = (char *)vim_strsave_escape_csi((char_u *)keys.data); + keys_esc = (char *)vim_strsave_escape_ks((char_u *)keys.data); } else { keys_esc = keys.data; } @@ -245,7 +247,7 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi) typebuf_was_filled = true; } - if (escape_csi) { + if (escape_ks) { xfree(keys_esc); } @@ -2281,6 +2283,11 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * fillchar = ' '; } else { wp = find_window_by_handle(window, err); + + if (wp == NULL) { + api_set_error(err, kErrorTypeException, "unknown winid %d", window); + return result; + } ewp = wp; if (fillchar == 0) { |