Patch 8.2.2090
Problem: Vim9: dict does not accept a key in quotes.
Solution: Recognize a key in single or double quotes.
Files: runtime/doc/vim9.txt, src/dict.c, src/proto/dict.pro,
src/vim9compile.c, src/testdir/test_vim9_expr.vim
*** ../vim-8.2.2089/runtime/doc/vim9.txt 2020-11-19 18:53:15.184492586
+0100
--- runtime/doc/vim9.txt 2020-12-04 19:03:01.619017804 +0100
***************
*** 433,451 ****
Traditionally Vim has supported dictionary literals with a {} syntax: >
let dict = {'key': value}
! Later it became clear that using a simple key name is very common, thus
! literally dictionaries were introduced in a backwards compatible way: >
let dict = #{key: value}
! However, this #{} syntax is unlike any existing language. As it appears that
! using a literaly key is much more common than using an expression, and
considering that JavaScript uses this syntax, using the {} form for dictionary
! literals was considered a much more useful syntax. In Vim9 script the {} form
uses literal keys: >
let dict = {key: value}
! In case an expression needs to be used for the key, square brackets can be
! used, just like in JavaScript: >
let dict = {["key" .. nr]: value}
--- 436,460 ----
Traditionally Vim has supported dictionary literals with a {} syntax: >
let dict = {'key': value}
! Later it became clear that using a simple text key is very common, thus
! literal dictionaries were introduced in a backwards compatible way: >
let dict = #{key: value}
! However, this #{} syntax is unlike any existing language. As it turns out
! that using a literal key is much more common than using an expression, and
considering that JavaScript uses this syntax, using the {} form for dictionary
! literals is considered a much more useful syntax. In Vim9 script the {} form
uses literal keys: >
let dict = {key: value}
! This works for alphanumeric characters, underscore and dash. If you want to
! use another character, use a single or double quoted string: >
! let dict = {'key with space': value}
! let dict = {"key\twith\ttabs": value}
! let dict = {'': value} # empty key
!
! In case the key needs to be an expression, square brackets can be used, just
! like in JavaScript: >
let dict = {["key" .. nr]: value}
*** ../vim-8.2.2089/src/dict.c 2020-12-02 17:36:49.169409752 +0100
--- src/dict.c 2020-12-04 18:55:50.744441533 +0100
***************
*** 801,807 ****
* Return FAIL when there is no valid key.
*/
static int
! get_literal_key(char_u **arg, typval_T *tv)
{
char_u *p = skip_literal_key(*arg);
--- 801,807 ----
* Return FAIL when there is no valid key.
*/
static int
! get_literal_key_tv(char_u **arg, typval_T *tv)
{
char_u *p = skip_literal_key(*arg);
***************
*** 815,820 ****
--- 815,861 ----
}
/*
+ * Get a literal key for a Vim9 dict:
+ * {"name": value},
+ * {'name': value},
+ * {name: value} use "name" as a literal key
+ * Return the key in allocated memory or NULL in the case of an error.
+ * "arg" is advanced to just after the key.
+ */
+ char_u *
+ get_literal_key(char_u **arg)
+ {
+ char_u *key;
+ char_u *end;
+ typval_T rettv;
+
+ if (**arg == '\'')
+ {
+ if (eval_lit_string(arg, &rettv, TRUE) == FAIL)
+ return NULL;
+ key = rettv.vval.v_string;
+ }
+ else if (**arg == '"')
+ {
+ if (eval_string(arg, &rettv, TRUE) == FAIL)
+ return NULL;
+ key = rettv.vval.v_string;
+ }
+ else
+ {
+ end = skip_literal_key(*arg);
+ if (end == *arg)
+ {
+ semsg(_(e_invalid_key_str), *arg);
+ return NULL;
+ }
+ key = vim_strnsave(*arg, end - *arg);
+ *arg = end;
+ }
+ return key;
+ }
+
+ /*
* Allocate a variable for a Dictionary and fill it from "*arg".
* "*arg" points to the "{".
* "literal" is TRUE for #{key: val}
***************
*** 864,873 ****
{
int has_bracket = vim9script && **arg == '[';
! if (literal || (vim9script && !has_bracket))
{
! if (get_literal_key(arg, &tvkey) == FAIL)
goto failret;
}
else
{
--- 905,921 ----
{
int has_bracket = vim9script && **arg == '[';
! if (literal)
! {
! if (get_literal_key_tv(arg, &tvkey) == FAIL)
! goto failret;
! }
! else if (vim9script && !has_bracket)
{
! tvkey.vval.v_string = get_literal_key(arg);
! if (tvkey.vval.v_string == NULL)
goto failret;
+ tvkey.v_type = VAR_STRING;
}
else
{
*** ../vim-8.2.2089/src/proto/dict.pro 2020-12-02 17:36:49.169409752 +0100
--- src/proto/dict.pro 2020-12-04 18:52:02.145226267 +0100
***************
*** 34,39 ****
--- 34,40 ----
varnumber_T dict_get_bool(dict_T *d, char_u *key, int def);
char_u *dict2string(typval_T *tv, int copyID, int restore_copyID);
char_u *skip_literal_key(char_u *key);
+ char_u *get_literal_key(char_u **arg);
int eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal);
void dict_extend(dict_T *d1, dict_T *d2, char_u *action);
dictitem_T *dict_lookup(hashitem_T *hi);
*** ../vim-8.2.2089/src/vim9compile.c 2020-12-04 12:43:23.786385152 +0100
--- src/vim9compile.c 2020-12-04 18:56:02.592401563 +0100
***************
*** 3024,3049 ****
if (**arg == '}')
break;
! // {name: value} uses "name" as a literal key and
! // {[expr]: value} uses an evaluated key.
! if (**arg != '[')
! {
! char_u *end = skip_literal_key(*arg);
!
! if (end == *arg)
! {
! semsg(_(e_invalid_key_str), *arg);
! return FAIL;
! }
! key = vim_strnsave(*arg, end - *arg);
! if (generate_PUSHS(cctx, key) == FAIL)
! return FAIL;
! *arg = end;
! }
! else
{
isn_T *isn;
*arg = skipwhite(*arg + 1);
if (compile_expr0(arg, cctx) == FAIL)
return FAIL;
--- 3024,3034 ----
if (**arg == '}')
break;
! if (**arg == '[')
{
isn_T *isn;
+ // {[expr]: value} uses an evaluated key.
*arg = skipwhite(*arg + 1);
if (compile_expr0(arg, cctx) == FAIL)
return FAIL;
***************
*** 3066,3071 ****
--- 3051,3067 ----
}
++*arg;
}
+ else
+ {
+ // {"name": value},
+ // {'name': value},
+ // {name: value} use "name" as a literal key
+ key = get_literal_key(arg);
+ if (key == NULL)
+ return FAIL;
+ if (generate_PUSHS(cctx, key) == FAIL)
+ return FAIL;
+ }
// Check for duplicate keys, if using string keys.
if (key != NULL)
*** ../vim-8.2.2089/src/testdir/test_vim9_expr.vim 2020-12-02
17:36:49.173409740 +0100
--- src/testdir/test_vim9_expr.vim 2020-12-04 18:58:28.299914463 +0100
***************
*** 1930,1941 ****
assert_equal(g:test_space_dict, {['']: 'empty', [' ']: 'space'})
assert_equal(g:test_hash_dict, {one: 1, two: 2})
END
CheckDefAndScriptSuccess(lines)
# legacy syntax doesn't work
CheckDefFailure(["var x = #{key: 8}"], 'E1097:', 2)
- CheckDefFailure(["var x = {'key': 8}"], 'E1014:', 1)
CheckDefFailure(["var x = 'a' .. #{a: 1}"], 'E1097:', 2)
CheckDefFailure(["var x = {a:8}"], 'E1069:', 1)
--- 1930,1942 ----
assert_equal(g:test_space_dict, {['']: 'empty', [' ']: 'space'})
assert_equal(g:test_hash_dict, {one: 1, two: 2})
+
+ assert_equal({['a a']: 1, ['b/c']: 2}, {'a a': 1, "b/c": 2})
END
CheckDefAndScriptSuccess(lines)
# legacy syntax doesn't work
CheckDefFailure(["var x = #{key: 8}"], 'E1097:', 2)
CheckDefFailure(["var x = 'a' .. #{a: 1}"], 'E1097:', 2)
CheckDefFailure(["var x = {a:8}"], 'E1069:', 1)
*** ../vim-8.2.2089/src/version.c 2020-12-04 18:09:50.648966590 +0100
--- src/version.c 2020-12-04 19:03:27.970932225 +0100
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 2090,
/**/
--
ARTHUR: Go on, Bors, chop its head off.
BORS: Right. Silly little bleeder. One rabbit stew coming up.
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/202012041812.0B4ICgLB579503%40masaka.moolenaar.net.