mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	API: Implement vim_{get,set}_var
This commit is contained in:
		| @@ -20,6 +20,8 @@ KHASH_SET_INIT_INT64(Lookup) | ||||
| /// @return The converted value | ||||
| static Object vim_to_object_rec(typval_T *obj, khash_t(Lookup) *lookup); | ||||
|  | ||||
| static bool object_to_vim(Object obj, typval_T *tv, Error *err); | ||||
|  | ||||
| void try_start() | ||||
| { | ||||
|   ++trylevel; | ||||
| @@ -62,6 +64,76 @@ bool try_end(Error *err) | ||||
|   return err->set; | ||||
| } | ||||
|  | ||||
| Object dict_get_value(dict_T *dict, String key, bool pop, Error *err) | ||||
| { | ||||
|   Object rv; | ||||
|   hashitem_T *hi; | ||||
|   dictitem_T *di; | ||||
|   char k[key.size + 1]; | ||||
|   // Convert the key | ||||
|   memcpy(k, key.data, key.size); | ||||
|   k[key.size] = NUL; | ||||
|   hi = hash_find(&dict->dv_hashtab, (uint8_t *)k); | ||||
|  | ||||
|   if (HASHITEM_EMPTY(hi)) { | ||||
|     set_api_error("Key not found", err); | ||||
|     return rv; | ||||
|   } | ||||
|  | ||||
|   di = dict_lookup(hi); | ||||
|   rv = vim_to_object(&di->di_tv); | ||||
|  | ||||
|   if (pop) { | ||||
|     if (dict->dv_lock) { | ||||
|       set_api_error("Dictionary is locked", err); | ||||
|       return rv; | ||||
|     } | ||||
|  | ||||
|     hash_remove(&dict->dv_hashtab, hi); | ||||
|     dictitem_free(di); | ||||
|   } | ||||
|  | ||||
|   return rv; | ||||
| } | ||||
|  | ||||
| Object dict_set_value(dict_T *dict, String key, Object value, Error *err) | ||||
| { | ||||
|   Object rv = {.type = kObjectTypeNil}; | ||||
|  | ||||
|   if (dict->dv_lock) { | ||||
|     set_api_error("Dictionary is locked", err); | ||||
|     return rv; | ||||
|   } | ||||
|  | ||||
|   if (key.size == 0) { | ||||
|     set_api_error("Empty dictionary keys aren't allowed", err); | ||||
|     return rv; | ||||
|   } | ||||
|  | ||||
|   dictitem_T *di = dict_find(dict, (uint8_t *)key.data, key.size); | ||||
|   typval_T tv; | ||||
|  | ||||
|   if (!object_to_vim(value, &tv, err)) { | ||||
|     return rv; | ||||
|   } | ||||
|  | ||||
|   if (di == NULL) { | ||||
|     uint8_t k[key.size + 1]; | ||||
|     memcpy(k, key.data, key.size); | ||||
|     k[key.size] = NUL; | ||||
|     di = dictitem_alloc(k); | ||||
|     dict_add(dict, di); | ||||
|   } else { | ||||
|     rv = vim_to_object(&di->di_tv); | ||||
|     clear_tv(&di->di_tv); | ||||
|   } | ||||
|  | ||||
|   copy_tv(&tv, &di->di_tv); | ||||
|   clear_tv(&tv); | ||||
|  | ||||
|   return rv; | ||||
| } | ||||
|  | ||||
| Object vim_to_object(typval_T *obj) | ||||
| { | ||||
|   Object rv; | ||||
| @@ -73,6 +145,94 @@ Object vim_to_object(typval_T *obj) | ||||
|   return rv; | ||||
| } | ||||
|  | ||||
| static bool object_to_vim(Object obj, typval_T *tv, Error *err) | ||||
| { | ||||
|   tv->v_type = VAR_UNKNOWN; | ||||
|   tv->v_lock = 0; | ||||
|  | ||||
|   switch (obj.type) { | ||||
|     case kObjectTypeNil: | ||||
|       tv->v_type = VAR_NUMBER; | ||||
|       tv->vval.v_number = 0; | ||||
|       break; | ||||
|  | ||||
|     case kObjectTypeBool: | ||||
|       tv->v_type = VAR_NUMBER; | ||||
|       tv->vval.v_number = obj.data.boolean; | ||||
|       break; | ||||
|  | ||||
|     case kObjectTypeInt: | ||||
|       tv->v_type = VAR_NUMBER; | ||||
|       tv->vval.v_number = obj.data.integer; | ||||
|       break; | ||||
|  | ||||
|     case kObjectTypeFloat: | ||||
|       tv->v_type = VAR_FLOAT; | ||||
|       tv->vval.v_float = obj.data.floating_point; | ||||
|       break; | ||||
|  | ||||
|     case kObjectTypeString: | ||||
|       tv->v_type = VAR_STRING; | ||||
|       tv->vval.v_string = (uint8_t *)xstrndup(obj.data.string.data, | ||||
|                                               obj.data.string.size); | ||||
|       break; | ||||
|  | ||||
|     case kObjectTypeArray: | ||||
|       tv->v_type = VAR_LIST; | ||||
|       tv->vval.v_list = list_alloc(); | ||||
|  | ||||
|       for (uint32_t i = 0; i < obj.data.array.size; i++) { | ||||
|         Object item = obj.data.array.items[i]; | ||||
|         listitem_T *li = listitem_alloc(); | ||||
|  | ||||
|         if (!object_to_vim(item, &li->li_tv, err)) { | ||||
|           // cleanup | ||||
|           listitem_free(li); | ||||
|           list_free(tv->vval.v_list, true); | ||||
|           return false; | ||||
|         } | ||||
|  | ||||
|         list_append(tv->vval.v_list, li); | ||||
|       } | ||||
|       tv->vval.v_list->lv_refcount++; | ||||
|       break; | ||||
|  | ||||
|     case kObjectTypeDictionary: | ||||
|       tv->v_type = VAR_DICT; | ||||
|       tv->vval.v_dict = dict_alloc(); | ||||
|  | ||||
|       for (uint32_t i = 0; i < obj.data.dictionary.size; i++) { | ||||
|         KeyValuePair item = obj.data.dictionary.items[i]; | ||||
|         String key = item.key; | ||||
|  | ||||
|         if (key.size == 0) { | ||||
|           set_api_error("Empty dictionary keys aren't allowed", err); | ||||
|           // cleanup | ||||
|           dict_free(tv->vval.v_dict, true); | ||||
|           return false; | ||||
|         } | ||||
|  | ||||
|         char k[key.size + 1]; | ||||
|         memcpy(k, key.data, key.size); | ||||
|         k[key.size] = NUL; | ||||
|         dictitem_T *di = dictitem_alloc((uint8_t *)k); | ||||
|  | ||||
|         if (!object_to_vim(item.value, &di->di_tv, err)) { | ||||
|           // cleanup | ||||
|           dictitem_free(di); | ||||
|           dict_free(tv->vval.v_dict, true); | ||||
|           return false; | ||||
|         } | ||||
|  | ||||
|         dict_add(tv->vval.v_dict, di); | ||||
|       } | ||||
|       tv->vval.v_dict->dv_refcount++; | ||||
|       break; | ||||
|   } | ||||
|  | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| static Object vim_to_object_rec(typval_T *obj, khash_t(Lookup) *lookup) | ||||
| { | ||||
|   Object rv = {.type = kObjectTypeNil}; | ||||
|   | ||||
| @@ -22,6 +22,24 @@ void try_start(void); | ||||
| /// @return true if an error occurred | ||||
| bool try_end(Error *err); | ||||
|  | ||||
| /// Recursively expands a vimscript value in a dict | ||||
| /// | ||||
| /// @param dict The vimscript dict | ||||
| /// @param key The key | ||||
| /// @param bool If true it will pop the value from the dict | ||||
| /// @param[out] err Details of an error that may have occurred | ||||
| Object dict_get_value(dict_T *dict, String key, bool pop, Error *err); | ||||
|  | ||||
| /// Set a value in a dict. Objects are recursively expanded into their | ||||
| /// vimscript equivalents. | ||||
| /// | ||||
| /// @param dict The vimscript dict | ||||
| /// @param key The key | ||||
| /// @param value The new value | ||||
| /// @param[out] err Details of an error that may have occurred | ||||
| /// @return the old value, if any | ||||
| Object dict_set_value(dict_T *dict, String key, Object value, Error *err); | ||||
|  | ||||
| /// Convert a vim object to an `Object` instance, recursively expanding | ||||
| /// Arrays/Dictionaries. | ||||
| /// | ||||
|   | ||||
| @@ -127,14 +127,16 @@ void vim_set_current_line(Object line, Error *err) | ||||
|   buffer_set_line(curbuf->b_fnum, curwin->w_cursor.lnum - 1, line, err); | ||||
| } | ||||
|  | ||||
| Object vim_get_var(bool special, String name, Error *err) | ||||
| Object vim_get_var(bool special, String name, bool pop, Error *err) | ||||
| { | ||||
|   abort(); | ||||
|   return dict_get_value(special ? &vimvardict : &globvardict, name, | ||||
|                         special ? false : pop, | ||||
|                         err); | ||||
| } | ||||
|  | ||||
| void vim_set_var(bool special, String name, Object value, Error *err) | ||||
| Object vim_set_var(String name, Object value, Error *err) | ||||
| { | ||||
|   abort(); | ||||
|   return dict_set_value(&globvardict, name, value, err); | ||||
| } | ||||
|  | ||||
| String vim_get_option(String name, Error *err) | ||||
|   | ||||
| @@ -62,15 +62,15 @@ void vim_set_current_line(Object line, Error *err); | ||||
| /// @param name The variable name | ||||
| /// @param[out] err Details of an error that may have occurred | ||||
| /// @return The variable value | ||||
| Object vim_get_var(bool special, String name, Error *err); | ||||
| Object vim_get_var(bool special, String name, bool pop, Error *err); | ||||
|  | ||||
| /// Sets a global or special variable | ||||
| /// Sets a global variable | ||||
| /// | ||||
| /// @param special If it's a special(:v) variable | ||||
| /// @param name The variable name | ||||
| /// @param value The variable value | ||||
| /// @param[out] err Details of an error that may have occurred | ||||
| void vim_set_var(bool special, String name, Object value, Error *err); | ||||
| /// @return the old value if any | ||||
| Object vim_set_var(String name, Object value, Error *err); | ||||
|  | ||||
| /// Get an option value string | ||||
| /// | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Thiago de Arruda
					Thiago de Arruda