neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

deprecated.c (32402B)


      1 // Island of misfit toys.
      2 
      3 #include <stdbool.h>
      4 #include <stdint.h>
      5 #include <string.h>
      6 
      7 #include "nvim/api/buffer.h"
      8 #include "nvim/api/deprecated.h"
      9 #include "nvim/api/extmark.h"
     10 #include "nvim/api/keysets_defs.h"
     11 #include "nvim/api/private/defs.h"
     12 #include "nvim/api/private/dispatch.h"
     13 #include "nvim/api/private/helpers.h"
     14 #include "nvim/api/private/validate.h"
     15 #include "nvim/api/vimscript.h"
     16 #include "nvim/buffer_defs.h"
     17 #include "nvim/decoration.h"
     18 #include "nvim/decoration_defs.h"
     19 #include "nvim/eval/vars.h"
     20 #include "nvim/extmark.h"
     21 #include "nvim/globals.h"
     22 #include "nvim/highlight.h"
     23 #include "nvim/highlight_group.h"
     24 #include "nvim/lua/executor.h"
     25 #include "nvim/marktree.h"
     26 #include "nvim/memory.h"
     27 #include "nvim/memory_defs.h"
     28 #include "nvim/message.h"
     29 #include "nvim/option.h"
     30 #include "nvim/option_defs.h"
     31 #include "nvim/pos_defs.h"
     32 #include "nvim/strings.h"
     33 #include "nvim/types_defs.h"
     34 
     35 #include "api/deprecated.c.generated.h"
     36 
     37 /// @deprecated Use nvim_exec2() instead.
     38 /// @see nvim_exec2
     39 String nvim_exec(uint64_t channel_id, String src, Boolean output, Error *err)
     40  FUNC_API_SINCE(7) FUNC_API_DEPRECATED_SINCE(11)
     41  FUNC_API_RET_ALLOC
     42 {
     43  Dict(exec_opts) opts = { .output = output };
     44  return exec_impl(channel_id, src, &opts, err);
     45 }
     46 
     47 /// @deprecated
     48 /// @see nvim_exec2
     49 String nvim_command_output(uint64_t channel_id, String command, Error *err)
     50  FUNC_API_SINCE(1) FUNC_API_DEPRECATED_SINCE(7)
     51  FUNC_API_RET_ALLOC
     52 {
     53  Dict(exec_opts) opts = { .output = true };
     54  return exec_impl(channel_id, command, &opts, err);
     55 }
     56 
     57 /// @deprecated Use nvim_exec_lua() instead.
     58 /// @see nvim_exec_lua
     59 Object nvim_execute_lua(String code, Array args, Arena *arena, Error *err)
     60  FUNC_API_SINCE(3)
     61  FUNC_API_DEPRECATED_SINCE(7)
     62  FUNC_API_REMOTE_ONLY
     63 {
     64  return nlua_exec(code, NULL, args, kRetObject, arena, err);
     65 }
     66 
     67 /// Gets the buffer number
     68 ///
     69 /// @deprecated The buffer number now is equal to the object id
     70 ///
     71 /// @param buffer     Buffer id, or 0 for current buffer
     72 /// @param[out] err   Error details, if any
     73 /// @return Buffer number
     74 Integer nvim_buf_get_number(Buffer buffer, Error *err)
     75  FUNC_API_SINCE(1)
     76  FUNC_API_DEPRECATED_SINCE(2)
     77 {
     78  buf_T *buf = find_buffer_by_handle(buffer, err);
     79 
     80  if (!buf) {
     81    return 0;
     82  }
     83 
     84  return buf->b_fnum;
     85 }
     86 
     87 static uint32_t src2ns(Integer *src_id)
     88 {
     89  if (*src_id == 0) {
     90    *src_id = nvim_create_namespace((String)STRING_INIT);
     91  }
     92  if (*src_id < 0) {
     93    return (((uint32_t)1) << 31) - 1;
     94  }
     95  return (uint32_t)(*src_id);
     96 }
     97 
     98 /// Clears highlights and virtual text from namespace and range of lines
     99 ///
    100 /// @deprecated use |nvim_buf_clear_namespace()|.
    101 ///
    102 /// @param buffer     Buffer id, or 0 for current buffer
    103 /// @param ns_id      Namespace to clear, or -1 to clear all.
    104 /// @param line_start Start of range of lines to clear
    105 /// @param line_end   End of range of lines to clear (exclusive) or -1 to clear
    106 ///                   to end of file.
    107 /// @param[out] err   Error details, if any
    108 void nvim_buf_clear_highlight(Buffer buffer, Integer ns_id, Integer line_start, Integer line_end,
    109                              Error *err)
    110  FUNC_API_SINCE(1)
    111  FUNC_API_DEPRECATED_SINCE(7)
    112 {
    113  nvim_buf_clear_namespace(buffer, ns_id, line_start, line_end, err);
    114 }
    115 
    116 /// Adds a highlight to buffer.
    117 ///
    118 /// @deprecated use |nvim_buf_set_extmark()| or |vim.hl.range()|
    119 ///
    120 /// Namespaces are used for batch deletion/updating of a set of highlights. To
    121 /// create a namespace, use |nvim_create_namespace()| which returns a namespace
    122 /// id. Pass it in to this function as `ns_id` to add highlights to the
    123 /// namespace. All highlights in the same namespace can then be cleared with
    124 /// single call to |nvim_buf_clear_namespace()|. If the highlight never will be
    125 /// deleted by an API call, pass `ns_id = -1`.
    126 ///
    127 /// As a shorthand, `ns_id = 0` can be used to create a new namespace for the
    128 /// highlight, the allocated id is then returned. If `hl_group` is the empty
    129 /// string no highlight is added, but a new `ns_id` is still returned. This is
    130 /// supported for backwards compatibility, new code should use
    131 /// |nvim_create_namespace()| to create a new empty namespace.
    132 ///
    133 /// @param buffer     Buffer id, or 0 for current buffer
    134 /// @param ns_id      namespace to use or -1 for ungrouped highlight
    135 /// @param hl_group   Name of the highlight group to use
    136 /// @param line       Line to highlight (zero-indexed)
    137 /// @param col_start  Start of (byte-indexed) column range to highlight
    138 /// @param col_end    End of (byte-indexed) column range to highlight,
    139 ///                   or -1 to highlight to end of line
    140 /// @param[out] err   Error details, if any
    141 /// @return The ns_id that was used
    142 Integer nvim_buf_add_highlight(Buffer buffer, Integer ns_id, String hl_group, Integer line,
    143                               Integer col_start, Integer col_end, Error *err)
    144  FUNC_API_SINCE(1)
    145  FUNC_API_DEPRECATED_SINCE(13)
    146 {
    147  buf_T *buf = find_buffer_by_handle(buffer, err);
    148  if (!buf) {
    149    return 0;
    150  }
    151 
    152  VALIDATE_RANGE((line >= 0 && line < MAXLNUM), "line number", {
    153    return 0;
    154  });
    155  VALIDATE_RANGE((col_start >= 0 && col_start <= MAXCOL), "column", {
    156    return 0;
    157  });
    158 
    159  if (col_end < 0 || col_end > MAXCOL) {
    160    col_end = MAXCOL;
    161  }
    162 
    163  uint32_t ns = src2ns(&ns_id);
    164 
    165  if (!(line < buf->b_ml.ml_line_count)) {
    166    // safety check, we can't add marks outside the range
    167    return ns_id;
    168  }
    169 
    170  int hl_id = 0;
    171  if (hl_group.size > 0) {
    172    hl_id = syn_check_group(hl_group.data, hl_group.size);
    173  } else {
    174    return ns_id;
    175  }
    176 
    177  int end_line = (int)line;
    178  if (col_end == MAXCOL) {
    179    col_end = 0;
    180    end_line++;
    181  }
    182 
    183  DecorInline decor = DECOR_INLINE_INIT;
    184  decor.data.hl.hl_id = hl_id;
    185 
    186  extmark_set(buf, ns, NULL, (int)line, (colnr_T)col_start, end_line, (colnr_T)col_end,
    187              decor, MT_FLAG_DECOR_HL, true, false, false, false, NULL);
    188  return ns_id;
    189 }
    190 /// Set the virtual text (annotation) for a buffer line.
    191 ///
    192 /// @deprecated use nvim_buf_set_extmark to use full virtual text functionality.
    193 ///
    194 /// The text will be placed after the buffer text. Virtual text will never
    195 /// cause reflow, rather virtual text will be truncated at the end of the screen
    196 /// line. The virtual text will begin one cell (|lcs-eol| or space) after the
    197 /// ordinary text.
    198 ///
    199 /// Namespaces are used to support batch deletion/updating of virtual text.
    200 /// To create a namespace, use |nvim_create_namespace()|. Virtual text is
    201 /// cleared using |nvim_buf_clear_namespace()|. The same `ns_id` can be used for
    202 /// both virtual text and highlights added by |nvim_buf_add_highlight()|, both
    203 /// can then be cleared with a single call to |nvim_buf_clear_namespace()|. If
    204 /// the virtual text never will be cleared by an API call, pass `ns_id = -1`.
    205 ///
    206 /// As a shorthand, `ns_id = 0` can be used to create a new namespace for the
    207 /// virtual text, the allocated id is then returned.
    208 ///
    209 /// @param buffer     Buffer id, or 0 for current buffer
    210 /// @param src_id     Namespace to use or 0 to create a namespace,
    211 ///                   or -1 for a ungrouped annotation
    212 /// @param line       Line to annotate with virtual text (zero-indexed)
    213 /// @param chunks     A list of [text, hl_group] arrays, each representing a
    214 ///                   text chunk with specified highlight. `hl_group` element
    215 ///                   can be omitted for no highlight.
    216 /// @param opts       Optional parameters. Currently not used.
    217 /// @param[out] err   Error details, if any
    218 /// @return The ns_id that was used
    219 Integer nvim_buf_set_virtual_text(Buffer buffer, Integer src_id, Integer line, Array chunks,
    220                                  Dict(empty) *opts, Error *err)
    221  FUNC_API_SINCE(5)
    222  FUNC_API_DEPRECATED_SINCE(8)
    223 {
    224  buf_T *buf = find_buffer_by_handle(buffer, err);
    225  if (!buf) {
    226    return 0;
    227  }
    228 
    229  if (line < 0 || line >= MAXLNUM) {
    230    api_set_error(err, kErrorTypeValidation, "Line number outside range");
    231    return 0;
    232  }
    233 
    234  uint32_t ns_id = src2ns(&src_id);
    235  int width;
    236 
    237  VirtText virt_text = parse_virt_text(chunks, err, &width);
    238  if (ERROR_SET(err)) {
    239    return 0;
    240  }
    241 
    242  DecorVirtText *existing = decor_find_virttext(buf, (int)line, ns_id);
    243 
    244  if (existing) {
    245    clear_virttext(&existing->data.virt_text);
    246    existing->data.virt_text = virt_text;
    247    existing->width = width;
    248    return src_id;
    249  }
    250 
    251  DecorVirtText *vt = xmalloc(sizeof *vt);
    252  *vt = (DecorVirtText)DECOR_VIRT_TEXT_INIT;
    253  vt->data.virt_text = virt_text;
    254  vt->width = width;
    255  vt->priority = 0;
    256 
    257  DecorInline decor = { .ext = true, .data.ext.vt = vt, .data.ext.sh_idx = DECOR_ID_INVALID };
    258 
    259  extmark_set(buf, ns_id, NULL, (int)line, 0, -1, -1, decor, 0, true,
    260              false, false, false, NULL);
    261  return src_id;
    262 }
    263 
    264 /// Gets a highlight definition by id. |hlID()|
    265 ///
    266 /// @deprecated use |nvim_get_hl()| instead
    267 ///
    268 /// @param hl_id Highlight id as returned by |hlID()|
    269 /// @param rgb Export RGB colors
    270 /// @param[out] err Error details, if any
    271 /// @return Highlight definition map
    272 /// @see nvim_get_hl_by_name
    273 Dict nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Arena *arena, Error *err)
    274  FUNC_API_SINCE(3)
    275  FUNC_API_DEPRECATED_SINCE(9)
    276 {
    277  Dict dic = ARRAY_DICT_INIT;
    278  VALIDATE_INT((syn_get_final_id((int)hl_id) != 0), "highlight id", hl_id, {
    279    return dic;
    280  });
    281  int attrcode = syn_id2attr((int)hl_id);
    282  return hl_get_attr_by_id(attrcode, rgb, arena, err);
    283 }
    284 
    285 /// Gets a highlight definition by name.
    286 ///
    287 /// @deprecated use |nvim_get_hl()| instead
    288 ///
    289 /// @param name Highlight group name
    290 /// @param rgb Export RGB colors
    291 /// @param[out] err Error details, if any
    292 /// @return Highlight definition map
    293 /// @see nvim_get_hl_by_id
    294 Dict nvim_get_hl_by_name(String name, Boolean rgb, Arena *arena, Error *err)
    295  FUNC_API_SINCE(3)
    296  FUNC_API_DEPRECATED_SINCE(9)
    297 {
    298  Dict result = ARRAY_DICT_INIT;
    299  int id = syn_name2id(name.data);
    300 
    301  VALIDATE_S((id != 0), "highlight name", name.data, {
    302    return result;
    303  });
    304  return nvim_get_hl_by_id(id, rgb, arena, err);
    305 }
    306 
    307 /// Inserts a sequence of lines to a buffer at a certain index
    308 ///
    309 /// @deprecated use nvim_buf_set_lines(buffer, lnum, lnum, true, lines)
    310 ///
    311 /// @param buffer     Buffer id
    312 /// @param lnum       Insert the lines after `lnum`. If negative, appends to
    313 ///                   the end of the buffer.
    314 /// @param lines      Array of lines
    315 /// @param[out] err   Error details, if any
    316 void buffer_insert(Buffer buffer, Integer lnum, ArrayOf(String) lines, Arena *arena, Error *err)
    317  FUNC_API_DEPRECATED_SINCE(1)
    318 {
    319  // "lnum" will be the index of the line after inserting,
    320  // no matter if it is negative or not
    321  nvim_buf_set_lines(0, buffer, lnum, lnum, true, lines, arena, err);
    322 }
    323 
    324 /// Gets a buffer line
    325 ///
    326 /// @deprecated use nvim_buf_get_lines instead.
    327 ///             for positive indices (including 0) use
    328 ///                 "nvim_buf_get_lines(buffer, index, index+1, true)"
    329 ///             for negative indices use
    330 ///                 "nvim_buf_get_lines(buffer, index-1, index, true)"
    331 ///
    332 /// @param buffer   Buffer id
    333 /// @param index    Line index
    334 /// @param[out] err Error details, if any
    335 /// @return Line string
    336 String buffer_get_line(Buffer buffer, Integer index, Arena *arena, Error *err)
    337  FUNC_API_DEPRECATED_SINCE(1)
    338 {
    339  String rv = { .size = 0 };
    340 
    341  index = convert_index(index);
    342  Array slice = nvim_buf_get_lines(0, buffer, index, index + 1, true, arena, NULL, err);
    343 
    344  if (!ERROR_SET(err) && slice.size) {
    345    rv = slice.items[0].data.string;
    346  }
    347 
    348  return rv;
    349 }
    350 
    351 /// Sets a buffer line
    352 ///
    353 /// @deprecated use nvim_buf_set_lines instead.
    354 ///             for positive indices use
    355 ///                 "nvim_buf_set_lines(buffer, index, index+1, true, [line])"
    356 ///             for negative indices use
    357 ///                 "nvim_buf_set_lines(buffer, index-1, index, true, [line])"
    358 ///
    359 /// @param buffer   Buffer id
    360 /// @param index    Line index
    361 /// @param line     Contents of the new line
    362 /// @param[out] err Error details, if any
    363 void buffer_set_line(Buffer buffer, Integer index, String line, Arena *arena, Error *err)
    364  FUNC_API_DEPRECATED_SINCE(1)
    365 {
    366  Object l = STRING_OBJ(line);
    367  Array array = { .items = &l, .size = 1 };
    368  index = convert_index(index);
    369  nvim_buf_set_lines(0, buffer, index, index + 1, true,  array, arena, err);
    370 }
    371 
    372 /// Deletes a buffer line
    373 ///
    374 /// @deprecated use nvim_buf_set_lines instead.
    375 ///             for positive indices use
    376 ///                 "nvim_buf_set_lines(buffer, index, index+1, true, [])"
    377 ///             for negative indices use
    378 ///                 "nvim_buf_set_lines(buffer, index-1, index, true, [])"
    379 /// @param buffer   buffer id
    380 /// @param index    line index
    381 /// @param[out] err Error details, if any
    382 void buffer_del_line(Buffer buffer, Integer index, Arena *arena, Error *err)
    383  FUNC_API_DEPRECATED_SINCE(1)
    384 {
    385  Array array = ARRAY_DICT_INIT;
    386  index = convert_index(index);
    387  nvim_buf_set_lines(0, buffer, index, index + 1, true, array, arena, err);
    388 }
    389 
    390 /// Retrieves a line range from the buffer
    391 ///
    392 /// @deprecated use nvim_buf_get_lines(buffer, newstart, newend, false)
    393 ///             where newstart = start + int(not include_start) - int(start < 0)
    394 ///                   newend = end + int(include_end) - int(end < 0)
    395 ///                   int(bool) = 1 if bool is true else 0
    396 /// @param buffer         Buffer id
    397 /// @param start          First line index
    398 /// @param end            Last line index
    399 /// @param include_start  True if the slice includes the `start` parameter
    400 /// @param include_end    True if the slice includes the `end` parameter
    401 /// @param[out] err       Error details, if any
    402 /// @return Array of lines
    403 ArrayOf(String) buffer_get_line_slice(Buffer buffer,
    404                                      Integer start,
    405                                      Integer end,
    406                                      Boolean include_start,
    407                                      Boolean include_end,
    408                                      Arena *arena,
    409                                      Error *err)
    410  FUNC_API_DEPRECATED_SINCE(1)
    411 {
    412  start = convert_index(start) + !include_start;
    413  end = convert_index(end) + include_end;
    414  return nvim_buf_get_lines(0, buffer, start, end, false, arena, NULL, err);
    415 }
    416 
    417 /// Replaces a line range on the buffer
    418 ///
    419 /// @deprecated use nvim_buf_set_lines(buffer, newstart, newend, false, lines)
    420 ///             where newstart = start + int(not include_start) + int(start < 0)
    421 ///                   newend = end + int(include_end) + int(end < 0)
    422 ///                   int(bool) = 1 if bool is true else 0
    423 ///
    424 /// @param buffer         Buffer id, or 0 for current buffer
    425 /// @param start          First line index
    426 /// @param end            Last line index
    427 /// @param include_start  True if the slice includes the `start` parameter
    428 /// @param include_end    True if the slice includes the `end` parameter
    429 /// @param replacement    Array of lines to use as replacement (0-length
    430 //                        array will delete the line range)
    431 /// @param[out] err       Error details, if any
    432 void buffer_set_line_slice(Buffer buffer, Integer start, Integer end, Boolean include_start,
    433                           Boolean include_end, ArrayOf(String) replacement, Arena *arena,
    434                           Error *err)
    435  FUNC_API_DEPRECATED_SINCE(1)
    436 {
    437  start = convert_index(start) + !include_start;
    438  end = convert_index(end) + include_end;
    439  nvim_buf_set_lines(0, buffer, start, end, false, replacement, arena, err);
    440 }
    441 
    442 /// Sets a buffer-scoped (b:) variable
    443 ///
    444 /// @deprecated
    445 ///
    446 /// @param buffer     Buffer id, or 0 for current buffer
    447 /// @param name       Variable name
    448 /// @param value      Variable value
    449 /// @param[out] err   Error details, if any
    450 /// @return Old value or nil if there was no previous value.
    451 ///
    452 ///         @warning It may return nil if there was no previous value
    453 ///                  or if previous value was `v:null`.
    454 Object buffer_set_var(Buffer buffer, String name, Object value, Arena *arena, Error *err)
    455  FUNC_API_DEPRECATED_SINCE(1)
    456 {
    457  buf_T *buf = find_buffer_by_handle(buffer, err);
    458 
    459  if (!buf) {
    460    return NIL;
    461  }
    462 
    463  return dict_set_var(buf->b_vars, name, value, false, true, arena, err);
    464 }
    465 
    466 /// Removes a buffer-scoped (b:) variable
    467 ///
    468 /// @deprecated
    469 ///
    470 /// @param buffer     Buffer id, or 0 for current buffer
    471 /// @param name       Variable name
    472 /// @param[out] err   Error details, if any
    473 /// @return Old value
    474 Object buffer_del_var(Buffer buffer, String name, Arena *arena, Error *err)
    475  FUNC_API_DEPRECATED_SINCE(1)
    476 {
    477  buf_T *buf = find_buffer_by_handle(buffer, err);
    478 
    479  if (!buf) {
    480    return NIL;
    481  }
    482 
    483  return dict_set_var(buf->b_vars, name, NIL, true, true, arena, err);
    484 }
    485 
    486 /// Sets a window-scoped (w:) variable
    487 ///
    488 /// @deprecated
    489 ///
    490 /// @param window   |window-ID|, or 0 for current window
    491 /// @param name     Variable name
    492 /// @param value    Variable value
    493 /// @param[out] err Error details, if any
    494 /// @return Old value or nil if there was no previous value.
    495 ///
    496 ///         @warning It may return nil if there was no previous value
    497 ///                  or if previous value was `v:null`.
    498 Object window_set_var(Window window, String name, Object value, Arena *arena, Error *err)
    499  FUNC_API_DEPRECATED_SINCE(1)
    500 {
    501  win_T *win = find_window_by_handle(window, err);
    502 
    503  if (!win) {
    504    return NIL;
    505  }
    506 
    507  return dict_set_var(win->w_vars, name, value, false, true, arena, err);
    508 }
    509 
    510 /// Removes a window-scoped (w:) variable
    511 ///
    512 /// @deprecated
    513 ///
    514 /// @param window   |window-ID|, or 0 for current window
    515 /// @param name     variable name
    516 /// @param[out] err Error details, if any
    517 /// @return Old value
    518 Object window_del_var(Window window, String name, Arena *arena, Error *err)
    519  FUNC_API_DEPRECATED_SINCE(1)
    520 {
    521  win_T *win = find_window_by_handle(window, err);
    522 
    523  if (!win) {
    524    return NIL;
    525  }
    526 
    527  return dict_set_var(win->w_vars, name, NIL, true, true, arena, err);
    528 }
    529 
    530 /// Sets a tab-scoped (t:) variable
    531 ///
    532 /// @deprecated
    533 ///
    534 /// @param tabpage  |tab-ID|, or 0 for current tabpage
    535 /// @param name     Variable name
    536 /// @param value    Variable value
    537 /// @param[out] err Error details, if any
    538 /// @return Old value or nil if there was no previous value.
    539 ///
    540 ///         @warning It may return nil if there was no previous value
    541 ///                  or if previous value was `v:null`.
    542 Object tabpage_set_var(Tabpage tabpage, String name, Object value, Arena *arena, Error *err)
    543  FUNC_API_DEPRECATED_SINCE(1)
    544 {
    545  tabpage_T *tab = find_tab_by_handle(tabpage, err);
    546 
    547  if (!tab) {
    548    return NIL;
    549  }
    550 
    551  return dict_set_var(tab->tp_vars, name, value, false, true, arena, err);
    552 }
    553 
    554 /// Removes a tab-scoped (t:) variable
    555 ///
    556 /// @deprecated
    557 ///
    558 /// @param tabpage  |tab-ID|, or 0 for current tabpage
    559 /// @param name     Variable name
    560 /// @param[out] err Error details, if any
    561 /// @return Old value
    562 Object tabpage_del_var(Tabpage tabpage, String name, Arena *arena, Error *err)
    563  FUNC_API_DEPRECATED_SINCE(1)
    564 {
    565  tabpage_T *tab = find_tab_by_handle(tabpage, err);
    566 
    567  if (!tab) {
    568    return NIL;
    569  }
    570 
    571  return dict_set_var(tab->tp_vars, name, NIL, true, true, arena, err);
    572 }
    573 
    574 /// @deprecated
    575 /// @see nvim_set_var
    576 /// @warning May return nil if there was no previous value
    577 ///          OR if previous value was `v:null`.
    578 /// @return Old value or nil if there was no previous value.
    579 Object vim_set_var(String name, Object value, Arena *arena, Error *err)
    580  FUNC_API_DEPRECATED_SINCE(1)
    581 {
    582  return dict_set_var(get_globvar_dict(), name, value, false, true, arena, err);
    583 }
    584 
    585 /// @deprecated
    586 /// @see nvim_del_var
    587 Object vim_del_var(String name, Arena *arena, Error *err)
    588  FUNC_API_DEPRECATED_SINCE(1)
    589 {
    590  return dict_set_var(get_globvar_dict(), name, NIL, true, true, arena, err);
    591 }
    592 
    593 static int64_t convert_index(int64_t index)
    594 {
    595  return index < 0 ? index - 1 : index;
    596 }
    597 
    598 /// Gets the option information for one option
    599 ///
    600 /// @deprecated Use @ref nvim_get_option_info2 instead.
    601 ///
    602 /// @param          name Option name
    603 /// @param[out] err Error details, if any
    604 /// @return         Option Information
    605 DictAs(get_option_info) nvim_get_option_info(String name, Arena *arena, Error *err)
    606  FUNC_API_SINCE(7)
    607  FUNC_API_DEPRECATED_SINCE(11)
    608 {
    609  return get_vimoption(name, OPT_GLOBAL, curbuf, curwin, arena, err);
    610 }
    611 
    612 /// Sets the global value of an option.
    613 ///
    614 /// @deprecated
    615 /// @param channel_id
    616 /// @param name     Option name
    617 /// @param value    New option value
    618 /// @param[out] err Error details, if any
    619 void nvim_set_option(uint64_t channel_id, String name, Object value, Error *err)
    620  FUNC_API_SINCE(1)
    621  FUNC_API_DEPRECATED_SINCE(11)
    622 {
    623  set_option_to(channel_id, NULL, kOptScopeGlobal, name, value, err);
    624 }
    625 
    626 /// Gets the global value of an option.
    627 ///
    628 /// @deprecated
    629 /// @param name     Option name
    630 /// @param[out] err Error details, if any
    631 /// @return         Option value (global)
    632 Object nvim_get_option(String name, Error *err)
    633  FUNC_API_SINCE(1)
    634  FUNC_API_DEPRECATED_SINCE(11)
    635  FUNC_API_RET_ALLOC
    636 {
    637  return get_option_from(NULL, kOptScopeGlobal, name, err);
    638 }
    639 
    640 /// Gets a buffer option value
    641 ///
    642 /// @deprecated
    643 /// @param buffer     Buffer id, or 0 for current buffer
    644 /// @param name       Option name
    645 /// @param[out] err   Error details, if any
    646 /// @return Option value
    647 Object nvim_buf_get_option(Buffer buffer, String name, Error *err)
    648  FUNC_API_SINCE(1)
    649  FUNC_API_DEPRECATED_SINCE(11)
    650  FUNC_API_RET_ALLOC
    651 {
    652  buf_T *buf = find_buffer_by_handle(buffer, err);
    653 
    654  if (!buf) {
    655    return (Object)OBJECT_INIT;
    656  }
    657 
    658  return get_option_from(buf, kOptScopeBuf, name, err);
    659 }
    660 
    661 /// Sets a buffer option value. Passing `nil` as value deletes the option (only
    662 /// works if there's a global fallback)
    663 ///
    664 /// @deprecated
    665 /// @param channel_id
    666 /// @param buffer     Buffer id, or 0 for current buffer
    667 /// @param name       Option name
    668 /// @param value      Option value
    669 /// @param[out] err   Error details, if any
    670 void nvim_buf_set_option(uint64_t channel_id, Buffer buffer, String name, Object value, Error *err)
    671  FUNC_API_SINCE(1)
    672  FUNC_API_DEPRECATED_SINCE(11)
    673 {
    674  buf_T *buf = find_buffer_by_handle(buffer, err);
    675 
    676  if (!buf) {
    677    return;
    678  }
    679 
    680  set_option_to(channel_id, buf, kOptScopeBuf, name, value, err);
    681 }
    682 
    683 /// Gets a window option value
    684 ///
    685 /// @deprecated
    686 /// @param window   |window-ID|, or 0 for current window
    687 /// @param name     Option name
    688 /// @param[out] err Error details, if any
    689 /// @return Option value
    690 Object nvim_win_get_option(Window window, String name, Error *err)
    691  FUNC_API_SINCE(1)
    692  FUNC_API_DEPRECATED_SINCE(11)
    693  FUNC_API_RET_ALLOC
    694 {
    695  win_T *win = find_window_by_handle(window, err);
    696 
    697  if (!win) {
    698    return (Object)OBJECT_INIT;
    699  }
    700 
    701  return get_option_from(win, kOptScopeWin, name, err);
    702 }
    703 
    704 /// Sets a window option value. Passing `nil` as value deletes the option (only
    705 /// works if there's a global fallback)
    706 ///
    707 /// @deprecated
    708 /// @param channel_id
    709 /// @param window   |window-ID|, or 0 for current window
    710 /// @param name     Option name
    711 /// @param value    Option value
    712 /// @param[out] err Error details, if any
    713 void nvim_win_set_option(uint64_t channel_id, Window window, String name, Object value, Error *err)
    714  FUNC_API_SINCE(1)
    715  FUNC_API_DEPRECATED_SINCE(11)
    716 {
    717  win_T *win = find_window_by_handle(window, err);
    718 
    719  if (!win) {
    720    return;
    721  }
    722 
    723  set_option_to(channel_id, win, kOptScopeWin, name, value, err);
    724 }
    725 
    726 /// Gets the value of a global or local (buffer, window) option.
    727 ///
    728 /// @param[in]   from       Pointer to buffer or window for local option value.
    729 /// @param       scope      Option scope. See OptScope in option.h.
    730 /// @param       name       The option name.
    731 /// @param[out]  err        Details of an error that may have occurred.
    732 ///
    733 /// @return  the option value. Must be freed by caller.
    734 static Object get_option_from(void *from, OptScope scope, String name, Error *err)
    735 {
    736  VALIDATE_S(name.size > 0, "option name", "<empty>", {
    737    return (Object)OBJECT_INIT;
    738  });
    739 
    740  OptIndex opt_idx = find_option(name.data);
    741  VALIDATE_S(opt_idx != kOptInvalid, "option name", name.data, {
    742    return (Object)OBJECT_INIT;
    743  });
    744 
    745  OptVal value = NIL_OPTVAL;
    746 
    747  if (option_has_scope(opt_idx, scope)) {
    748    value = get_option_value_for(opt_idx, scope == kOptScopeGlobal ? OPT_GLOBAL : OPT_LOCAL,
    749                                 scope, from, err);
    750    if (ERROR_SET(err)) {
    751      return (Object)OBJECT_INIT;
    752    }
    753  }
    754 
    755  VALIDATE_S(value.type != kOptValTypeNil, "option name", name.data, {
    756    return (Object)OBJECT_INIT;
    757  });
    758 
    759  return optval_as_object(value);
    760 }
    761 
    762 /// Sets the value of a global or local (buffer, window) option.
    763 ///
    764 /// @param[in]   to         Pointer to buffer or window for local option value.
    765 /// @param       scope      Option scope. See OptScope in option.h.
    766 /// @param       name       The option name.
    767 /// @param       value      New option value.
    768 /// @param[out]  err        Details of an error that may have occurred.
    769 static void set_option_to(uint64_t channel_id, void *to, OptScope scope, String name, Object value,
    770                          Error *err)
    771 {
    772  VALIDATE_S(name.size > 0, "option name", "<empty>", {
    773    return;
    774  });
    775 
    776  OptIndex opt_idx = find_option(name.data);
    777  VALIDATE_S(opt_idx != kOptInvalid, "option name", name.data, {
    778    return;
    779  });
    780 
    781  bool error = false;
    782  OptVal optval = object_as_optval(value, &error);
    783 
    784  // Handle invalid option value type.
    785  // Don't use `name` in the error message here, because `name` can be any String.
    786  // No need to check if value type actually matches the types for the option, as set_option_value()
    787  // already handles that.
    788  VALIDATE_EXP(!error, "value", "valid option type", api_typename(value.type), {
    789    return;
    790  });
    791 
    792  // For global-win-local options -> setlocal
    793  // For        win-local options -> setglobal and setlocal (opt_flags == 0)
    794  const int opt_flags
    795    = (scope == kOptScopeWin && !option_has_scope(opt_idx, kOptScopeGlobal))
    796      ? 0
    797      : ((scope == kOptScopeGlobal) ? OPT_GLOBAL : OPT_LOCAL);
    798 
    799  WITH_SCRIPT_CONTEXT(channel_id, {
    800    set_option_value_for(name.data, opt_idx, optval, opt_flags, scope, to, err);
    801  });
    802 }
    803 
    804 /// @deprecated Use nvim_exec_lua() instead.
    805 ///
    806 /// Calls many API methods atomically.
    807 ///
    808 /// This has two main usages:
    809 /// 1. To perform several requests from an async context atomically, i.e.
    810 ///    without interleaving redraws, RPC requests from other clients, or user
    811 ///    interactions (however API methods may trigger autocommands or event
    812 ///    processing which have such side effects, e.g. |:sleep| may wake timers).
    813 /// 2. To minimize RPC overhead (roundtrips) of a sequence of many requests.
    814 ///
    815 /// @param channel_id
    816 /// @param calls an array of calls, where each call is described by an array
    817 ///              with two elements: the request name, and an array of arguments.
    818 /// @param[out] err Validation error details (malformed `calls` parameter),
    819 ///             if any. Errors from batched calls are given in the return value.
    820 ///
    821 /// @return Array of two elements. The first is an array of return
    822 /// values. The second is NIL if all calls succeeded. If a call resulted in
    823 /// an error, it is a three-element array with the zero-based index of the call
    824 /// which resulted in an error, the error type and the error message. If an
    825 /// error occurred, the values from all preceding calls will still be returned.
    826 Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *err)
    827  FUNC_API_SINCE(1) FUNC_API_DEPRECATED_SINCE(12) FUNC_API_REMOTE_ONLY
    828 {
    829  Array rv = arena_array(arena, 2);
    830  Array results = arena_array(arena, calls.size);
    831  Error nested_error = ERROR_INIT;
    832 
    833  size_t i;  // also used for freeing the variables
    834  for (i = 0; i < calls.size; i++) {
    835    VALIDATE_T("'calls' item", kObjectTypeArray, calls.items[i].type, {
    836      goto theend;
    837    });
    838    Array call = calls.items[i].data.array;
    839    VALIDATE_EXP((call.size == 2), "'calls' item", "2-item Array", NULL, {
    840      goto theend;
    841    });
    842    VALIDATE_T("name", kObjectTypeString, call.items[0].type, {
    843      goto theend;
    844    });
    845    String name = call.items[0].data.string;
    846    VALIDATE_T("call args", kObjectTypeArray, call.items[1].type, {
    847      goto theend;
    848    });
    849    Array args = call.items[1].data.array;
    850 
    851    MsgpackRpcRequestHandler handler =
    852      msgpack_rpc_get_handler_for(name.data,
    853                                  name.size,
    854                                  &nested_error);
    855 
    856    if (ERROR_SET(&nested_error)) {
    857      break;
    858    }
    859 
    860    Object result = handler.fn(channel_id, args, arena, &nested_error);
    861    if (ERROR_SET(&nested_error)) {
    862      // error handled after loop
    863      break;
    864    }
    865    // TODO(bfredl): wasteful copy. It could be avoided to encoding to msgpack
    866    // directly here. But `result` might become invalid when next api function
    867    // is called in the loop.
    868    ADD_C(results, copy_object(result, arena));
    869    if (handler.ret_alloc) {
    870      api_free_object(result);
    871    }
    872  }
    873 
    874  ADD_C(rv, ARRAY_OBJ(results));
    875  if (ERROR_SET(&nested_error)) {
    876    Array errval = arena_array(arena, 3);
    877    ADD_C(errval, INTEGER_OBJ((Integer)i));
    878    ADD_C(errval, INTEGER_OBJ(nested_error.type));
    879    ADD_C(errval, STRING_OBJ(copy_string(cstr_as_string(nested_error.msg), arena)));
    880    ADD_C(rv, ARRAY_OBJ(errval));
    881  } else {
    882    ADD_C(rv, NIL);
    883  }
    884 
    885 theend:
    886  api_clear_error(&nested_error);
    887  return rv;
    888 }
    889 
    890 /// @deprecated
    891 ///
    892 /// @param channel_id Channel id (passed automatically by the dispatcher)
    893 /// @param event      Event type string
    894 void nvim_subscribe(uint64_t channel_id, String event)
    895 // XXX: c_grammar.lua is order-sensitive.
    896  FUNC_API_SINCE(1) FUNC_API_DEPRECATED_SINCE(13) FUNC_API_REMOTE_ONLY
    897 {
    898  // Does nothing. `rpcnotify(0,…)` broadcasts to all channels, there are no "subscriptions".
    899 }
    900 
    901 /// @deprecated
    902 ///
    903 /// @param channel_id Channel id (passed automatically by the dispatcher)
    904 /// @param event      Event type string
    905 void nvim_unsubscribe(uint64_t channel_id, String event)
    906 // XXX: c_grammar.lua is order-sensitive.
    907  FUNC_API_SINCE(1) FUNC_API_DEPRECATED_SINCE(13) FUNC_API_REMOTE_ONLY
    908 {
    909  // Does nothing. `rpcnotify(0,…)` broadcasts to all channels, there are no "subscriptions".
    910 }
    911 
    912 enum { LINE_BUFFER_MIN_SIZE = 4096, };
    913 
    914 /// Writes a message to vim output or error buffer. The string is split
    915 /// and flushed after each newline. Incomplete lines are kept for writing
    916 /// later.
    917 ///
    918 /// @param message  Message to write
    919 /// @param to_err   true: message is an error (uses `emsg` instead of `msg`)
    920 /// @param writeln  Append a trailing newline
    921 static void write_msg(String message, bool to_err, bool writeln)
    922 {
    923  static StringBuilder out_line_buf = KV_INITIAL_VALUE;
    924  static StringBuilder err_line_buf = KV_INITIAL_VALUE;
    925  StringBuilder *line_buf = to_err ? &err_line_buf : &out_line_buf;
    926 
    927 #define PUSH_CHAR(c) \
    928  if (kv_max(*line_buf) == 0) { \
    929    kv_resize(*line_buf, LINE_BUFFER_MIN_SIZE); \
    930  } \
    931  if (c == NL) { \
    932    kv_push(*line_buf, NUL); \
    933    if (to_err) { \
    934      emsg(line_buf->items); \
    935    } else { \
    936      msg(line_buf->items, 0); \
    937    } \
    938    if (msg_silent == 0) { \
    939      msg_didout = true; \
    940    } \
    941    kv_drop(*line_buf, kv_size(*line_buf)); \
    942    kv_resize(*line_buf, LINE_BUFFER_MIN_SIZE); \
    943  } else if (c == NUL) { \
    944    kv_push(*line_buf, NL); \
    945  } else { \
    946    kv_push(*line_buf, c); \
    947  }
    948 
    949  no_wait_return++;
    950  for (uint32_t i = 0; i < message.size; i++) {
    951    if (got_int) {
    952      break;
    953    }
    954    PUSH_CHAR(message.data[i]);
    955  }
    956  if (writeln) {
    957    PUSH_CHAR(NL);
    958  }
    959  no_wait_return--;
    960  msg_end();
    961 }
    962 
    963 /// @deprecated
    964 ///
    965 /// @param str Message
    966 void nvim_out_write(String str)
    967  FUNC_API_SINCE(1) FUNC_API_DEPRECATED_SINCE(13)
    968 {
    969  write_msg(str, false, false);
    970 }
    971 
    972 /// @deprecated
    973 ///
    974 /// @param str Message
    975 void nvim_err_write(String str)
    976  FUNC_API_SINCE(1) FUNC_API_DEPRECATED_SINCE(13)
    977 {
    978  write_msg(str, true, false);
    979 }
    980 
    981 /// @deprecated
    982 ///
    983 /// @param str Message
    984 void nvim_err_writeln(String str)
    985  FUNC_API_SINCE(1) FUNC_API_DEPRECATED_SINCE(13)
    986 {
    987  write_msg(str, true, true);
    988 }
    989 
    990 /// @deprecated
    991 ///
    992 /// Use `nvim_echo` or `nvim_exec_lua("vim.notify(...)", ...)` instead.
    993 ///
    994 /// @param msg        Message to display to the user
    995 /// @param log_level  The log level
    996 /// @param opts       Reserved for future use.
    997 /// @param[out] err   Error details, if any
    998 Object nvim_notify(String msg, Integer log_level, Dict opts, Arena *arena, Error *err)
    999  FUNC_API_SINCE(7) FUNC_API_DEPRECATED_SINCE(13)
   1000 {
   1001  MAXSIZE_TEMP_ARRAY(args, 3);
   1002  ADD_C(args, STRING_OBJ(msg));
   1003  ADD_C(args, INTEGER_OBJ(log_level));
   1004  ADD_C(args, DICT_OBJ(opts));
   1005 
   1006  return NLUA_EXEC_STATIC("return vim.notify(...)", args, kRetObject, arena, err);
   1007 }