]> granicus.if.org Git - vim/commitdiff
patch 8.2.1934: Vim9: command modifiers in :def function not tested v8.2.1934
authorBram Moolenaar <Bram@vim.org>
Sun, 1 Nov 2020 16:03:37 +0000 (17:03 +0100)
committerBram Moolenaar <Bram@vim.org>
Sun, 1 Nov 2020 16:03:37 +0000 (17:03 +0100)
Problem:    Vim9: command modifiers in :def function not tested.
Solution:   Add tests.  Fix using modifier before filter command.

src/ex_docmd.c
src/testdir/test_vim9_cmd.vim
src/version.c
src/vim9compile.c

index 48da263df03a20c366ea5d8c8f3460f34bc3054b..d2cc05f59a56aa99d2d14e3a2fc6c419d276573f 100644 (file)
@@ -1782,14 +1782,27 @@ do_one_cmd(
  */
     cmd = ea.cmd;
 #ifdef FEAT_EVAL
-    // In Vim9 script a colon is required before the range.
-    may_have_range = !vim9script || starts_with_colon;
+    // In Vim9 script a colon is required before the range.  This may also be
+    // after command modifiers.
+    if (vim9script)
+    {
+       may_have_range = FALSE;
+       for (p = ea.cmd; p >= *cmdlinep; --p)
+       {
+           if (*p == ':')
+               may_have_range = TRUE;
+           if (p < ea.cmd && !VIM_ISWHITE(*p))
+               break;
+       }
+    }
+    else
+       may_have_range = TRUE;
     if (may_have_range)
 #endif
        ea.cmd = skip_range(ea.cmd, TRUE, NULL);
 
 #ifdef FEAT_EVAL
-    if (vim9script && !starts_with_colon)
+    if (vim9script && !may_have_range)
     {
        if (ea.cmd == cmd + 1 && *cmd == '$')
            // should be "$VAR = val"
index 61c47b85f94aa631a3418fdc9193497f5e698701..a355af14fe92a45ebfdd593413bdf3fb097a5fbe 100644 (file)
@@ -2,6 +2,7 @@
 
 source check.vim
 source vim9.vim
+source term_util.vim
 source view_util.vim
 
 def Test_edit_wildcards()
@@ -312,7 +313,7 @@ def Test_filter_is_not_modifier()
   assert_equal([#{x: 3, y: 4}], tags)
 enddef
 
-def Test_filter_is_recognized()
+def Test_command_modifier_filter()
   var lines =<< trim END
     final expected = "\nType Name Content\n  c  \"c   piyo"
     @a = 'hoge'
@@ -324,6 +325,135 @@ def Test_filter_is_recognized()
   CheckDefAndScriptSuccess(lines)
 enddef
 
+def Test_win_command_modifiers()
+  assert_equal(1, winnr('$'))
+
+  set splitright
+  vsplit
+  assert_equal(2, winnr())
+  close
+  aboveleft vsplit
+  assert_equal(1, winnr())
+  close
+  set splitright&
+
+  vsplit
+  assert_equal(1, winnr())
+  close
+  belowright vsplit
+  assert_equal(2, winnr())
+  close
+  rightbelow vsplit
+  assert_equal(2, winnr())
+  close
+
+  browse set
+  assert_equal('option-window', expand('%'))
+  close
+
+  vsplit
+  botright split
+  assert_equal(3, winnr())
+  assert_equal(&columns, winwidth(0))
+  close
+  close
+
+  vsplit
+  topleft split
+  assert_equal(1, winnr())
+  assert_equal(&columns, winwidth(0))
+  close
+  close
+
+  gettabinfo()->len()->assert_equal(1)
+  tab split
+  gettabinfo()->len()->assert_equal(2)
+  tabclose
+
+  vertical new
+  assert_inrange(&columns / 2 - 2, &columns / 2 + 1, winwidth(0))
+  close
+enddef
+
+func Test_command_modifier_confirm()
+  CheckNotGui
+  CheckRunVimInTerminal
+
+  " Test for saving all the modified buffers
+  let lines =<< trim END
+    call setline(1, 'changed')
+    def Getout()
+      confirm write Xfile
+    enddef
+  END
+  call writefile(lines, 'Xconfirmscript')
+  call writefile(['empty'], 'Xfile')
+  let buf = RunVimInTerminal('-S Xconfirmscript', {'rows': 8})
+  call term_sendkeys(buf, ":call Getout()\n")
+  call WaitForAssert({-> assert_match('(Y)es, \[N\]o: ', term_getline(buf, 8))}, 1000)
+  call term_sendkeys(buf, "y")
+  call StopVimInTerminal(buf)
+
+  call assert_equal(['changed'], readfile('Xfile'))
+  call delete('Xfile')
+  call delete('Xconfirmscript')
+endfunc
+
+def Test_command_modifiers_keep()
+  if has('unix')
+    def DoTest(addRflag: bool, keepMarks: bool, hasMarks: bool)
+      new
+      setline(1, ['one', 'two', 'three'])
+      normal 1Gma
+      normal 2Gmb
+      normal 3Gmc
+      if addRflag
+        set cpo+=R
+      else
+        set cpo-=R
+      endif
+      if keepMarks
+        keepmarks :%!cat
+      else
+        :%!cat
+      endif
+      if hasMarks
+        assert_equal(1, line("'a"))
+        assert_equal(2, line("'b"))
+        assert_equal(3, line("'c"))
+      else
+        assert_equal(0, line("'a"))
+        assert_equal(0, line("'b"))
+        assert_equal(0, line("'c"))
+      endif
+      quit!
+    enddef
+    DoTest(false, false, true)
+    DoTest(true, false, false)
+    DoTest(false, true, true)
+    DoTest(true, true, true)
+    set cpo&vim
+  endif
+
+  # TODO
+  # lockmarks
+  # keepalt
+  # keeppatterns
+  # keepjumps
+enddef
+
+def Test_command_modifier_other()
+  # TODO
+  # hide
+  # noautocmd
+  # noswapfile
+  # sandbox
+  # silent
+  # silent!
+  # unsilent
+  # verbose
+enddef
+
 def Test_eval_command()
   var from = 3
   var to = 5
index ca98d241c423adc8b82b2ddb492a92161673fdfd..a0c3857b8b22f25c10dbf2cd8dc528ebbcfd9d2d 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1934,
 /**/
     1933,
 /**/
index bc1481dc8457d3fd49589072973defcb9f247525..4f1b62c7b3d5cc342123d0e1d9769ebebd3d62c5 100644 (file)
@@ -2642,6 +2642,7 @@ compile_call(
                type_T      *type = ((type_T **)stack->ga_data)[
                                                            stack->ga_len - 2];
 
+               // add() can be compiled to instructions if we know the type
                if (type->tt_type == VAR_LIST)
                {
                    // inline "add(list, item)" so that the type can be checked
@@ -7173,10 +7174,6 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
                    continue;
                }
                break;
-
-           case ':':
-               starts_with_colon = TRUE;
-               break;
        }
 
        /*
@@ -7195,6 +7192,16 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
        generate_cmdmods(&cctx, &local_cmdmod);
        undo_cmdmod(&local_cmdmod);
 
+       // Check if there was a colon after the last command modifier or before
+       // the current position.
+       for (p = ea.cmd; p >= line; --p)
+       {
+           if (*p == ':')
+               starts_with_colon = TRUE;
+           if (p < ea.cmd && !VIM_ISWHITE(*p))
+               break;
+       }
+
        // Skip ":call" to get to the function name.
        p = ea.cmd;
        if (checkforcmd(&ea.cmd, "call", 3))