]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.0548: it's not possible to get a unique id for some vars v9.1.0548
authorErnie Rael <errael@raelity.com>
Tue, 9 Jul 2024 16:39:52 +0000 (18:39 +0200)
committerChristian Brabandt <cb@256bit.org>
Tue, 9 Jul 2024 16:39:52 +0000 (18:39 +0200)
Problem:  it's not possible to get a unique id for some vars
Solution: Add the id() Vim script function, which returns a unique
          identifier for object, dict, list, job, blob or channel
          variables (Ernie Rael)

fixes: #14374
closes: #15145

Signed-off-by: Ernie Rael <errael@raelity.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
runtime/doc/builtin.txt
runtime/doc/tags
runtime/doc/usr_41.txt
runtime/doc/version9.txt
src/evalfunc.c
src/testdir/test_listdict.vim
src/version.c

index 635b7b2218c0cd927182217e0c702ca1a3ca122f..9c3d7a91f8bef4798398ecb48970210f44aa71d1 100644 (file)
@@ -309,6 +309,7 @@ hlget([{name} [, {resolve}]])       List    get highlight group attributes
 hlset({list})                  Number  set highlight group attributes
 hostname()                     String  name of the machine Vim is running on
 iconv({expr}, {from}, {to})    String  convert encoding of {expr}
+id({item})                     String  get address of item as a string
 indent({lnum})                 Number  indent of line {lnum}
 index({object}, {expr} [, {start} [, {ic}]])
                                Number  index in {object} where {expr} appears
@@ -5618,6 +5619,34 @@ iconv({string}, {from}, {to})                            *iconv()*
                Return type: |String|
 
 
+id({item})                                                         *id()*
+               The result is a unique String associated with the {item} and
+               not with the {item}'s contents. It is only valid while the
+               {item} exists and is referenced. It is valid only in the
+               instance of vim that produces the result. The whole idea is
+               that `id({item})` does not change if the contents of {item}
+               changes. This is useful as a `key` for creating an identity
+               dictionary, rather than one based on equals.
+
+               This operation does not reference {item} and there is no
+               function to convert the `id` to the {item}. It may be useful to
+               have a map of `id` to {item}. The following >
+                   var referenceMap: dict<any>
+                   var id = item->id()
+                   referenceMap[id] = item
+<              prevents {item} from being garbage collected and provides a
+               way to get the {item} from the `id`.
+
+               {item} may be a List, Dictionary, Object, Job, Channel or
+               Blob. If the item is not a permitted type, or it is a null
+               value, then an empty String is returned.
+
+               Can also be used as a |method|: >
+                       GetItem()->id()
+<
+               Return type: |String|
+
+
 indent({lnum})                                                 *indent()*
                The result is a Number, which is indent of line {lnum} in the
                current buffer.  The indent is counted in spaces, the value
index be71710bc46004f9736770a7908e1e41a30641cf..adbc1458598e28117e3125723fad28f4017bda4a 100644 (file)
@@ -8302,6 +8302,7 @@ iconise   starting.txt    /*iconise*
 iconize        starting.txt    /*iconize*
 iconv()        builtin.txt     /*iconv()*
 iconv-dynamic  mbyte.txt       /*iconv-dynamic*
+id()   builtin.txt     /*id()*
 ident-search   tips.txt        /*ident-search*
 idl-syntax     syntax.txt      /*idl-syntax*
 idl.vim        syntax.txt      /*idl.vim*
index 922e80a050e51acde1684821bc9dbf039e19830a..765eab50409fcd2a736831d79392b281caef6190 100644 (file)
@@ -1408,6 +1408,8 @@ Various:                                  *various-functions*
 
        wordcount()             get byte/word/char count of buffer
 
+       id()                    get unique string for item to use as a key
+
        luaeval()               evaluate |Lua| expression
        mzeval()                evaluate |MzScheme| expression
        perleval()              evaluate Perl expression (|+perl|)
index 43de2692fa8a03735bce9979b338560a2058ca73..86ec0208ac771eed08c1ed54ae40486e0d69ee01 100644 (file)
@@ -1,4 +1,4 @@
-*version9.txt*  For Vim version 9.1.  Last change: 2024 Jul 08
+*version9.txt*  For Vim version 9.1.  Last change: 2024 Jul 09
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -41593,6 +41593,8 @@ Functions: ~
 |foreach()|            apply function to List items
 |getregion()|          get a region of text from a buffer
 |getregionpos()|       get a list of positions for a region
+|id()|                 get unique identifier for a Dict, List, Object,
+                       Channel or Blob variable
 |matchbufline()|       all the matches of a pattern in a buffer
 |matchstrlist()|       all the matches of a pattern in a List of strings
 |popup_setbuf()|       switch to a different buffer in a popup
index 5e3122dd975ccbbc2c77d1cbb54e153225d55e34..370b26bd89500c315e9f2ced1f515cceaae21b22 100644 (file)
@@ -82,6 +82,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv);
 static void f_hlID(typval_T *argvars, typval_T *rettv);
 static void f_hlexists(typval_T *argvars, typval_T *rettv);
 static void f_hostname(typval_T *argvars, typval_T *rettv);
+static void f_id(typval_T *argvars, typval_T *rettv);
 static void f_index(typval_T *argvars, typval_T *rettv);
 static void f_indexof(typval_T *argvars, typval_T *rettv);
 static void f_input(typval_T *argvars, typval_T *rettv);
@@ -2207,6 +2208,8 @@ static funcentry_T global_functions[] =
                        ret_string,         f_hostname},
     {"iconv",          3, 3, FEARG_1,      arg3_string,
                        ret_string,         f_iconv},
+    {"id",             1, 1, FEARG_1,      NULL,
+                       ret_string,         f_id},
     {"indent",         1, 1, FEARG_1,      arg1_lnum,
                        ret_number,         f_indent},
     {"index",          2, 4, FEARG_1,      arg24_index,
@@ -7516,6 +7519,40 @@ f_hostname(typval_T *argvars UNUSED, typval_T *rettv)
     rettv->vval.v_string = vim_strsave(hostname);
 }
 
+/*
+ * "id()" function
+ * Identity. Return address of item as a hex string, %p format.
+ * Currently only valid for object/container types.
+ * Return empty string if not an object.
+ */
+    void
+f_id(typval_T *argvars, typval_T *rettv)
+{
+    char_u     numbuf[NUMBUFLEN];
+
+    switch (argvars[0].v_type)
+    {
+       case VAR_LIST:
+       case VAR_DICT:
+       case VAR_OBJECT:
+       case VAR_JOB:
+       case VAR_CHANNEL:
+       case VAR_BLOB:
+           // Assume pointer value in typval_T vval union at common location.
+           if (argvars[0].vval.v_object != NULL)
+               vim_snprintf((char*)numbuf, sizeof(numbuf), "%p",
+                                           (void *)argvars[0].vval.v_object);
+           else
+               numbuf[0] = NUL;
+           break;
+       default:
+           numbuf[0] = NUL;
+    }
+
+    rettv->v_type = VAR_STRING;
+    rettv->vval.v_string = vim_strsave(numbuf);
+}
+
 /*
  * "index()" function
  */
index 0a4f88c4e5571a55bb15526c55818ed384e27aef..48217cf33eff5b98573a01b380769afca9fb20b9 100644 (file)
@@ -1619,4 +1619,34 @@ func Test_deep_nested_listdict_compare()
   call v9.CheckLegacyAndVim9Success(lines)
 endfunc
 
+" Test for using id()
+def Test_id_with_dict()
+  # demonstate a way that "id(item)" differs from "string(item)"
+  var d1 = {one: 1}
+  var d2 = {one: 1}
+  var d3 = {one: 1}
+  var idDict: dict<any>
+  idDict[id(d1)] = d1
+  idDict[id(d2)] = d2
+  idDict[id(d3)] = d3
+  assert_equal(3, idDict->len())
+
+  var stringDict: dict<any>
+  stringDict[string(d1)] = d1
+  stringDict[string(d2)] = d2
+  stringDict[string(d3)] = d3
+  assert_equal(1, stringDict->len())
+
+  assert_equal('', id(3))
+
+  assert_equal('', id(null))
+  assert_equal('', id(null_blob))
+  assert_equal('', id(null_dict))
+  assert_equal('', id(null_function))
+  assert_equal('', id(null_list))
+  assert_equal('', id(null_partial))
+  assert_equal('', id(null_string))
+  assert_equal('', id(null_channel))
+  assert_equal('', id(null_job))
+enddef
 " vim: shiftwidth=2 sts=2 expandtab
index ce6b8d60ab5a5219e4fa0d2813a98eaed5f931b4..1f334caba22ed91de579fa31d02916270978d13a 100644 (file)
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    548,
 /**/
     547,
 /**/