/// Set a value in a dict. Objects are recursively expanded into their /// vimscript equivalents. Passing 'nil' as value deletes the key. /// /// @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) { Object rv = OBJECT_INIT; 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; } if (key.size > INT_MAX) { set_api_error("Key length is too high", err); return rv; } dictitem_T *di = dict_find(dict, (uint8_t *)key.data, (int)key.size); if (value.type == kObjectTypeNil) { // Delete the key if (di == NULL) { // Doesn't exist, fail set_api_error("Key doesn't exist", err); } else { // Return the old value rv = vim_to_object(&di->di_tv); // Delete the entry hashitem_T *hi = hash_find(&dict->dv_hashtab, di->di_key); hash_remove(&dict->dv_hashtab, hi); dictitem_free(di); } } else { // Update the key typval_T tv; // Convert the object to a vimscript type in the temporary variable if (!object_to_vim(value, &tv, err)) { return rv; } if (di == NULL) { // Need to create an entry di = dictitem_alloc((uint8_t *) key.data); dict_add(dict, di); } else { // Return the old value clear_tv(&di->di_tv); } // Update the value copy_tv(&tv, &di->di_tv); // Clear the temporary variable clear_tv(&tv); } return rv; }
/// Recursively expands a vimscript value in a dict /// /// @param dict The vimscript dict /// @param key The key /// @param[out] err Details of an error that may have occurred Object dict_get_value(dict_T *dict, String key, Error *err) { hashitem_T *hi = hash_find(&dict->dv_hashtab, (uint8_t *) key.data); if (HASHITEM_EMPTY(hi)) { set_api_error("Key not found", err); return (Object) OBJECT_INIT; } dictitem_T *di = dict_lookup(hi); return vim_to_object(&di->di_tv); }
Object vim_eval(String str, Error *err) { Object rv; char *expr_str = xstrndup(str.data, str.size); // Evaluate the expression try_start(); typval_T *expr_result = eval_expr((char_u *)expr_str, NULL); free(expr_str); if (!try_end(err)) { // No errors, convert the result rv = vim_to_object(expr_result); } // Free the vim object free_tv(expr_result); return rv; }
Object dict_get_value(dict_T *dict, String key, Error *err) { Object rv; hashitem_T *hi; dictitem_T *di; char *k = xstrndup(key.data, key.size); hi = hash_find(&dict->dv_hashtab, (uint8_t *)k); free(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); return rv; }
/// Call the given function with the given arguments stored in an array. /// /// @param fname Function to call /// @param args Functions arguments packed in an Array /// @param[out] err Details of an error that may have occurred /// @return Result of the function call Object vim_call_function(String fname, Array args, Error *err) { Object rv = OBJECT_INIT; if (args.size > MAX_FUNC_ARGS) { api_set_error(err, Validation, _("Function called with too many arguments.")); return rv; } // Convert the arguments in args from Object to typval_T values typval_T vim_args[MAX_FUNC_ARGS + 1]; size_t i = 0; // also used for freeing the variables for (; i < args.size; i++) { if (!object_to_vim(args.items[i], &vim_args[i], err)) { goto free_vim_args; } } try_start(); // Call the function typval_T rettv; int dummy; int r = call_func((char_u *) fname.data, (int) fname.size, &rettv, (int) args.size, vim_args, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &dummy, true, NULL); if (r == FAIL) { api_set_error(err, Exception, _("Error calling function.")); } if (!try_end(err)) { rv = vim_to_object(&rettv); } clear_tv(&rettv); free_vim_args: while (i > 0) { clear_tv(&vim_args[--i]); } return rv; }
/// Evaluates the expression str using the vim internal expression /// evaluator (see |expression|). /// Dictionaries and lists are recursively expanded. /// /// @param str The expression str /// @param[out] err Details of an error that may have occurred /// @return The expanded object Object vim_eval(String str, Error *err) { Object rv; // Evaluate the expression try_start(); typval_T *expr_result = eval_expr((char_u *) str.data, NULL); if (!expr_result) { set_api_error("Failed to eval expression", err); } if (!try_end(err)) { // No errors, convert the result rv = vim_to_object(expr_result); } // Free the vim object free_tv(expr_result); return rv; }
/// Evaluates a VimL expression (:help expression). /// Dictionaries and Lists are recursively expanded. /// On VimL error: Returns a generic error; v:errmsg is not updated. /// /// @param expr VimL expression string /// @param[out] err Error details, if any /// @return Evaluation result or expanded object Object nvim_eval(String expr, Error *err) { Object rv = OBJECT_INIT; // Evaluate the expression try_start(); typval_T *expr_result = eval_expr((char_u *)expr.data, NULL); if (!expr_result) { api_set_error(err, Exception, _("Failed to evaluate expression")); } if (!try_end(err)) { // No errors, convert the result rv = vim_to_object(expr_result); } // Free the vim object free_tv(expr_result); return rv; }