To: vim_dev@googlegroups.com Subject: Patch 8.2.3710 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3710 Problem: Vim9: backtick expression expanded for :global. Solution: Check the following command. Files: runtime/doc/vim9.txt, src/vim9compile.c, src/testdir/test_vim9_cmd.vim *** ../vim-8.2.3709/runtime/doc/vim9.txt 2021-11-30 16:14:44.052582170 +0000 --- runtime/doc/vim9.txt 2021-12-01 09:03:35.134951769 +0000 *************** *** 1025,1060 **** function scope. Instead, use a lambda: > def MapList(): list var list = ['aa', 'bb', 'cc', 'dd'] ! return range(1, 2)->map(( _, v) => list[v]) enddef ! The same is true for commands that are not compiled, such as `:global`. ! For these the backtick expansion can be used. Example: > def Replace() ! var newText = 'blah' ! g/pattern/s/^/`=newText`/ enddef Closures defined in a loop will share the same context. For example: > var flist: list ! for i in range(10) var inloop = i flist[i] = () => inloop endfor The "inloop" variable will exist only once, all closures put in the list refer ! to the same instance, which in the end will have the value 9. This is ! efficient. If you do want a separate context for each closure call a function ! to define it: > ! def GetFunc(i: number): func ! var inloop = i ! return () => inloop enddef var flist: list ! for i in range(10) ! flist[i] = GetFunc(i) endfor ============================================================================== --- 1128,1167 ---- function scope. Instead, use a lambda: > def MapList(): list var list = ['aa', 'bb', 'cc', 'dd'] ! return range(1, 2)->map((_, v) => list[v]) enddef ! For commands that are not compiled, such as `:edit`, backtick expansion can be ! used and it can use the local scope. Example: > def Replace() ! var fname = 'blah.txt' ! edit `=fname` enddef Closures defined in a loop will share the same context. For example: > var flist: list ! for i in range(5) var inloop = i flist[i] = () => inloop endfor + echo range(5)->map((i, _) => flist[i]()) + # Result: [4, 4, 4, 4, 4] The "inloop" variable will exist only once, all closures put in the list refer ! to the same instance, which in the end will have the value 4. This is ! efficient, also when looping many times. If you do want a separate context ! for each closure call a function to define it: > ! def GetClosure(i: number): func ! var infunc = i ! return () => infunc enddef var flist: list ! for i in range(5) ! flist[i] = GetClosure(i) endfor + echo range(5)->map((i, _) => flist[i]()) + # Result: [0, 1, 2, 3, 4] ============================================================================== *** ../vim-8.2.3709/src/vim9compile.c 2021-11-30 21:58:15.628436358 +0000 --- src/vim9compile.c 2021-12-01 09:20:02.280670246 +0000 *************** *** 9070,9075 **** --- 9070,9076 ---- int has_expr = FALSE; char_u *nextcmd = (char_u *)""; char_u *tofree = NULL; + char_u *cmd_arg = NULL; if (cctx->ctx_skip == SKIP_YES) goto theend; *************** *** 9172,9191 **** p = skip_regexp_ex(eap->arg + 1, delim, TRUE, NULL, NULL, NULL); if (*p == delim) ! { ! eap->arg = p + 1; ! has_expr = TRUE; ! } } if (eap->cmdidx == CMD_folddoopen || eap->cmdidx == CMD_folddoclosed) { exarg_T nea; CLEAR_FIELD(nea); ! nea.cmd = eap->arg; p = find_ex_command(&nea, NULL, lookup_scriptitem, NULL); ! if (nea.cmdidx <= CMD_SIZE) { has_expr = excmd_get_argt(nea.cmdidx) & (EX_XFILE | EX_EXPAND); if (has_expr) --- 9173,9192 ---- p = skip_regexp_ex(eap->arg + 1, delim, TRUE, NULL, NULL, NULL); if (*p == delim) ! cmd_arg = p + 1; } if (eap->cmdidx == CMD_folddoopen || eap->cmdidx == CMD_folddoclosed) + cmd_arg = eap->arg; + + if (cmd_arg != NULL) { exarg_T nea; CLEAR_FIELD(nea); ! nea.cmd = cmd_arg; p = find_ex_command(&nea, NULL, lookup_scriptitem, NULL); ! if (nea.cmdidx < CMD_SIZE) { has_expr = excmd_get_argt(nea.cmdidx) & (EX_XFILE | EX_EXPAND); if (has_expr) *** ../vim-8.2.3709/src/testdir/test_vim9_cmd.vim 2021-11-30 21:58:15.628436358 +0000 --- src/testdir/test_vim9_cmd.vim 2021-12-01 09:09:40.538225555 +0000 *************** *** 183,193 **** enddef def Test_global_backtick_expansion() new ! setline(1, 'xx') ! var name = 'foobar' ! g/^xx/s/.*/`=name` ! assert_equal('foobar', getline(1)) bwipe! enddef --- 183,200 ---- enddef def Test_global_backtick_expansion() + var name = 'xxx' new ! setline(1, ['one', 'two', 'three']) ! set nomod ! g/two/edit `=name` ! assert_equal('xxx', bufname()) ! bwipe! ! ! new ! setline(1, ['one', 'two', 'three']) ! g/two/s/^/`=name`/ ! assert_equal('`=name`two', getline(2)) bwipe! enddef *** ../vim-8.2.3709/src/version.c 2021-11-30 21:58:15.628436358 +0000 --- src/version.c 2021-12-01 09:25:25.971792629 +0000 *************** *** 755,756 **** --- 755,758 ---- { /* Add new patch number below this line */ + /**/ + 3710, /**/ -- ARTHUR: I've said I'm sorry about the old woman, but from the behind you looked ... DENNIS: What I object to is that you automatically treat me like an inferior... ARTHUR: Well ... I AM king. "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///