neovim

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

helpers.h (5737B)


      1 #pragma once
      2 
      3 #include <stdbool.h>
      4 #include <stddef.h>  // IWYU pragma: keep
      5 
      6 #include "klib/kvec.h"
      7 #include "nvim/api/private/defs.h"  // IWYU pragma: keep
      8 #include "nvim/buffer_defs.h"  // IWYU pragma: keep
      9 #include "nvim/eval/typval_defs.h"  // IWYU pragma: keep
     10 #include "nvim/ex_eval_defs.h"
     11 #include "nvim/macros_defs.h"
     12 #include "nvim/map_defs.h"
     13 #include "nvim/message_defs.h"  // IWYU pragma: keep
     14 
     15 #define OBJECT_OBJ(o) o
     16 
     17 #define BOOLEAN_OBJ(b) ((Object) { \
     18    .type = kObjectTypeBoolean, \
     19    .data.boolean = b })
     20 
     21 #define INTEGER_OBJ(i) ((Object) { \
     22    .type = kObjectTypeInteger, \
     23    .data.integer = i })
     24 
     25 #define FLOAT_OBJ(f) ((Object) { \
     26    .type = kObjectTypeFloat, \
     27    .data.floating = f })
     28 
     29 #define STRING_OBJ(s) ((Object) { \
     30    .type = kObjectTypeString, \
     31    .data.string = s })
     32 
     33 #define CSTR_AS_OBJ(s) STRING_OBJ(cstr_as_string(s))
     34 #define CSTR_TO_OBJ(s) STRING_OBJ(cstr_to_string(s))
     35 #define CSTR_TO_ARENA_STR(arena, s) arena_string(arena, cstr_as_string(s))
     36 #define CSTR_TO_ARENA_OBJ(arena, s) STRING_OBJ(CSTR_TO_ARENA_STR(arena, s))
     37 #define CBUF_TO_ARENA_STR(arena, s, len) arena_string(arena, cbuf_as_string((char *)(s), len))
     38 #define CBUF_TO_ARENA_OBJ(arena, s, len) STRING_OBJ(CBUF_TO_ARENA_STR(arena, s, len))
     39 
     40 #define BUFFER_OBJ(s) ((Object) { \
     41    .type = kObjectTypeBuffer, \
     42    .data.integer = s })
     43 
     44 #define WINDOW_OBJ(s) ((Object) { \
     45    .type = kObjectTypeWindow, \
     46    .data.integer = s })
     47 
     48 #define TABPAGE_OBJ(s) ((Object) { \
     49    .type = kObjectTypeTabpage, \
     50    .data.integer = s })
     51 
     52 #define ARRAY_OBJ(a) ((Object) { \
     53    .type = kObjectTypeArray, \
     54    .data.array = a })
     55 
     56 #define DICT_OBJ(d) ((Object) { \
     57    .type = kObjectTypeDict, \
     58    .data.dict = d })
     59 
     60 #define LUAREF_OBJ(r) ((Object) { \
     61    .type = kObjectTypeLuaRef, \
     62    .data.luaref = r })
     63 
     64 #define NIL ((Object)OBJECT_INIT)
     65 #define NULL_STRING ((String)STRING_INIT)
     66 
     67 #define HAS_KEY(d, typ, key) (((d)->is_set__##typ##_ & (1ULL << KEYSET_OPTIDX_##typ##__##key)) != 0)
     68 
     69 #define GET_BOOL_OR_TRUE(d, typ, key) (HAS_KEY(d, typ, key) ? (d)->key : true)
     70 
     71 #define PUT(dict, k, v) \
     72  kv_push(dict, ((KeyValuePair) { .key = cstr_to_string(k), .value = v }))
     73 
     74 #define PUT_C(dict, k, v) \
     75  kv_push_c(dict, ((KeyValuePair) { .key = cstr_as_string(k), .value = v }))
     76 
     77 #define PUT_KEY(d, typ, key, v) \
     78  do { (d).is_set__##typ##_ |= (1ULL << KEYSET_OPTIDX_##typ##__##key); (d).key = v; } while (0)
     79 
     80 #define ADD(array, item) \
     81  kv_push(array, item)
     82 
     83 #define ADD_C(array, item) \
     84  kv_push_c(array, item)
     85 
     86 #define MAXSIZE_TEMP_ARRAY(name, maxsize) \
     87  Array name = ARRAY_DICT_INIT; \
     88  Object name##__items[maxsize]; \
     89  name.capacity = maxsize; \
     90  name.items = name##__items; \
     91 
     92 #define MAXSIZE_TEMP_DICT(name, maxsize) \
     93  Dict name = ARRAY_DICT_INIT; \
     94  KeyValuePair name##__items[maxsize]; \
     95  name.capacity = maxsize; \
     96  name.items = name##__items; \
     97 
     98 typedef kvec_withinit_t(Object, 16) ArrayBuilder;
     99 
    100 #define cbuf_as_string(d, s) ((String) { .data = d, .size = s })
    101 
    102 #define STATIC_CSTR_AS_STRING(s) ((String) { .data = s, .size = sizeof("" s) - 1 })
    103 
    104 /// Create a new String instance, putting data in allocated memory
    105 ///
    106 /// @param[in]  s  String to work with. Must be a string literal.
    107 #define STATIC_CSTR_TO_STRING(s) ((String){ \
    108    .data = xmemdupz(s, sizeof(s) - 1), \
    109    .size = sizeof(s) - 1 })
    110 
    111 #define STATIC_CSTR_AS_OBJ(s) STRING_OBJ(STATIC_CSTR_AS_STRING(s))
    112 #define STATIC_CSTR_TO_OBJ(s) STRING_OBJ(STATIC_CSTR_TO_STRING(s))
    113 
    114 #define API_CLEAR_STRING(s) \
    115  do { \
    116    XFREE_CLEAR(s.data); \
    117    s.size = 0; \
    118  } while (0)
    119 
    120 // Helpers used by the generated msgpack-rpc api wrappers
    121 #define api_init_boolean
    122 #define api_init_integer
    123 #define api_init_float
    124 #define api_init_string = STRING_INIT
    125 #define api_init_buffer
    126 #define api_init_window
    127 #define api_init_tabpage
    128 #define api_init_object = NIL
    129 #define api_init_array = ARRAY_DICT_INIT
    130 #define api_init_dict = ARRAY_DICT_INIT
    131 
    132 #define KEYDICT_INIT { 0 }
    133 
    134 EXTERN PMap(int) buffer_handles INIT( = MAP_INIT);
    135 EXTERN PMap(int) window_handles INIT( = MAP_INIT);
    136 EXTERN PMap(int) tabpage_handles INIT( = MAP_INIT);
    137 
    138 #define handle_get_buffer(h) pmap_get(int)(&buffer_handles, (h))
    139 #define handle_get_window(h) pmap_get(int)(&window_handles, (h))
    140 #define handle_get_tabpage(h) pmap_get(int)(&tabpage_handles, (h))
    141 
    142 /// Structure used for saving state for :try
    143 ///
    144 /// Used when caller is supposed to be operating when other Vimscript code is being
    145 /// processed and that “other Vimscript code” must not be affected.
    146 typedef struct {
    147  except_T *current_exception;
    148  msglist_T *private_msg_list;
    149  const msglist_T *const *msg_list;
    150  int got_int;
    151  bool did_throw;
    152  int need_rethrow;
    153  int did_emsg;
    154 } TryState;
    155 
    156 // TODO(bfredl): prepare error-handling at "top level" (nv_event).
    157 #define TRY_WRAP(err, code) \
    158  do { \
    159    TryState tstate; \
    160    try_enter(&tstate); \
    161    code; \
    162    try_leave(&tstate, err); \
    163  } while (0)
    164 
    165 // Execute code with cursor position saved and restored and textlock active.
    166 #define TEXTLOCK_WRAP(code) \
    167  do { \
    168    const pos_T save_cursor = curwin->w_cursor; \
    169    textlock++; \
    170    code; \
    171    textlock--; \
    172    curwin->w_cursor = save_cursor; \
    173  } while (0)
    174 
    175 // Useful macro for executing some `code` for each item in an array.
    176 #define FOREACH_ITEM(a, __foreach_item, code) \
    177  for (size_t (__foreach_item##_index) = 0; (__foreach_item##_index) < (a).size; \
    178       (__foreach_item##_index)++) { \
    179    Object __foreach_item = (a).items[__foreach_item##_index]; \
    180    code; \
    181  }
    182 
    183 #include "api/private/helpers.h.generated.h"
    184 
    185 #define WITH_SCRIPT_CONTEXT(channel_id, code) \
    186  do { \
    187    const sctx_T save_current_sctx = api_set_sctx(channel_id); \
    188    code; \
    189    current_sctx = save_current_sctx; \
    190  } while (0);