diff options
author | ZyX <kp-pav@yandex.ru> | 2017-12-03 16:49:30 +0300 |
---|---|---|
committer | ZyX <kp-pav@yandex.ru> | 2017-12-03 16:49:30 +0300 |
commit | c49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57 (patch) | |
tree | b7e59c416d1435725c65f8952b6e55c70544d97e /test/functional/ui/inccommand_spec.lua | |
parent | 62108c3b0be46936c83f6d4c98b44ceb5e6f77fd (diff) | |
parent | 27a577586eace687c47e7398845178208cae524a (diff) | |
download | rneovim-c49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57.tar.gz rneovim-c49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57.tar.bz2 rneovim-c49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57.zip |
Merge branch 'master' into s-dash-stdin
Diffstat (limited to 'test/functional/ui/inccommand_spec.lua')
-rw-r--r-- | test/functional/ui/inccommand_spec.lua | 1103 |
1 files changed, 969 insertions, 134 deletions
diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua index 3b31da0397..53fd17c309 100644 --- a/test/functional/ui/inccommand_spec.lua +++ b/test/functional/ui/inccommand_spec.lua @@ -1,10 +1,11 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear = helpers.clear +local command = helpers.command local curbufmeths = helpers.curbufmeths local eq = helpers.eq local eval = helpers.eval -local execute = helpers.execute +local feed_command = helpers.feed_command local expect = helpers.expect local feed = helpers.feed local insert = helpers.insert @@ -13,17 +14,54 @@ local neq = helpers.neq local ok = helpers.ok local source = helpers.source local wait = helpers.wait +local nvim = helpers.nvim local default_text = [[ Inc substitution on two lines ]] +local multiline_text = [[ + 1 2 3 + A B C + 4 5 6 + X Y Z + 7 8 9 +]] + +local multimatch_text = [[ + a bdc eae a fgl lzia r + x +]] + +local multibyte_text = [[ + £ ¥ ѫѫ PEPPERS +£ ¥ ѫfѫ + a£ ѫ¥KOL +£ ¥ libm +£ ¥ +]] + +local long_multiline_text = [[ + 1 2 3 + A B C + 4 5 6 + X Y Z + 7 8 9 + K L M + a b c + d e f + q r s + x y z + £ m n + t œ ¥ +]] + local function common_setup(screen, inccommand, text) if screen then - execute("syntax on") - execute("set nohlsearch") - execute("hi Substitute guifg=red guibg=yellow") + command("syntax on") + command("set nohlsearch") + command("hi Substitute guifg=red guibg=yellow") screen:attach() screen:set_default_attr_ids({ [1] = {foreground = Screen.colors.Fuchsia}, @@ -46,7 +84,7 @@ local function common_setup(screen, inccommand, text) }) end - execute("set inccommand=" .. (inccommand and inccommand or "")) + command("set inccommand=" .. (inccommand and inccommand or "")) if text then insert(text) @@ -91,8 +129,8 @@ describe(":substitute, 'inccommand' preserves", function() local screen = Screen.new(30,10) common_setup(screen, "split", "ABC") - execute("%s/AB/BA/") - execute("ls") + feed_command("%s/AB/BA/") + feed_command("ls") screen:expect([[ {15:~ }| @@ -111,25 +149,25 @@ describe(":substitute, 'inccommand' preserves", function() for _, case in pairs{"", "split", "nosplit"} do it("various delimiters (inccommand="..case..")", function() insert(default_text) - execute("set inccommand=" .. case) + feed_command("set inccommand=" .. case) local delims = { '/', '#', ';', '%', ',', '@', '!', ''} for _,delim in pairs(delims) do - execute("%s"..delim.."lines"..delim.."LINES"..delim.."g") + feed_command("%s"..delim.."lines"..delim.."LINES"..delim.."g") expect([[ Inc substitution on two LINES ]]) - execute("undo") + feed_command("undo") end end) end for _, case in pairs{"", "split", "nosplit"} do it("'undolevels' (inccommand="..case..")", function() - execute("set undolevels=139") - execute("setlocal undolevels=34") - execute("set inccommand=" .. case) + feed_command("set undolevels=139") + feed_command("setlocal undolevels=34") + feed_command("set inccommand=" .. case) insert("as") feed(":%s/as/glork/<enter>") eq(meths.get_option('undolevels'), 139) @@ -139,8 +177,8 @@ describe(":substitute, 'inccommand' preserves", function() for _, case in ipairs({"", "split", "nosplit"}) do it("empty undotree() (inccommand="..case..")", function() - execute("set undolevels=1000") - execute("set inccommand=" .. case) + feed_command("set undolevels=1000") + feed_command("set inccommand=" .. case) local expected_undotree = eval("undotree()") -- Start typing an incomplete :substitute command. @@ -157,8 +195,8 @@ describe(":substitute, 'inccommand' preserves", function() for _, case in ipairs({"", "split", "nosplit"}) do it("undotree() with branches (inccommand="..case..")", function() - execute("set undolevels=1000") - execute("set inccommand=" .. case) + feed_command("set undolevels=1000") + feed_command("set inccommand=" .. case) -- Make some changes. feed([[isome text 1<C-\><C-N>]]) feed([[osome text 2<C-\><C-N>]]) @@ -192,7 +230,7 @@ describe(":substitute, 'inccommand' preserves", function() for _, case in pairs{"", "split", "nosplit"} do it("b:changedtick (inccommand="..case..")", function() - execute("set inccommand=" .. case) + feed_command("set inccommand=" .. case) feed([[isome text 1<C-\><C-N>]]) feed([[osome text 2<C-\><C-N>]]) local expected_tick = eval("b:changedtick") @@ -271,18 +309,18 @@ describe(":substitute, 'inccommand' preserves undo", function() local function test_sub(substring, split, redoable) clear() - execute("set inccommand=" .. split) + feed_command("set inccommand=" .. split) insert("1") feed("o2<esc>") - execute("undo") + feed_command("undo") feed("o3<esc>") if redoable then feed("o4<esc>") - execute("undo") + feed_command("undo") end feed(substring.. "<enter>") - execute("undo") + feed_command("undo") feed("g-") expect([[ @@ -297,15 +335,15 @@ describe(":substitute, 'inccommand' preserves undo", function() local function test_notsub(substring, split, redoable) clear() - execute("set inccommand=" .. split) + feed_command("set inccommand=" .. split) insert("1") feed("o2<esc>") - execute("undo") + feed_command("undo") feed("o3<esc>") if redoable then feed("o4<esc>") - execute("undo") + feed_command("undo") end feed(substring .. "<esc>") @@ -331,7 +369,7 @@ describe(":substitute, 'inccommand' preserves undo", function() local function test_threetree(substring, split) clear() - execute("set inccommand=" .. split) + feed_command("set inccommand=" .. split) insert("1") feed("o2<esc>") @@ -424,22 +462,22 @@ describe(":substitute, 'inccommand' preserves undo", function() for _, case in pairs(cases) do clear() common_setup(nil, case, default_text) - execute("set undolevels=0") + feed_command("set undolevels=0") feed("1G0") insert("X") feed(":%s/tw/MO/<esc>") - execute("undo") + feed_command("undo") expect(default_text) - execute("undo") + feed_command("undo") expect(default_text:gsub("Inc", "XInc")) - execute("undo") + feed_command("undo") - execute("%s/tw/MO/g") + feed_command("%s/tw/MO/g") expect(default_text:gsub("tw", "MO")) - execute("undo") + feed_command("undo") expect(default_text) - execute("undo") + feed_command("undo") expect(default_text:gsub("tw", "MO")) end end) @@ -450,13 +488,13 @@ describe(":substitute, 'inccommand' preserves undo", function() for _, case in pairs(cases) do clear() common_setup(screen, case, default_text) - execute("set undolevels=1") + feed_command("set undolevels=1") feed("1G0") insert("X") feed("IY<esc>") feed(":%s/tw/MO/<esc>") - -- execute("undo") here would cause "Press ENTER". + -- feed_command("undo") here would cause "Press ENTER". feed("u") expect(default_text:gsub("Inc", "XInc")) feed("u") @@ -508,13 +546,13 @@ describe(":substitute, 'inccommand' preserves undo", function() for _, case in pairs(cases) do clear() common_setup(screen, case, default_text) - execute("set undolevels=2") + feed_command("set undolevels=2") feed("2GAx<esc>") feed("Ay<esc>") feed("Az<esc>") feed(":%s/tw/AR<esc>") - -- using execute("undo") here will result in a "Press ENTER" prompt + -- feed_command("undo") here would cause "Press ENTER". feed("u") expect(default_text:gsub("lines", "linesxy")) feed("u") @@ -601,9 +639,9 @@ describe(":substitute, 'inccommand' preserves undo", function() clear() common_setup(screen, case, default_text) - execute("set undolevels=-1") + feed_command("set undolevels=-1") feed(":%s/tw/MO/g<enter>") - -- using execute("undo") here will result in a "Press ENTER" prompt + -- feed_command("undo") here will result in a "Press ENTER" prompt feed("u") if case == "split" then screen:expect([[ @@ -637,7 +675,7 @@ describe(":substitute, 'inccommand' preserves undo", function() clear() common_setup(screen, case, default_text) - execute("set undolevels=-1") + feed_command("set undolevels=-1") feed("1G") feed("IL<esc>") feed(":%s/tw/MO/g<esc>") @@ -676,18 +714,18 @@ describe(":substitute, inccommand=split", function() end) it("preserves 'modified' buffer flag", function() - execute("set nomodified") + feed_command("set nomodified") feed(":%s/tw") screen:expect([[ Inc substitution on | - two lines | + {12:tw}o lines | | {15:~ }| {15:~ }| {11:[No Name] }| - |2| two lines | - |4| two lines | - | + |2| {12:tw}o lines | + |4| {12:tw}o lines | + {15:~ }| {15:~ }| {15:~ }| {15:~ }| @@ -699,18 +737,37 @@ describe(":substitute, inccommand=split", function() eq(0, eval("&modified")) end) + it("shows preview when cmd modifiers are present", function() + -- one modifier + feed(':keeppatterns %s/tw/to') + screen:expect([[{12:to}o lines]], nil, nil, nil, true) + feed('<Esc>') + screen:expect([[two lines]], nil, nil, nil, true) + + -- multiple modifiers + feed(':keeppatterns silent %s/tw/to') + screen:expect([[{12:to}o lines]], nil, nil, nil, true) + feed('<Esc>') + screen:expect([[two lines]], nil, nil, nil, true) + + -- non-modifier prefix + feed(':silent tabedit %s/tw/to') + screen:expect([[two lines]], nil, nil, nil, true) + feed('<Esc>') + end) + it('shows split window when typing the pattern', function() feed(":%s/tw") screen:expect([[ Inc substitution on | - two lines | + {12:tw}o lines | | {15:~ }| {15:~ }| {11:[No Name] [+] }| - |2| two lines | - |4| two lines | - | + |2| {12:tw}o lines | + |4| {12:tw}o lines | + {15:~ }| {15:~ }| {15:~ }| {15:~ }| @@ -731,7 +788,7 @@ describe(":substitute, inccommand=split", function() {11:[No Name] [+] }| |2| o lines | |4| o lines | - | + {15:~ }| {15:~ }| {15:~ }| {15:~ }| @@ -743,14 +800,14 @@ describe(":substitute, inccommand=split", function() feed("x") screen:expect([[ Inc substitution on | - xo lines | + {12:x}o lines | | {15:~ }| {15:~ }| {11:[No Name] [+] }| |2| {12:x}o lines | |4| {12:x}o lines | - | + {15:~ }| {15:~ }| {15:~ }| {15:~ }| @@ -769,7 +826,7 @@ describe(":substitute, inccommand=split", function() {11:[No Name] [+] }| |2| o lines | |4| o lines | - | + {15:~ }| {15:~ }| {15:~ }| {15:~ }| @@ -784,14 +841,14 @@ describe(":substitute, inccommand=split", function() feed(":%s/tw/XX") screen:expect([[ Inc substitution on | - XXo lines | + {12:XX}o lines | | {15:~ }| {15:~ }| {11:[No Name] [+] }| |2| {12:XX}o lines | |4| {12:XX}o lines | - | + {15:~ }| {15:~ }| {15:~ }| {15:~ }| @@ -804,10 +861,10 @@ describe(":substitute, inccommand=split", function() it('does not show split window for :s/', function() feed("2gg") feed(":s/tw") - wait() + screen:sleep(1) screen:expect([[ Inc substitution on | - two lines | + {12:tw}o lines | Inc substitution on | two lines | | @@ -825,7 +882,7 @@ describe(":substitute, inccommand=split", function() end) it("'hlsearch' is active, 'cursorline' is not", function() - execute("set hlsearch cursorline") + feed_command("set hlsearch cursorline") feed("gg") -- Assert that 'cursorline' is active. @@ -851,14 +908,14 @@ describe(":substitute, inccommand=split", function() -- 'cursorline' is NOT active during preview. screen:expect([[ Inc substitution on | - {9:tw}o lines | + {12:tw}o lines | Inc substitution on | - {9:tw}o lines | + {12:tw}o lines | | {11:[No Name] [+] }| - |2| {9:tw}o lines | - |4| {9:tw}o lines | - | + |2| {12:tw}o lines | + |4| {12:tw}o lines | + {15:~ }| {15:~ }| {15:~ }| {15:~ }| @@ -873,14 +930,14 @@ describe(":substitute, inccommand=split", function() feed('M M M<esc>') feed(':%s/M/123/g') screen:expect([[ - 123 123 123 | + {12:123} {12:123} {12:123} | Inc substitution on | two lines | Inc substitution on | two lines | {11:[No Name] [+] }| |1| {12:123} {12:123} {12:123} | - | + {15:~ }| {15:~ }| {15:~ }| {15:~ }| @@ -891,6 +948,53 @@ describe(":substitute, inccommand=split", function() ]]) end) + it("highlights nothing when there's no match", function() + feed('gg') + feed(':%s/Inx') + screen:expect([[ + Inc substitution on | + two lines | + Inc substitution on | + two lines | + | + {11:[No Name] [+] }| + | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + :%s/Inx^ | + ]]) + end) + + it('previews correctly when previewhight is small', function() + feed_command('set cwh=3') + feed_command('set hls') + feed('ggdG') + insert(string.rep('abc abc abc\n', 20)) + feed(':%s/abc/MMM/g') + screen:expect([[ + {12:MMM} {12:MMM} {12:MMM} | + {12:MMM} {12:MMM} {12:MMM} | + {12:MMM} {12:MMM} {12:MMM} | + {12:MMM} {12:MMM} {12:MMM} | + {12:MMM} {12:MMM} {12:MMM} | + {12:MMM} {12:MMM} {12:MMM} | + {12:MMM} {12:MMM} {12:MMM} | + {12:MMM} {12:MMM} {12:MMM} | + {12:MMM} {12:MMM} {12:MMM} | + {11:[No Name] [+] }| + | 1| {12:MMM} {12:MMM} {12:MMM} | + | 2| {12:MMM} {12:MMM} {12:MMM} | + | 3| {12:MMM} {12:MMM} {12:MMM} | + {10:[Preview] }| + :%s/abc/MMM/g^ | + ]]) + end) + it('actually replaces text', function() feed(":%s/tw/XX/g<Enter>") @@ -917,15 +1021,15 @@ describe(":substitute, inccommand=split", function() feed("gg") feed("2yy") feed("2000p") - execute("1,1000s/tw/BB/g") + feed_command("1,1000s/tw/BB/g") feed(":%s/tw/X") screen:expect([[ BBo lines | Inc substitution on | - Xo lines | + {12:X}o lines | Inc substitution on | - Xo lines | + {12:X}o lines | {11:[No Name] [+] }| |1001| {12:X}o lines | |1003| {12:X}o lines | @@ -983,9 +1087,9 @@ describe(":substitute, inccommand=split", function() -- Assert that 'inccommand' is ENABLED initially. eq("split", eval("&inccommand")) -- Set 'redrawtime' to minimal value, to ensure timeout is triggered. - execute("set redrawtime=1 nowrap") + feed_command("set redrawtime=1 nowrap") -- Load a big file. - execute("silent edit! test/functional/fixtures/bigfile.txt") + feed_command("silent edit! test/functional/fixtures/bigfile_oneline.txt") -- Start :substitute with a slow pattern. feed([[:%s/B.*N/x]]) wait() @@ -995,19 +1099,19 @@ describe(":substitute, inccommand=split", function() -- Assert that preview cleared (or never manifested). screen:expect([[ 0000;<control>;Cc;0;BN;;;;;N;N| - 0001;<control>;Cc;0;BN;;;;;N;S| - 0002;<control>;Cc;0;BN;;;;;N;S| - 0003;<control>;Cc;0;BN;;;;;N;E| - 0004;<control>;Cc;0;BN;;;;;N;E| - 0005;<control>;Cc;0;BN;;;;;N;E| - 0006;<control>;Cc;0;BN;;;;;N;A| - 0007;<control>;Cc;0;BN;;;;;N;B| - 0008;<control>;Cc;0;BN;;;;;N;B| - 0009;<control>;Cc;0;S;;;;;N;CH| - 000A;<control>;Cc;0;B;;;;;N;LI| - 000B;<control>;Cc;0;S;;;;;N;LI| - 000C;<control>;Cc;0;WS;;;;;N;F| - 000D;<control>;Cc;0;B;;;;;N;CA| + 2F923;CJK COMPATIBILITY IDEOGR| + 2F924;CJK COMPATIBILITY IDEOGR| + 2F925;CJK COMPATIBILITY IDEOGR| + 2F926;CJK COMPATIBILITY IDEOGR| + 2F927;CJK COMPATIBILITY IDEOGR| + 2F928;CJK COMPATIBILITY IDEOGR| + 2F929;CJK COMPATIBILITY IDEOGR| + 2F92A;CJK COMPATIBILITY IDEOGR| + 2F92B;CJK COMPATIBILITY IDEOGR| + 2F92C;CJK COMPATIBILITY IDEOGR| + 2F92D;CJK COMPATIBILITY IDEOGR| + 2F92E;CJK COMPATIBILITY IDEOGR| + 2F92F;CJK COMPATIBILITY IDEOGR| :%s/B.*N/x^ | ]]) @@ -1018,20 +1122,20 @@ describe(":substitute, inccommand=split", function() it("clears preview if non-previewable command is edited #5585", function() -- Put a non-previewable command in history. - execute("echo 'foo'") + feed_command("echo 'foo'") -- Start an incomplete :substitute command. feed(":1,2s/t/X") screen:expect([[ - Inc subsXitution on | - Xwo lines | + Inc subs{12:X}itution on | + {12:X}wo lines | Inc substitution on | two lines | | {11:[No Name] [+] }| |1| Inc subs{12:X}itution on | |2| {12:X}wo lines | - | + {15:~ }| {15:~ }| {15:~ }| {15:~ }| @@ -1079,7 +1183,7 @@ describe("inccommand=nosplit", function() end) it("works with :smagic, :snomagic", function() - execute("set hlsearch") + feed_command("set hlsearch") insert("Line *.3.* here") feed(":%smagic/3.*/X") -- start :smagic command @@ -1088,7 +1192,7 @@ describe("inccommand=nosplit", function() two lines | Inc substitution on | two lines | - Line *.X | + Line *.{12:X} | {15:~ }| {15:~ }| {15:~ }| @@ -1096,7 +1200,6 @@ describe("inccommand=nosplit", function() :%smagic/3.*/X^ | ]]) - feed([[<C-\><C-N>]]) -- cancel feed(":%snomagic/3.*/X") -- start :snomagic command screen:expect([[ @@ -1104,7 +1207,7 @@ describe("inccommand=nosplit", function() two lines | Inc substitution on | two lines | - Line *.X here | + Line *.{12:X} here | {15:~ }| {15:~ }| {15:~ }| @@ -1113,15 +1216,57 @@ describe("inccommand=nosplit", function() ]]) end) + it("shows preview when cmd modifiers are present", function() + -- one modifier + feed(':keeppatterns %s/tw/to') + screen:expect([[{12:to}o lines]], nil, nil, nil, true) + feed('<Esc>') + screen:expect([[two lines]], nil, nil, nil, true) + + -- multiple modifiers + feed(':keeppatterns silent %s/tw/to') + screen:expect([[{12:to}o lines]], nil, nil, nil, true) + feed('<Esc>') + screen:expect([[two lines]], nil, nil, nil, true) + + -- non-modifier prefix + feed(':silent tabedit %s/tw/to') + screen:expect([[two lines]], nil, nil, nil, true) + feed('<Esc>') + end) + + it("does not show window after toggling :set inccommand", function() + feed(":%s/tw/OKOK") + feed("<Esc>") + command("set icm=split") + feed(":%s/tw/OKOK") + feed("<Esc>") + command("set icm=nosplit") + feed(":%s/tw/OKOK") + wait() + screen:expect([[ + Inc substitution on | + {12:OKOK}o lines | + Inc substitution on | + {12:OKOK}o lines | + | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + :%s/tw/OKOK^ | + ]]) + end) + it('never shows preview buffer', function() - execute("set hlsearch") + feed_command("set hlsearch") feed(":%s/tw") screen:expect([[ Inc substitution on | - {9:tw}o lines | + {12:tw}o lines | Inc substitution on | - {9:tw}o lines | + {12:tw}o lines | | {15:~ }| {15:~ }| @@ -1133,9 +1278,9 @@ describe("inccommand=nosplit", function() feed("/BM") screen:expect([[ Inc substitution on | - BMo lines | + {12:BM}o lines | Inc substitution on | - BMo lines | + {12:BM}o lines | | {15:~ }| {15:~ }| @@ -1147,9 +1292,9 @@ describe("inccommand=nosplit", function() feed("/") screen:expect([[ Inc substitution on | - BMo lines | + {12:BM}o lines | Inc substitution on | - BMo lines | + {12:BM}o lines | | {15:~ }| {15:~ }| @@ -1175,13 +1320,13 @@ describe("inccommand=nosplit", function() it("clears preview if non-previewable command is edited", function() -- Put a non-previewable command in history. - execute("echo 'foo'") + feed_command("echo 'foo'") -- Start an incomplete :substitute command. feed(":1,2s/t/X") screen:expect([[ - Inc subsXitution on | - Xwo lines | + Inc subs{12:X}itution on | + {12:X}wo lines | Inc substitution on | two lines | | @@ -1224,7 +1369,7 @@ describe(":substitute, 'inccommand' with a failing expression", function() it('in the pattern does nothing', function() for _, case in pairs(cases) do refresh(case) - execute("set inccommand=" .. case) + feed_command("set inccommand=" .. case) feed(":silent! %s/tw\\(/LARD/<enter>") expect(default_text) end @@ -1236,10 +1381,10 @@ describe(":substitute, 'inccommand' with a failing expression", function() local replacements = { "\\='LARD", "\\=xx_novar__xx" } for _, repl in pairs(replacements) do - execute("set inccommand=" .. case) + feed_command("set inccommand=" .. case) feed(":silent! %s/tw/" .. repl .. "/<enter>") expect(default_text:gsub("tw", "")) - execute("undo") + feed_command("undo") end end end) @@ -1291,14 +1436,14 @@ describe("'inccommand' and :cnoremap", function() it('work with remapped characters', function() for _, case in pairs(cases) do refresh(case) - local command = "%s/lines/LINES/g" + local cmd = "%s/lines/LINES/g" - for i = 1, string.len(command) do - local c = string.sub(command, i, i) - execute("cnoremap ".. c .. " " .. c) + for i = 1, string.len(cmd) do + local c = string.sub(cmd, i, i) + feed_command("cnoremap ".. c .. " " .. c) end - execute(command) + feed_command(cmd) expect([[ Inc substitution on two LINES @@ -1309,7 +1454,7 @@ describe("'inccommand' and :cnoremap", function() it('work when mappings move the cursor', function() for _, case in pairs(cases) do refresh(case) - execute("cnoremap ,S LINES/<left><left><left><left><left><left>") + feed_command("cnoremap ,S LINES/<left><left><left><left><left><left>") feed(":%s/lines/,Sor three <enter>") expect([[ @@ -1317,21 +1462,21 @@ describe("'inccommand' and :cnoremap", function() two or three LINES ]]) - execute("cnoremap ;S /X/<left><left><left>") + feed_command("cnoremap ;S /X/<left><left><left>") feed(":%s/;SI<enter>") expect([[ Xnc substitution on two or three LXNES ]]) - execute("cnoremap ,T //Y/<left><left><left>") + feed_command("cnoremap ,T //Y/<left><left><left>") feed(":%s,TX<enter>") expect([[ Ync substitution on two or three LYNES ]]) - execute("cnoremap ;T s//Z/<left><left><left>") + feed_command("cnoremap ;T s//Z/<left><left><left>") feed(":%;TY<enter>") expect([[ Znc substitution on @@ -1343,7 +1488,7 @@ describe("'inccommand' and :cnoremap", function() it('does not work with a failing mapping', function() for _, case in pairs(cases) do refresh(case) - execute("cnoremap <expr> x execute('bwipeout!')[-1].'x'") + feed_command("cnoremap <expr> x execute('bwipeout!')[-1].'x'") feed(":%s/tw/tox<enter>") @@ -1356,7 +1501,7 @@ describe("'inccommand' and :cnoremap", function() it('work when temporarily moving the cursor', function() for _, case in pairs(cases) do refresh(case) - execute("cnoremap <expr> x cursor(1, 1)[-1].'x'") + feed_command("cnoremap <expr> x cursor(1, 1)[-1].'x'") feed(":%s/tw/tox/g<enter>") expect(default_text:gsub("tw", "tox")) @@ -1366,7 +1511,7 @@ describe("'inccommand' and :cnoremap", function() it("work when a mapping disables 'inccommand'", function() for _, case in pairs(cases) do refresh(case) - execute("cnoremap <expr> x execute('set inccommand=')[-1]") + feed_command("cnoremap <expr> x execute('set inccommand=')[-1]") feed(":%s/tw/toxa/g<enter>") expect(default_text:gsub("tw", "toa")) @@ -1440,7 +1585,7 @@ describe("'inccommand' autocommands", function() local function register_autocmd(event) meths.set_var(event .. "_fired", {}) - execute("autocmd " .. event .. " * call add(g:" .. event .. "_fired, expand('<abuf>'))") + feed_command("autocmd " .. event .. " * call add(g:" .. event .. "_fired, expand('<abuf>'))") end it('are not fired when splitting', function() @@ -1493,12 +1638,12 @@ describe("'inccommand' split windows", function() refresh() feed("gg") - execute("vsplit") - execute("split") + feed_command("vsplit") + feed_command("split") feed(":%s/tw") screen:expect([[ Inc substitution on {10:|}Inc substitution on| - two lines {10:|}two lines | + {12:tw}o lines {10:|}{12:tw}o lines | {10:|} | {15:~ }{10:|}{15:~ }| {15:~ }{10:|}{15:~ }| @@ -1513,13 +1658,13 @@ describe("'inccommand' split windows", function() {15:~ }{10:|}{15:~ }| {11:[No Name] [+] }{10:|}{15:~ }| Inc substitution on {10:|}{15:~ }| - two lines {10:|}{15:~ }| + {12:tw}o lines {10:|}{15:~ }| {10:|}{15:~ }| {15:~ }{10:|}{15:~ }| {15:~ }{10:|}{15:~ }| {10:[No Name] [+] [No Name] [+] }| - |2| two lines | - | + |2| {12:tw}o lines | + {15:~ }| {15:~ }| {15:~ }| {15:~ }| @@ -1530,14 +1675,14 @@ describe("'inccommand' split windows", function() ]]) feed("<esc>") - execute("only") - execute("split") - execute("vsplit") + feed_command("only") + feed_command("split") + feed_command("vsplit") feed(":%s/tw") screen:expect([[ Inc substitution on {10:|}Inc substitution on| - two lines {10:|}two lines | + {12:tw}o lines {10:|}{12:tw}o lines | {10:|} | {15:~ }{10:|}{15:~ }| {15:~ }{10:|}{15:~ }| @@ -1552,13 +1697,13 @@ describe("'inccommand' split windows", function() {15:~ }{10:|}{15:~ }| {11:[No Name] [+] }{10:[No Name] [+] }| Inc substitution on | - two lines | + {12:tw}o lines | | {15:~ }| {15:~ }| {10:[No Name] [+] }| - |2| two lines | - | + |2| {12:tw}o lines | + {15:~ }| {15:~ }| {15:~ }| {15:~ }| @@ -1581,13 +1726,13 @@ describe("'inccommand' split windows", function() it("are not affected by various settings", function() for _, setting in pairs(settings) do refresh() - execute("set " .. setting) + feed_command("set " .. setting) feed(":%s/tw") screen:expect([[ Inc substitution on | - two lines | + {12:tw}o lines | | {15:~ }| {15:~ }| @@ -1607,8 +1752,8 @@ describe("'inccommand' split windows", function() {15:~ }| {15:~ }| {11:[No Name] [+] }| - |2| two lines | - | + |2| {12:tw}o lines | + {15:~ }| {15:~ }| {15:~ }| {15:~ }| @@ -1621,3 +1766,693 @@ describe("'inccommand' split windows", function() end) end) + +describe("'inccommand' with 'gdefault'", function() + before_each(function() + clear() + end) + + it("does not lock up #7244", function() + common_setup(nil, "nosplit", "{") + command("set gdefault") + feed(":s/{\\n") + eq({mode='c', blocking=false}, nvim("get_mode")) + feed("/A<Enter>") + expect("A") + eq({mode='n', blocking=false}, nvim("get_mode")) + end) + + it("with multiline text and range, does not lock up #7244", function() + common_setup(nil, "nosplit", "{\n\n{") + command("set gdefault") + feed(":%s/{\\n") + eq({mode='c', blocking=false}, nvim("get_mode")) + feed("/A<Enter>") + expect("A\nA") + eq({mode='n', blocking=false}, nvim("get_mode")) + end) + + it("does not crash on zero-width matches #7485", function() + common_setup(nil, "split", default_text) + command("set gdefault") + feed("gg") + feed("Vj") + feed(":s/\\%V") + eq({mode='c', blocking=false}, nvim("get_mode")) + feed("<Esc>") + eq({mode='n', blocking=false}, nvim("get_mode")) + end) + + it("removes highlights after abort for a zero-width match", function() + local screen = Screen.new(30,5) + common_setup(screen, "nosplit", default_text) + command("set gdefault") + + feed(":%s/\\%1c/a/") + screen:expect([[ + {12:a}Inc substitution on | + {12:a}two lines | + {12:a} | + {15:~ }| + :%s/\%1c/a/^ | + ]]) + + feed("<Esc>") + screen:expect([[ + Inc substitution on | + two lines | + ^ | + {15:~ }| + | + ]]) + end) + +end) + +describe(":substitute", function() + local screen = Screen.new(30,15) + + before_each(function() + clear() + end) + + it(", inccommand=split, highlights multiline substitutions", function() + common_setup(screen, "split", multiline_text) + feed("gg") + + feed(":%s/2\\_.*X") + screen:expect([[ + 1 {12:2 3} | + {12:A B C} | + {12:4 5 6} | + {12:X} Y Z | + 7 8 9 | + {11:[No Name] [+] }| + |1| 1 {12:2 3} | + |2|{12: A B C} | + |3|{12: 4 5 6} | + |4|{12: X} Y Z | + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + :%s/2\_.*X^ | + ]]) + + feed("/MMM") + screen:expect([[ + 1 {12:MMM} Y Z | + 7 8 9 | + | + {15:~ }| + {15:~ }| + {11:[No Name] [+] }| + |1| 1 {12:MMM} Y Z | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + :%s/2\_.*X/MMM^ | + ]]) + + feed("\\rK\\rLLL") + screen:expect([[ + 1 {12:MMM} | + {12:K} | + {12:LLL} Y Z | + 7 8 9 | + | + {11:[No Name] [+] }| + |1| 1 {12:MMM} | + |2|{12: K} | + |3|{12: LLL} Y Z | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + :%s/2\_.*X/MMM\rK\rLLL^ | + ]]) + end) + + it(", inccommand=nosplit, highlights multiline substitutions", function() + common_setup(screen, "nosplit", multiline_text) + feed("gg") + + feed(":%s/2\\_.*X/MMM") + screen:expect([[ + 1 {12:MMM} Y Z | + 7 8 9 | + | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + :%s/2\_.*X/MMM^ | + ]]) + + feed("\\rK\\rLLL") + screen:expect([[ + 1 {12:MMM} | + {12:K} | + {12:LLL} Y Z | + 7 8 9 | + | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + :%s/2\_.*X/MMM\rK\rLLL^ | + ]]) + end) + + it(", inccommand=split, highlights multiple matches on a line", function() + common_setup(screen, "split", multimatch_text) + command("set gdefault") + feed("gg") + + feed(":%s/a/XLK") + screen:expect([[ + {12:XLK} bdc e{12:XLK}e {12:XLK} fgl lzi{12:XLK} r| + x | + | + {15:~ }| + {15:~ }| + {11:[No Name] [+] }| + |1| {12:XLK} bdc e{12:XLK}e {12:XLK} fgl lzi{12:X}| + {12:LK} r | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + :%s/a/XLK^ | + ]]) + end) + + it(", inccommand=nosplit, highlights multiple matches on a line", function() + common_setup(screen, "nosplit", multimatch_text) + command("set gdefault") + feed("gg") + + feed(":%s/a/XLK") + screen:expect([[ + {12:XLK} bdc e{12:XLK}e {12:XLK} fgl lzi{12:XLK} r| + x | + | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + :%s/a/XLK^ | + ]]) + end) + + it(", inccommand=split, with \\zs", function() + common_setup(screen, "split", multiline_text) + feed("gg") + + feed(":%s/[0-9]\\n\\zs[A-Z]/OKO") + screen:expect([[ + 1 2 3 | + {12:OKO} B C | + 4 5 6 | + {12:OKO} Y Z | + 7 8 9 | + {11:[No Name] [+] }| + |1| 1 2 3 | + |2| {12:OKO} B C | + |3| 4 5 6 | + |4| {12:OKO} Y Z | + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + :%s/[0-9]\n\zs[A-Z]/OKO^ | + ]]) + end) + + it(", inccommand=nosplit, with \\zs", function() + common_setup(screen, "nosplit", multiline_text) + feed("gg") + + feed(":%s/[0-9]\\n\\zs[A-Z]/OKO") + screen:expect([[ + 1 2 3 | + {12:OKO} B C | + 4 5 6 | + {12:OKO} Y Z | + 7 8 9 | + | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + :%s/[0-9]\n\zs[A-Z]/OKO^ | + ]]) + end) + + it(", inccommand=split, substitutions of different length", + function() + common_setup(screen, "split", "T T123 T2T TTT T090804\nx") + + feed(":%s/T\\([0-9]\\+\\)/\\1\\1/g") + screen:expect([[ + T {12:123123} {12:22}T TTT {12:090804090804} | + x | + {15:~ }| + {15:~ }| + {15:~ }| + {11:[No Name] [+] }| + |1| T {12:123123} {12:22}T TTT {12:090804090}| + {12:804} | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + :%s/T\([0-9]\+\)/\1\1/g^ | + ]]) + end) + + it(", inccommand=nosplit, substitutions of different length", function() + common_setup(screen, "nosplit", "T T123 T2T TTT T090804\nx") + + feed(":%s/T\\([0-9]\\+\\)/\\1\\1/g") + screen:expect([[ + T {12:123123} {12:22}T TTT {12:090804090804} | + x | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + :%s/T\([0-9]\+\)/\1\1/g^ | + ]]) + end) + + it(", inccommand=split, contraction of lines", function() + local text = [[ + T T123 T T123 T2T TT T23423424 + x + afa Q + adf la;lkd R + alx + ]] + + common_setup(screen, "split", text) + feed(":%s/[QR]\\n") + screen:expect([[ + afa {12:Q} | + adf la;lkd {12:R} | + alx | + | + {15:~ }| + {11:[No Name] [+] }| + |3| afa {12:Q} | + |4|{12: }adf la;lkd {12:R} | + |5|{12: }alx | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + :%s/[QR]\n^ | + ]]) + + feed("/KKK") + screen:expect([[ + x | + afa {12:KKK}adf la;lkd {12:KKK}alx | + | + {15:~ }| + {15:~ }| + {11:[No Name] [+] }| + |3| afa {12:KKK}adf la;lkd {12:KKK}alx | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + :%s/[QR]\n/KKK^ | + ]]) + end) + + it(", inccommand=nosplit, contraction of lines", function() + local text = [[ + T T123 T T123 T2T TT T23423424 + x + afa Q + adf la;lkd R + alx + ]] + + common_setup(screen, "nosplit", text) + feed(":%s/[QR]\\n/KKK") + screen:expect([[ + T T123 T T123 T2T TT T23423424| + x | + afa {12:KKK}adf la;lkd {12:KKK}alx | + | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + :%s/[QR]\n/KKK^ | + ]]) + end) + + it(", inccommand=split, multibyte text", function() + common_setup(screen, "split", multibyte_text) + feed(":%s/£.*ѫ/X¥¥") + screen:expect([[ + {12:X¥¥} | + a{12:X¥¥}¥KOL | + £ ¥ libm | + £ ¥ | + | + {11:[No Name] [+] }| + |1| {12:X¥¥} PEPPERS | + |2| {12:X¥¥} | + |3| a{12:X¥¥}¥KOL | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + :%s/£.*ѫ/X¥¥^ | + ]]) + + feed("\\ra££ ¥") + screen:expect([[ + {12:a££ ¥} | + a{12:X¥¥} | + {12:a££ ¥}¥KOL | + £ ¥ libm | + £ ¥ | + {11:[No Name] [+] }| + |1| {12:X¥¥} | + |2|{12: a££ ¥} PEPPERS | + |3| {12:X¥¥} | + |4|{12: a££ ¥} | + |5| a{12:X¥¥} | + |6|{12: a££ ¥}¥KOL | + {15:~ }| + {10:[Preview] }| + :%s/£.*ѫ/X¥¥\ra££ ¥^ | + ]]) + end) + + it(", inccommand=nosplit, multibyte text", function() + common_setup(screen, "nosplit", multibyte_text) + feed(":%s/£.*ѫ/X¥¥") + screen:expect([[ + {12:X¥¥} PEPPERS | + {12:X¥¥} | + a{12:X¥¥}¥KOL | + £ ¥ libm | + £ ¥ | + | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + :%s/£.*ѫ/X¥¥^ | + ]]) + + feed("\\ra££ ¥") + screen:expect([[ + {12:X¥¥} | + {12:a££ ¥} PEPPERS | + {12:X¥¥} | + {12:a££ ¥} | + a{12:X¥¥} | + {12:a££ ¥}¥KOL | + £ ¥ libm | + £ ¥ | + | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + :%s/£.*ѫ/X¥¥\ra££ ¥^ | + ]]) + end) + + it(", inccommand=split, small cmdwinheight", function() + common_setup(screen, "split", long_multiline_text) + command("set cmdwinheight=2") + + feed(":%s/[a-z]") + screen:expect([[ + X Y Z | + 7 8 9 | + K L M | + {12:a} b c | + {12:d} e f | + {12:q} r s | + {12:x} y z | + £ {12:m} n | + {12:t} œ ¥ | + | + {11:[No Name] [+] }| + | 7| {12:a} b c | + | 8| {12:d} e f | + {10:[Preview] }| + :%s/[a-z]^ | + ]]) + + feed("/JLKR £") + screen:expect([[ + X Y Z | + 7 8 9 | + K L M | + {12:JLKR £} b c | + {12:JLKR £} e f | + {12:JLKR £} r s | + {12:JLKR £} y z | + £ {12:JLKR £} n | + {12:JLKR £} œ ¥ | + | + {11:[No Name] [+] }| + | 7| {12:JLKR £} b c | + | 8| {12:JLKR £} e f | + {10:[Preview] }| + :%s/[a-z]/JLKR £^ | + ]]) + + feed("\\rѫ ab \\rXXXX") + screen:expect([[ + 7 8 9 | + K L M | + {12:JLKR £} | + {12:ѫ ab } | + {12:XXXX} b c | + {12:JLKR £} | + {12:ѫ ab } | + {12:XXXX} e f | + {12:JLKR £} | + {11:[No Name] [+] }| + | 7| {12:JLKR £} | + | 8|{12: ѫ ab } | + {10:[Preview] }| + :%s/[a-z]/JLKR £\rѫ ab \rXXX| + X^ | + ]]) + end) + + it(", inccommand=split, large cmdwinheight", function() + common_setup(screen, "split", long_multiline_text) + command("set cmdwinheight=11") + + feed(":%s/. .$") + screen:expect([[ + t {12:œ ¥} | + {11:[No Name] [+] }| + | 1| 1 {12:2 3} | + | 2| A {12:B C} | + | 3| 4 {12:5 6} | + | 4| X {12:Y Z} | + | 5| 7 {12:8 9} | + | 6| K {12:L M} | + | 7| a {12:b c} | + | 8| d {12:e f} | + | 9| q {12:r s} | + |10| x {12:y z} | + |11| £ {12:m n} | + {10:[Preview] }| + :%s/. .$^ | + ]]) + + feed("/ YYY") + screen:expect([[ + t {12: YYY} | + {11:[No Name] [+] }| + | 1| 1 {12: YYY} | + | 2| A {12: YYY} | + | 3| 4 {12: YYY} | + | 4| X {12: YYY} | + | 5| 7 {12: YYY} | + | 6| K {12: YYY} | + | 7| a {12: YYY} | + | 8| d {12: YYY} | + | 9| q {12: YYY} | + |10| x {12: YYY} | + |11| £ {12: YYY} | + {10:[Preview] }| + :%s/. .$/ YYY^ | + ]]) + + feed("\\r KKK") + screen:expect([[ + a {12: YYY} | + {11:[No Name] [+] }| + | 1| 1 {12: YYY} | + | 2|{12: KKK} | + | 3| A {12: YYY} | + | 4|{12: KKK} | + | 5| 4 {12: YYY} | + | 6|{12: KKK} | + | 7| X {12: YYY} | + | 8|{12: KKK} | + | 9| 7 {12: YYY} | + |10|{12: KKK} | + |11| K {12: YYY} | + {10:[Preview] }| + :%s/. .$/ YYY\r KKK^ | + ]]) + end) + + it(", inccommand=split, lookaround", function() + common_setup(screen, "split", "something\neverything\nsomeone") + feed([[:%s/\(some\)\@<lt>=thing/one/]]) + screen:expect([[ + some{12:one} | + everything | + someone | + {15:~ }| + {15:~ }| + {11:[No Name] [+] }| + |1| some{12:one} | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + :%s/\(some\)\@<=thing/one/^ | + ]]) + + feed("<C-c>") + wait() + feed([[:%s/\(some\)\@<lt>!thing/one/]]) + screen:expect([[ + something | + every{12:one} | + someone | + {15:~ }| + {15:~ }| + {11:[No Name] [+] }| + |2| every{12:one} | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + :%s/\(some\)\@<!thing/one/^ | + ]]) + + feed([[<C-c>]]) + wait() + feed([[:%s/some\(thing\)\@=/every/]]) + screen:expect([[ + {12:every}thing | + everything | + someone | + {15:~ }| + {15:~ }| + {11:[No Name] [+] }| + |1| {12:every}thing | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + :%s/some\(thing\)\@=/every/^ | + ]]) + + feed([[<C-c>]]) + wait() + feed([[:%s/some\(thing\)\@!/every/]]) + screen:expect([[ + everything | + {12:every}one | + {15:~ }| + {15:~ }| + {15:~ }| + {11:[No Name] [+] }| + |3| {12:every}one | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + :%s/some\(thing\)\@!/every/^ | + ]]) + end) +end) |