2016-08-12 03:05:18 -07:00
|
|
|
local helpers = require('test.functional.helpers')(after_each)
|
|
|
|
local Screen = require('test.functional.ui.screen')
|
|
|
|
local clear = helpers.clear
|
2017-04-10 12:54:19 -07:00
|
|
|
local command = helpers.command
|
2016-08-12 03:05:18 -07:00
|
|
|
local curbufmeths = helpers.curbufmeths
|
|
|
|
local eq = helpers.eq
|
|
|
|
local eval = helpers.eval
|
2017-04-08 14:12:26 -07:00
|
|
|
local feed_command = helpers.feed_command
|
2016-08-12 03:05:18 -07:00
|
|
|
local expect = helpers.expect
|
|
|
|
local feed = helpers.feed
|
|
|
|
local insert = helpers.insert
|
|
|
|
local meths = helpers.meths
|
|
|
|
local neq = helpers.neq
|
2016-11-06 08:57:44 -07:00
|
|
|
local ok = helpers.ok
|
2018-01-22 16:53:22 -07:00
|
|
|
local retry = helpers.retry
|
2016-08-12 03:05:18 -07:00
|
|
|
local source = helpers.source
|
2020-10-19 11:17:51 -07:00
|
|
|
local poke_eventloop = helpers.poke_eventloop
|
2017-09-09 02:38:19 -07:00
|
|
|
local nvim = helpers.nvim
|
2018-04-22 03:26:16 -07:00
|
|
|
local sleep = helpers.sleep
|
2022-06-22 05:51:52 -07:00
|
|
|
local testprg = helpers.testprg
|
2020-02-01 08:16:36 -07:00
|
|
|
local assert_alive = helpers.assert_alive
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
local default_text = [[
|
|
|
|
Inc substitution on
|
|
|
|
two lines
|
|
|
|
]]
|
|
|
|
|
2017-09-18 13:47:09 -07:00
|
|
|
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 œ ¥
|
|
|
|
]]
|
|
|
|
|
2016-11-06 16:59:32 -07:00
|
|
|
local function common_setup(screen, inccommand, text)
|
2016-08-12 03:05:18 -07:00
|
|
|
if screen then
|
2017-04-10 12:54:19 -07:00
|
|
|
command("syntax on")
|
|
|
|
command("set nohlsearch")
|
|
|
|
command("hi Substitute guifg=red guibg=yellow")
|
2016-08-12 03:05:18 -07:00
|
|
|
screen:attach()
|
|
|
|
screen:set_default_attr_ids({
|
|
|
|
[1] = {foreground = Screen.colors.Fuchsia},
|
|
|
|
[2] = {foreground = Screen.colors.Brown, bold = true},
|
|
|
|
[3] = {foreground = Screen.colors.SlateBlue},
|
|
|
|
[4] = {bold = true, foreground = Screen.colors.SlateBlue},
|
|
|
|
[5] = {foreground = Screen.colors.DarkCyan},
|
|
|
|
[6] = {bold = true},
|
|
|
|
[7] = {underline = true, bold = true, foreground = Screen.colors.SlateBlue},
|
|
|
|
[8] = {foreground = Screen.colors.Slateblue, underline = true},
|
|
|
|
[9] = {background = Screen.colors.Yellow},
|
|
|
|
[10] = {reverse = true},
|
|
|
|
[11] = {reverse = true, bold=true},
|
|
|
|
[12] = {foreground = Screen.colors.Red, background = Screen.colors.Yellow},
|
|
|
|
[13] = {bold = true, foreground = Screen.colors.SeaGreen},
|
|
|
|
[14] = {foreground = Screen.colors.White, background = Screen.colors.Red},
|
|
|
|
[15] = {bold=true, foreground=Screen.colors.Blue},
|
2016-11-06 15:58:53 -07:00
|
|
|
[16] = {background=Screen.colors.Grey90}, -- cursorline
|
2020-02-01 08:16:36 -07:00
|
|
|
[17] = {foreground = Screen.colors.Blue1},
|
2017-01-11 12:53:09 -07:00
|
|
|
vis = {background=Screen.colors.LightGrey}
|
2016-08-12 03:05:18 -07:00
|
|
|
})
|
|
|
|
end
|
|
|
|
|
2019-10-30 13:38:41 -07:00
|
|
|
command("set inccommand=" .. (inccommand or ""))
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
if text then
|
|
|
|
insert(text)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-10-29 15:31:40 -07:00
|
|
|
describe(":substitute, inccommand=split interactivity", function()
|
2016-11-06 08:20:03 -07:00
|
|
|
before_each(function()
|
|
|
|
clear()
|
|
|
|
common_setup(nil, "split", default_text)
|
|
|
|
end)
|
|
|
|
|
2018-01-22 16:53:22 -07:00
|
|
|
-- Test the tests: verify that the `1==bufnr('$')` assertion
|
|
|
|
-- in the "no preview" tests (below) actually means something.
|
|
|
|
it("previews interactive cmdline", function()
|
|
|
|
feed(':%s/tw/MO/g')
|
|
|
|
retry(nil, 1000, function()
|
|
|
|
eq(2, eval("bufnr('$')"))
|
|
|
|
end)
|
|
|
|
end)
|
|
|
|
|
|
|
|
it("no preview if invoked by a script", function()
|
2016-11-06 19:08:31 -07:00
|
|
|
source('%s/tw/MO/g')
|
2020-10-19 11:17:51 -07:00
|
|
|
poke_eventloop()
|
2016-11-06 08:20:03 -07:00
|
|
|
eq(1, eval("bufnr('$')"))
|
|
|
|
-- sanity check: assert the buffer state
|
|
|
|
expect(default_text:gsub("tw", "MO"))
|
|
|
|
end)
|
|
|
|
|
2018-01-22 16:53:22 -07:00
|
|
|
it("no preview if invoked by feedkeys()", function()
|
2016-11-06 19:08:31 -07:00
|
|
|
-- in a script...
|
|
|
|
source([[:call feedkeys(":%s/tw/MO/g\<CR>")]])
|
|
|
|
-- or interactively...
|
2022-05-22 07:08:37 -07:00
|
|
|
feed([[:call feedkeys(":%s/bs/BUU/g\<lt>CR>")<CR>]])
|
2016-11-06 08:20:03 -07:00
|
|
|
eq(1, eval("bufnr('$')"))
|
|
|
|
-- sanity check: assert the buffer state
|
2022-05-22 07:08:37 -07:00
|
|
|
expect(default_text:gsub("tw", "MO"):gsub("bs", "BUU"))
|
2016-11-06 08:20:03 -07:00
|
|
|
end)
|
|
|
|
end)
|
|
|
|
|
2016-11-06 16:59:32 -07:00
|
|
|
describe(":substitute, 'inccommand' preserves", function()
|
2016-08-12 03:05:18 -07:00
|
|
|
before_each(clear)
|
|
|
|
|
2016-11-06 08:57:44 -07:00
|
|
|
it('listed buffers (:ls)', function()
|
2016-08-12 03:05:18 -07:00
|
|
|
local screen = Screen.new(30,10)
|
|
|
|
common_setup(screen, "split", "ABC")
|
|
|
|
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("%s/AB/BA/")
|
|
|
|
feed_command("ls")
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
screen:expect([[
|
2022-08-17 07:19:35 -07:00
|
|
|
BAC |
|
2016-08-12 03:05:18 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2022-08-17 07:19:35 -07:00
|
|
|
{11: }|
|
2016-08-12 03:05:18 -07:00
|
|
|
:ls |
|
|
|
|
1 %a + "[No Name]" |
|
|
|
|
line 1 |
|
|
|
|
{13:Press ENTER or type command to}|
|
|
|
|
{13: continue}^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
'inccommand': Preserve curbuf->b_u_newhead.
Add tests for undotree().
Helped-by: Björn Linse <bjorn.linse@gmail.com>
When "curhead" points to a valid head, the value of "newhead" is
meaningless (and really should be set to null). The undo state for
a buffer is _logically_ the enum:
enum UndoState {
CurrentHead(head),
NewHead(head),
EmptyTree
}
nvim _represents_ this as: whenever `curbuf->b_u_curhead` is nonnull it
should be used as the current head, and `curbuf->b_u_newhead` is
ignored. If the there is a current head, then this will be redoed on the
next redo, and its parent will be undone on next undo. Only if
`b_u_curhead` is NULL, `b_u_newhead` will be used as the head to undo
(and it is not possible to redo). Also both can be NULL, to indicate an
empty undotree. (To be fair, this only strictly true when calling undo.c
from the outside, in some places _within_ a function in undo.c both
values might be meaningful)
Apparently `undotree()` breaks this non-abstraction, this _cosmetic_
issue can easily be fixed by `ex_substitute` also saving and restoring
`b_u_newhead`, but is doesn't reflect any error really how
`u_undo_and_forget` manipulates the _actual_ state of the undo tree.
2016-11-07 14:48:39 -07:00
|
|
|
for _, case in pairs{"", "split", "nosplit"} do
|
|
|
|
it("various delimiters (inccommand="..case..")", function()
|
2016-08-12 03:05:18 -07:00
|
|
|
insert(default_text)
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set inccommand=" .. case)
|
2016-08-12 03:05:18 -07:00
|
|
|
|
2020-08-09 12:02:54 -07:00
|
|
|
local delims = { '/', '#', ';', '%', ',', '@', '!' }
|
2016-08-12 03:05:18 -07:00
|
|
|
for _,delim in pairs(delims) do
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("%s"..delim.."lines"..delim.."LINES"..delim.."g")
|
2016-08-12 03:05:18 -07:00
|
|
|
expect([[
|
|
|
|
Inc substitution on
|
|
|
|
two LINES
|
|
|
|
]])
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("undo")
|
2016-08-12 03:05:18 -07:00
|
|
|
end
|
'inccommand': Preserve curbuf->b_u_newhead.
Add tests for undotree().
Helped-by: Björn Linse <bjorn.linse@gmail.com>
When "curhead" points to a valid head, the value of "newhead" is
meaningless (and really should be set to null). The undo state for
a buffer is _logically_ the enum:
enum UndoState {
CurrentHead(head),
NewHead(head),
EmptyTree
}
nvim _represents_ this as: whenever `curbuf->b_u_curhead` is nonnull it
should be used as the current head, and `curbuf->b_u_newhead` is
ignored. If the there is a current head, then this will be redoed on the
next redo, and its parent will be undone on next undo. Only if
`b_u_curhead` is NULL, `b_u_newhead` will be used as the head to undo
(and it is not possible to redo). Also both can be NULL, to indicate an
empty undotree. (To be fair, this only strictly true when calling undo.c
from the outside, in some places _within_ a function in undo.c both
values might be meaningful)
Apparently `undotree()` breaks this non-abstraction, this _cosmetic_
issue can easily be fixed by `ex_substitute` also saving and restoring
`b_u_newhead`, but is doesn't reflect any error really how
`u_undo_and_forget` manipulates the _actual_ state of the undo tree.
2016-11-07 14:48:39 -07:00
|
|
|
end)
|
|
|
|
end
|
2016-08-12 03:05:18 -07:00
|
|
|
|
'inccommand': Preserve curbuf->b_u_newhead.
Add tests for undotree().
Helped-by: Björn Linse <bjorn.linse@gmail.com>
When "curhead" points to a valid head, the value of "newhead" is
meaningless (and really should be set to null). The undo state for
a buffer is _logically_ the enum:
enum UndoState {
CurrentHead(head),
NewHead(head),
EmptyTree
}
nvim _represents_ this as: whenever `curbuf->b_u_curhead` is nonnull it
should be used as the current head, and `curbuf->b_u_newhead` is
ignored. If the there is a current head, then this will be redoed on the
next redo, and its parent will be undone on next undo. Only if
`b_u_curhead` is NULL, `b_u_newhead` will be used as the head to undo
(and it is not possible to redo). Also both can be NULL, to indicate an
empty undotree. (To be fair, this only strictly true when calling undo.c
from the outside, in some places _within_ a function in undo.c both
values might be meaningful)
Apparently `undotree()` breaks this non-abstraction, this _cosmetic_
issue can easily be fixed by `ex_substitute` also saving and restoring
`b_u_newhead`, but is doesn't reflect any error really how
`u_undo_and_forget` manipulates the _actual_ state of the undo tree.
2016-11-07 14:48:39 -07:00
|
|
|
for _, case in pairs{"", "split", "nosplit"} do
|
|
|
|
it("'undolevels' (inccommand="..case..")", function()
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set undolevels=139")
|
|
|
|
feed_command("setlocal undolevels=34")
|
|
|
|
feed_command("set inccommand=" .. case)
|
2016-08-12 03:05:18 -07:00
|
|
|
insert("as")
|
|
|
|
feed(":%s/as/glork/<enter>")
|
|
|
|
eq(meths.get_option('undolevels'), 139)
|
|
|
|
eq(curbufmeths.get_option('undolevels'), 34)
|
'inccommand': Preserve curbuf->b_u_newhead.
Add tests for undotree().
Helped-by: Björn Linse <bjorn.linse@gmail.com>
When "curhead" points to a valid head, the value of "newhead" is
meaningless (and really should be set to null). The undo state for
a buffer is _logically_ the enum:
enum UndoState {
CurrentHead(head),
NewHead(head),
EmptyTree
}
nvim _represents_ this as: whenever `curbuf->b_u_curhead` is nonnull it
should be used as the current head, and `curbuf->b_u_newhead` is
ignored. If the there is a current head, then this will be redoed on the
next redo, and its parent will be undone on next undo. Only if
`b_u_curhead` is NULL, `b_u_newhead` will be used as the head to undo
(and it is not possible to redo). Also both can be NULL, to indicate an
empty undotree. (To be fair, this only strictly true when calling undo.c
from the outside, in some places _within_ a function in undo.c both
values might be meaningful)
Apparently `undotree()` breaks this non-abstraction, this _cosmetic_
issue can easily be fixed by `ex_substitute` also saving and restoring
`b_u_newhead`, but is doesn't reflect any error really how
`u_undo_and_forget` manipulates the _actual_ state of the undo tree.
2016-11-07 14:48:39 -07:00
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
for _, case in ipairs({"", "split", "nosplit"}) do
|
|
|
|
it("empty undotree() (inccommand="..case..")", function()
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set undolevels=1000")
|
|
|
|
feed_command("set inccommand=" .. case)
|
'inccommand': Preserve curbuf->b_u_newhead.
Add tests for undotree().
Helped-by: Björn Linse <bjorn.linse@gmail.com>
When "curhead" points to a valid head, the value of "newhead" is
meaningless (and really should be set to null). The undo state for
a buffer is _logically_ the enum:
enum UndoState {
CurrentHead(head),
NewHead(head),
EmptyTree
}
nvim _represents_ this as: whenever `curbuf->b_u_curhead` is nonnull it
should be used as the current head, and `curbuf->b_u_newhead` is
ignored. If the there is a current head, then this will be redoed on the
next redo, and its parent will be undone on next undo. Only if
`b_u_curhead` is NULL, `b_u_newhead` will be used as the head to undo
(and it is not possible to redo). Also both can be NULL, to indicate an
empty undotree. (To be fair, this only strictly true when calling undo.c
from the outside, in some places _within_ a function in undo.c both
values might be meaningful)
Apparently `undotree()` breaks this non-abstraction, this _cosmetic_
issue can easily be fixed by `ex_substitute` also saving and restoring
`b_u_newhead`, but is doesn't reflect any error really how
`u_undo_and_forget` manipulates the _actual_ state of the undo tree.
2016-11-07 14:48:39 -07:00
|
|
|
local expected_undotree = eval("undotree()")
|
|
|
|
|
|
|
|
-- Start typing an incomplete :substitute command.
|
|
|
|
feed([[:%s/e/YYYY/g]])
|
2020-10-19 11:17:51 -07:00
|
|
|
poke_eventloop()
|
'inccommand': Preserve curbuf->b_u_newhead.
Add tests for undotree().
Helped-by: Björn Linse <bjorn.linse@gmail.com>
When "curhead" points to a valid head, the value of "newhead" is
meaningless (and really should be set to null). The undo state for
a buffer is _logically_ the enum:
enum UndoState {
CurrentHead(head),
NewHead(head),
EmptyTree
}
nvim _represents_ this as: whenever `curbuf->b_u_curhead` is nonnull it
should be used as the current head, and `curbuf->b_u_newhead` is
ignored. If the there is a current head, then this will be redoed on the
next redo, and its parent will be undone on next undo. Only if
`b_u_curhead` is NULL, `b_u_newhead` will be used as the head to undo
(and it is not possible to redo). Also both can be NULL, to indicate an
empty undotree. (To be fair, this only strictly true when calling undo.c
from the outside, in some places _within_ a function in undo.c both
values might be meaningful)
Apparently `undotree()` breaks this non-abstraction, this _cosmetic_
issue can easily be fixed by `ex_substitute` also saving and restoring
`b_u_newhead`, but is doesn't reflect any error really how
`u_undo_and_forget` manipulates the _actual_ state of the undo tree.
2016-11-07 14:48:39 -07:00
|
|
|
-- Cancel the :substitute.
|
|
|
|
feed([[<C-\><C-N>]])
|
|
|
|
|
|
|
|
-- The undo tree should be unchanged.
|
|
|
|
eq(expected_undotree, eval("undotree()"))
|
|
|
|
eq({}, eval("undotree()")["entries"])
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
for _, case in ipairs({"", "split", "nosplit"}) do
|
|
|
|
it("undotree() with branches (inccommand="..case..")", function()
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set undolevels=1000")
|
|
|
|
feed_command("set inccommand=" .. case)
|
'inccommand': Preserve curbuf->b_u_newhead.
Add tests for undotree().
Helped-by: Björn Linse <bjorn.linse@gmail.com>
When "curhead" points to a valid head, the value of "newhead" is
meaningless (and really should be set to null). The undo state for
a buffer is _logically_ the enum:
enum UndoState {
CurrentHead(head),
NewHead(head),
EmptyTree
}
nvim _represents_ this as: whenever `curbuf->b_u_curhead` is nonnull it
should be used as the current head, and `curbuf->b_u_newhead` is
ignored. If the there is a current head, then this will be redoed on the
next redo, and its parent will be undone on next undo. Only if
`b_u_curhead` is NULL, `b_u_newhead` will be used as the head to undo
(and it is not possible to redo). Also both can be NULL, to indicate an
empty undotree. (To be fair, this only strictly true when calling undo.c
from the outside, in some places _within_ a function in undo.c both
values might be meaningful)
Apparently `undotree()` breaks this non-abstraction, this _cosmetic_
issue can easily be fixed by `ex_substitute` also saving and restoring
`b_u_newhead`, but is doesn't reflect any error really how
`u_undo_and_forget` manipulates the _actual_ state of the undo tree.
2016-11-07 14:48:39 -07:00
|
|
|
-- Make some changes.
|
|
|
|
feed([[isome text 1<C-\><C-N>]])
|
|
|
|
feed([[osome text 2<C-\><C-N>]])
|
|
|
|
-- Add an undo branch.
|
|
|
|
feed([[u]])
|
|
|
|
-- More changes, more undo branches.
|
|
|
|
feed([[osome text 3<C-\><C-N>]])
|
|
|
|
feed([[AX<C-\><C-N>]])
|
|
|
|
feed([[...]])
|
|
|
|
feed([[uu]])
|
|
|
|
feed([[osome text 4<C-\><C-N>]])
|
|
|
|
feed([[u<C-R>u]])
|
|
|
|
feed([[osome text 5<C-\><C-N>]])
|
|
|
|
expect([[
|
|
|
|
some text 1
|
|
|
|
some text 3XX
|
|
|
|
some text 5]])
|
|
|
|
local expected_undotree = eval("undotree()")
|
|
|
|
eq(5, #expected_undotree["entries"]) -- sanity
|
2016-08-12 03:05:18 -07:00
|
|
|
|
'inccommand': Preserve curbuf->b_u_newhead.
Add tests for undotree().
Helped-by: Björn Linse <bjorn.linse@gmail.com>
When "curhead" points to a valid head, the value of "newhead" is
meaningless (and really should be set to null). The undo state for
a buffer is _logically_ the enum:
enum UndoState {
CurrentHead(head),
NewHead(head),
EmptyTree
}
nvim _represents_ this as: whenever `curbuf->b_u_curhead` is nonnull it
should be used as the current head, and `curbuf->b_u_newhead` is
ignored. If the there is a current head, then this will be redoed on the
next redo, and its parent will be undone on next undo. Only if
`b_u_curhead` is NULL, `b_u_newhead` will be used as the head to undo
(and it is not possible to redo). Also both can be NULL, to indicate an
empty undotree. (To be fair, this only strictly true when calling undo.c
from the outside, in some places _within_ a function in undo.c both
values might be meaningful)
Apparently `undotree()` breaks this non-abstraction, this _cosmetic_
issue can easily be fixed by `ex_substitute` also saving and restoring
`b_u_newhead`, but is doesn't reflect any error really how
`u_undo_and_forget` manipulates the _actual_ state of the undo tree.
2016-11-07 14:48:39 -07:00
|
|
|
-- Start typing an incomplete :substitute command.
|
|
|
|
feed([[:%s/e/YYYY/g]])
|
2020-10-19 11:17:51 -07:00
|
|
|
poke_eventloop()
|
'inccommand': Preserve curbuf->b_u_newhead.
Add tests for undotree().
Helped-by: Björn Linse <bjorn.linse@gmail.com>
When "curhead" points to a valid head, the value of "newhead" is
meaningless (and really should be set to null). The undo state for
a buffer is _logically_ the enum:
enum UndoState {
CurrentHead(head),
NewHead(head),
EmptyTree
}
nvim _represents_ this as: whenever `curbuf->b_u_curhead` is nonnull it
should be used as the current head, and `curbuf->b_u_newhead` is
ignored. If the there is a current head, then this will be redoed on the
next redo, and its parent will be undone on next undo. Only if
`b_u_curhead` is NULL, `b_u_newhead` will be used as the head to undo
(and it is not possible to redo). Also both can be NULL, to indicate an
empty undotree. (To be fair, this only strictly true when calling undo.c
from the outside, in some places _within_ a function in undo.c both
values might be meaningful)
Apparently `undotree()` breaks this non-abstraction, this _cosmetic_
issue can easily be fixed by `ex_substitute` also saving and restoring
`b_u_newhead`, but is doesn't reflect any error really how
`u_undo_and_forget` manipulates the _actual_ state of the undo tree.
2016-11-07 14:48:39 -07:00
|
|
|
-- Cancel the :substitute.
|
|
|
|
feed([[<C-\><C-N>]])
|
|
|
|
|
|
|
|
-- The undo tree should be unchanged.
|
|
|
|
eq(expected_undotree, eval("undotree()"))
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
for _, case in pairs{"", "split", "nosplit"} do
|
|
|
|
it("b:changedtick (inccommand="..case..")", function()
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set inccommand=" .. case)
|
2016-11-06 08:57:44 -07:00
|
|
|
feed([[isome text 1<C-\><C-N>]])
|
|
|
|
feed([[osome text 2<C-\><C-N>]])
|
|
|
|
local expected_tick = eval("b:changedtick")
|
|
|
|
ok(expected_tick > 0)
|
|
|
|
|
|
|
|
expect([[
|
|
|
|
some text 1
|
|
|
|
some text 2]])
|
|
|
|
feed(":%s/e/XXX/")
|
2020-10-19 11:17:51 -07:00
|
|
|
poke_eventloop()
|
2016-11-06 08:57:44 -07:00
|
|
|
|
|
|
|
eq(expected_tick, eval("b:changedtick"))
|
'inccommand': Preserve curbuf->b_u_newhead.
Add tests for undotree().
Helped-by: Björn Linse <bjorn.linse@gmail.com>
When "curhead" points to a valid head, the value of "newhead" is
meaningless (and really should be set to null). The undo state for
a buffer is _logically_ the enum:
enum UndoState {
CurrentHead(head),
NewHead(head),
EmptyTree
}
nvim _represents_ this as: whenever `curbuf->b_u_curhead` is nonnull it
should be used as the current head, and `curbuf->b_u_newhead` is
ignored. If the there is a current head, then this will be redoed on the
next redo, and its parent will be undone on next undo. Only if
`b_u_curhead` is NULL, `b_u_newhead` will be used as the head to undo
(and it is not possible to redo). Also both can be NULL, to indicate an
empty undotree. (To be fair, this only strictly true when calling undo.c
from the outside, in some places _within_ a function in undo.c both
values might be meaningful)
Apparently `undotree()` breaks this non-abstraction, this _cosmetic_
issue can easily be fixed by `ex_substitute` also saving and restoring
`b_u_newhead`, but is doesn't reflect any error really how
`u_undo_and_forget` manipulates the _actual_ state of the undo tree.
2016-11-07 14:48:39 -07:00
|
|
|
end)
|
|
|
|
end
|
2016-11-06 08:57:44 -07:00
|
|
|
|
2022-01-25 01:18:58 -07:00
|
|
|
for _, case in ipairs({'', 'split', 'nosplit'}) do
|
|
|
|
it('previous substitute string ~ (inccommand='..case..') #12109', function()
|
|
|
|
local screen = Screen.new(30,10)
|
|
|
|
common_setup(screen, case, default_text)
|
|
|
|
|
|
|
|
feed(':%s/Inc/SUB<CR>')
|
|
|
|
expect([[
|
|
|
|
SUB substitution on
|
|
|
|
two lines
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed(':%s/line/')
|
|
|
|
poke_eventloop()
|
|
|
|
feed('~')
|
|
|
|
poke_eventloop()
|
|
|
|
feed('<CR>')
|
|
|
|
expect([[
|
|
|
|
SUB substitution on
|
|
|
|
two SUBs
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed(':%s/sti/')
|
|
|
|
poke_eventloop()
|
|
|
|
feed('~')
|
|
|
|
poke_eventloop()
|
|
|
|
feed('B')
|
|
|
|
poke_eventloop()
|
|
|
|
feed('<CR>')
|
|
|
|
expect([[
|
|
|
|
SUB subSUBBtution on
|
|
|
|
two SUBs
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed(':%s/ion/NEW<CR>')
|
|
|
|
expect([[
|
|
|
|
SUB subSUBBtutNEW on
|
|
|
|
two SUBs
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed(':%s/two/')
|
|
|
|
poke_eventloop()
|
|
|
|
feed('N')
|
|
|
|
poke_eventloop()
|
|
|
|
feed('~')
|
|
|
|
poke_eventloop()
|
|
|
|
feed('<CR>')
|
|
|
|
expect([[
|
|
|
|
SUB subSUBBtutNEW on
|
|
|
|
NNEW SUBs
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed(':%s/bS/')
|
|
|
|
poke_eventloop()
|
|
|
|
feed('~')
|
|
|
|
poke_eventloop()
|
|
|
|
feed('W')
|
|
|
|
poke_eventloop()
|
|
|
|
feed('<CR>')
|
|
|
|
expect([[
|
|
|
|
SUB suNNEWWUBBtutNEW on
|
|
|
|
NNEW SUBs
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
end
|
2016-08-12 03:05:18 -07:00
|
|
|
end)
|
|
|
|
|
2016-11-06 16:59:32 -07:00
|
|
|
describe(":substitute, 'inccommand' preserves undo", function()
|
2016-08-12 03:05:18 -07:00
|
|
|
local cases = { "", "split", "nosplit" }
|
|
|
|
|
|
|
|
local substrings = {
|
|
|
|
":%s/1",
|
|
|
|
":%s/1/",
|
|
|
|
":%s/1/<bs>",
|
|
|
|
":%s/1/a",
|
|
|
|
":%s/1/a<bs>",
|
|
|
|
":%s/1/ax",
|
|
|
|
":%s/1/ax<bs>",
|
|
|
|
":%s/1/ax<bs><bs>",
|
|
|
|
":%s/1/ax<bs><bs><bs>",
|
|
|
|
":%s/1/ax/",
|
|
|
|
":%s/1/ax/<bs>",
|
|
|
|
":%s/1/ax/<bs>/",
|
|
|
|
":%s/1/ax/g",
|
|
|
|
":%s/1/ax/g<bs>",
|
|
|
|
":%s/1/ax/g<bs><bs>"
|
|
|
|
}
|
|
|
|
|
|
|
|
local function test_sub(substring, split, redoable)
|
2022-05-22 07:08:37 -07:00
|
|
|
command('bwipe!')
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set inccommand=" .. split)
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
insert("1")
|
|
|
|
feed("o2<esc>")
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("undo")
|
2016-08-12 03:05:18 -07:00
|
|
|
feed("o3<esc>")
|
|
|
|
if redoable then
|
|
|
|
feed("o4<esc>")
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("undo")
|
2016-08-12 03:05:18 -07:00
|
|
|
end
|
|
|
|
feed(substring.. "<enter>")
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("undo")
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
feed("g-")
|
|
|
|
expect([[
|
|
|
|
1
|
|
|
|
2]])
|
|
|
|
|
|
|
|
feed("g+")
|
|
|
|
expect([[
|
|
|
|
1
|
|
|
|
3]])
|
|
|
|
end
|
|
|
|
|
|
|
|
local function test_notsub(substring, split, redoable)
|
2022-05-22 07:08:37 -07:00
|
|
|
command('bwipe!')
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set inccommand=" .. split)
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
insert("1")
|
|
|
|
feed("o2<esc>")
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("undo")
|
2016-08-12 03:05:18 -07:00
|
|
|
feed("o3<esc>")
|
|
|
|
if redoable then
|
|
|
|
feed("o4<esc>")
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("undo")
|
2016-08-12 03:05:18 -07:00
|
|
|
end
|
|
|
|
feed(substring .. "<esc>")
|
|
|
|
|
|
|
|
feed("g-")
|
|
|
|
expect([[
|
|
|
|
1
|
|
|
|
2]])
|
|
|
|
|
|
|
|
feed("g+")
|
|
|
|
expect([[
|
|
|
|
1
|
|
|
|
3]])
|
|
|
|
|
|
|
|
if redoable then
|
|
|
|
feed("<c-r>")
|
|
|
|
expect([[
|
|
|
|
1
|
|
|
|
3
|
|
|
|
4]])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
local function test_threetree(substring, split)
|
2022-05-22 07:08:37 -07:00
|
|
|
command('bwipe!')
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set inccommand=" .. split)
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
insert("1")
|
|
|
|
feed("o2<esc>")
|
|
|
|
feed("o3<esc>")
|
|
|
|
feed("uu")
|
|
|
|
feed("oa<esc>")
|
|
|
|
feed("ob<esc>")
|
|
|
|
feed("uu")
|
|
|
|
feed("oA<esc>")
|
|
|
|
feed("oB<esc>")
|
|
|
|
|
|
|
|
-- This is the undo tree (x-Axis is timeline), we're at B now
|
|
|
|
-- ----------------A - B
|
|
|
|
-- /
|
|
|
|
-- | --------a - b
|
|
|
|
-- |/
|
|
|
|
-- 1 - 2 - 3
|
|
|
|
|
|
|
|
feed("2u")
|
|
|
|
feed(substring .. "<esc>")
|
2017-01-26 03:41:05 -07:00
|
|
|
expect([[
|
|
|
|
1]])
|
|
|
|
feed("g-")
|
|
|
|
expect([[
|
|
|
|
]])
|
|
|
|
feed("g+")
|
|
|
|
expect([[
|
|
|
|
1]])
|
2016-08-12 03:05:18 -07:00
|
|
|
feed("<c-r>")
|
|
|
|
expect([[
|
|
|
|
1
|
|
|
|
A]])
|
|
|
|
|
|
|
|
feed("g-") -- go to b
|
|
|
|
feed("2u")
|
|
|
|
feed(substring .. "<esc>")
|
|
|
|
feed("<c-r>")
|
|
|
|
expect([[
|
|
|
|
1
|
|
|
|
a]])
|
|
|
|
|
|
|
|
feed("g-") -- go to 3
|
|
|
|
feed("2u")
|
|
|
|
feed(substring .. "<esc>")
|
|
|
|
feed("<c-r>")
|
|
|
|
expect([[
|
|
|
|
1
|
|
|
|
2]])
|
|
|
|
end
|
|
|
|
|
2022-05-22 07:08:37 -07:00
|
|
|
before_each(clear)
|
|
|
|
|
2017-01-26 03:41:05 -07:00
|
|
|
it("at a non-leaf of the undo tree", function()
|
2016-10-30 19:50:19 -07:00
|
|
|
for _, case in pairs(cases) do
|
|
|
|
for _, str in pairs(substrings) do
|
|
|
|
for _, redoable in pairs({true}) do
|
|
|
|
test_sub(str, case, redoable)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2016-08-12 03:05:18 -07:00
|
|
|
end)
|
|
|
|
|
|
|
|
it("at a leaf of the undo tree", function()
|
|
|
|
for _, case in pairs(cases) do
|
|
|
|
for _, str in pairs(substrings) do
|
|
|
|
for _, redoable in pairs({false}) do
|
|
|
|
test_sub(str, case, redoable)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
it("when interrupting substitution", function()
|
|
|
|
for _, case in pairs(cases) do
|
|
|
|
for _, str in pairs(substrings) do
|
|
|
|
for _, redoable in pairs({true,false}) do
|
|
|
|
test_notsub(str, case, redoable)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
it("in a complex undo scenario", function()
|
|
|
|
for _, case in pairs(cases) do
|
|
|
|
for _, str in pairs(substrings) do
|
|
|
|
test_threetree(str, case)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
it('with undolevels=0', function()
|
|
|
|
for _, case in pairs(cases) do
|
|
|
|
clear()
|
|
|
|
common_setup(nil, case, default_text)
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set undolevels=0")
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
feed("1G0")
|
|
|
|
insert("X")
|
|
|
|
feed(":%s/tw/MO/<esc>")
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("undo")
|
2016-08-12 03:05:18 -07:00
|
|
|
expect(default_text)
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("undo")
|
2016-08-12 03:05:18 -07:00
|
|
|
expect(default_text:gsub("Inc", "XInc"))
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("undo")
|
2016-08-12 03:05:18 -07:00
|
|
|
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("%s/tw/MO/g")
|
2016-08-12 03:05:18 -07:00
|
|
|
expect(default_text:gsub("tw", "MO"))
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("undo")
|
2016-08-12 03:05:18 -07:00
|
|
|
expect(default_text)
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("undo")
|
2016-08-12 03:05:18 -07:00
|
|
|
expect(default_text:gsub("tw", "MO"))
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
it('with undolevels=1', function()
|
|
|
|
local screen = Screen.new(20,10)
|
|
|
|
|
|
|
|
for _, case in pairs(cases) do
|
|
|
|
clear()
|
|
|
|
common_setup(screen, case, default_text)
|
2017-06-26 05:49:15 -07:00
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
^ |
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
|
|
|
|
|
]])
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set undolevels=1")
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
feed("1G0")
|
|
|
|
insert("X")
|
|
|
|
feed("IY<esc>")
|
|
|
|
feed(":%s/tw/MO/<esc>")
|
2017-04-10 12:54:19 -07:00
|
|
|
-- feed_command("undo") here would cause "Press ENTER".
|
2016-08-12 03:05:18 -07:00
|
|
|
feed("u")
|
|
|
|
expect(default_text:gsub("Inc", "XInc"))
|
|
|
|
feed("u")
|
|
|
|
expect(default_text)
|
|
|
|
|
|
|
|
feed(":%s/tw/MO/g<enter>")
|
|
|
|
feed(":%s/MO/GO/g<enter>")
|
|
|
|
feed(":%s/GO/NO/g<enter>")
|
|
|
|
feed("u")
|
|
|
|
expect(default_text:gsub("tw", "GO"))
|
|
|
|
feed("u")
|
|
|
|
expect(default_text:gsub("tw", "MO"))
|
|
|
|
feed("u")
|
|
|
|
|
|
|
|
if case == "split" then
|
|
|
|
screen:expect([[
|
2016-11-10 07:47:14 -07:00
|
|
|
Inc substitution on |
|
2016-08-12 03:05:18 -07:00
|
|
|
^MOo lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2017-03-06 08:44:07 -07:00
|
|
|
Already ...t change |
|
2016-08-12 03:05:18 -07:00
|
|
|
]])
|
|
|
|
else
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
^MOo lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2017-03-06 08:44:07 -07:00
|
|
|
Already ...t change |
|
2016-08-12 03:05:18 -07:00
|
|
|
]])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
it('with undolevels=2', function()
|
|
|
|
local screen = Screen.new(20,10)
|
|
|
|
|
|
|
|
for _, case in pairs(cases) do
|
|
|
|
clear()
|
|
|
|
common_setup(screen, case, default_text)
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set undolevels=2")
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
feed("2GAx<esc>")
|
|
|
|
feed("Ay<esc>")
|
|
|
|
feed("Az<esc>")
|
|
|
|
feed(":%s/tw/AR<esc>")
|
2017-04-10 12:54:19 -07:00
|
|
|
-- feed_command("undo") here would cause "Press ENTER".
|
2016-08-12 03:05:18 -07:00
|
|
|
feed("u")
|
|
|
|
expect(default_text:gsub("lines", "linesxy"))
|
|
|
|
feed("u")
|
|
|
|
expect(default_text:gsub("lines", "linesx"))
|
|
|
|
feed("u")
|
|
|
|
expect(default_text)
|
|
|
|
feed("u")
|
|
|
|
|
|
|
|
if case == "split" then
|
|
|
|
screen:expect([[
|
2016-11-10 07:47:14 -07:00
|
|
|
Inc substitution on |
|
2016-08-12 03:05:18 -07:00
|
|
|
two line^s |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2017-03-06 08:44:07 -07:00
|
|
|
Already ...t change |
|
2016-08-12 03:05:18 -07:00
|
|
|
]])
|
|
|
|
else
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
two line^s |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2017-03-06 08:44:07 -07:00
|
|
|
Already ...t change |
|
2016-08-12 03:05:18 -07:00
|
|
|
]])
|
|
|
|
end
|
|
|
|
|
|
|
|
feed(":%s/tw/MO/g<enter>")
|
|
|
|
feed(":%s/MO/GO/g<enter>")
|
|
|
|
feed(":%s/GO/NO/g<enter>")
|
|
|
|
feed(":%s/NO/LO/g<enter>")
|
|
|
|
feed("u")
|
|
|
|
expect(default_text:gsub("tw", "NO"))
|
|
|
|
feed("u")
|
|
|
|
expect(default_text:gsub("tw", "GO"))
|
|
|
|
feed("u")
|
|
|
|
expect(default_text:gsub("tw", "MO"))
|
|
|
|
feed("u")
|
|
|
|
|
|
|
|
if case == "split" then
|
|
|
|
screen:expect([[
|
2016-11-10 07:47:14 -07:00
|
|
|
Inc substitution on |
|
2016-08-12 03:05:18 -07:00
|
|
|
^MOo lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2017-03-06 08:44:07 -07:00
|
|
|
Already ...t change |
|
2016-08-12 03:05:18 -07:00
|
|
|
]])
|
|
|
|
else
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
^MOo lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2017-03-06 08:44:07 -07:00
|
|
|
Already ...t change |
|
2016-08-12 03:05:18 -07:00
|
|
|
]])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
it('with undolevels=-1', function()
|
|
|
|
local screen = Screen.new(20,10)
|
|
|
|
|
|
|
|
for _, case in pairs(cases) do
|
|
|
|
clear()
|
|
|
|
common_setup(screen, case, default_text)
|
|
|
|
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set undolevels=-1")
|
2016-08-12 03:05:18 -07:00
|
|
|
feed(":%s/tw/MO/g<enter>")
|
2017-04-10 12:54:19 -07:00
|
|
|
-- feed_command("undo") here will result in a "Press ENTER" prompt
|
2016-08-12 03:05:18 -07:00
|
|
|
feed("u")
|
|
|
|
if case == "split" then
|
|
|
|
screen:expect([[
|
2016-11-10 07:47:14 -07:00
|
|
|
Inc substitution on |
|
2016-08-12 03:05:18 -07:00
|
|
|
^MOo lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2017-03-06 08:44:07 -07:00
|
|
|
Already ...t change |
|
2016-08-12 03:05:18 -07:00
|
|
|
]])
|
|
|
|
else
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
^MOo lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2017-03-06 08:44:07 -07:00
|
|
|
Already ...t change |
|
2016-08-12 03:05:18 -07:00
|
|
|
]])
|
|
|
|
end
|
|
|
|
|
|
|
|
-- repeat with an interrupted substitution
|
|
|
|
clear()
|
|
|
|
common_setup(screen, case, default_text)
|
|
|
|
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set undolevels=-1")
|
2016-08-12 03:05:18 -07:00
|
|
|
feed("1G")
|
|
|
|
feed("IL<esc>")
|
|
|
|
feed(":%s/tw/MO/g<esc>")
|
|
|
|
feed("u")
|
|
|
|
|
2016-11-14 07:13:50 -07:00
|
|
|
screen:expect([[
|
|
|
|
^LInc substitution on|
|
|
|
|
two lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2017-03-06 08:44:07 -07:00
|
|
|
Already ...t change |
|
2016-11-14 07:13:50 -07:00
|
|
|
]])
|
2016-08-12 03:05:18 -07:00
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
end)
|
|
|
|
|
2016-11-06 16:59:32 -07:00
|
|
|
describe(":substitute, inccommand=split", function()
|
2016-08-12 03:05:18 -07:00
|
|
|
local screen = Screen.new(30,15)
|
|
|
|
|
|
|
|
before_each(function()
|
|
|
|
clear()
|
|
|
|
common_setup(screen, "split", default_text .. default_text)
|
|
|
|
end)
|
|
|
|
|
2016-11-06 12:48:12 -07:00
|
|
|
it("preserves 'modified' buffer flag", function()
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set nomodified")
|
2016-11-06 12:48:12 -07:00
|
|
|
feed(":%s/tw")
|
|
|
|
screen:expect([[
|
2019-09-24 22:56:29 -07:00
|
|
|
Inc substitution on |
|
|
|
|
{12:tw}o lines |
|
2016-11-06 12:48:12 -07:00
|
|
|
Inc substitution on |
|
2017-09-24 04:57:47 -07:00
|
|
|
{12:tw}o lines |
|
2016-11-06 12:48:12 -07:00
|
|
|
|
|
|
|
|
{11:[No Name] }|
|
2017-09-24 04:57:47 -07:00
|
|
|
|2| {12:tw}o lines |
|
|
|
|
|4| {12:tw}o lines |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2016-11-06 12:48:12 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
:%s/tw^ |
|
|
|
|
]])
|
|
|
|
feed([[<C-\><C-N>]]) -- Cancel the :substitute command.
|
|
|
|
eq(0, eval("&modified"))
|
|
|
|
end)
|
|
|
|
|
2017-10-23 16:52:23 -07:00
|
|
|
it("shows preview when cmd modifiers are present", function()
|
|
|
|
-- one modifier
|
|
|
|
feed(':keeppatterns %s/tw/to')
|
2018-08-20 09:51:25 -07:00
|
|
|
screen:expect{any=[[{12:to}o lines]]}
|
2017-10-23 16:52:23 -07:00
|
|
|
feed('<Esc>')
|
2018-08-20 09:51:25 -07:00
|
|
|
screen:expect{any=[[two lines]]}
|
2017-10-23 16:52:23 -07:00
|
|
|
|
|
|
|
-- multiple modifiers
|
|
|
|
feed(':keeppatterns silent %s/tw/to')
|
2018-08-20 09:51:25 -07:00
|
|
|
screen:expect{any=[[{12:to}o lines]]}
|
2017-10-23 16:52:23 -07:00
|
|
|
feed('<Esc>')
|
2018-08-20 09:51:25 -07:00
|
|
|
screen:expect{any=[[two lines]]}
|
2017-10-23 16:52:23 -07:00
|
|
|
|
|
|
|
-- non-modifier prefix
|
|
|
|
feed(':silent tabedit %s/tw/to')
|
2017-06-26 05:49:15 -07:00
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:silent tabedit %s/tw/to^ |
|
|
|
|
]])
|
2019-03-08 15:49:48 -07:00
|
|
|
feed('<Esc>')
|
|
|
|
|
|
|
|
-- leading colons
|
|
|
|
feed(':::%s/tw/to')
|
|
|
|
screen:expect{any=[[{12:to}o lines]]}
|
|
|
|
feed('<Esc>')
|
|
|
|
screen:expect{any=[[two lines]]}
|
2017-10-23 16:52:23 -07:00
|
|
|
end)
|
|
|
|
|
2019-10-29 15:31:40 -07:00
|
|
|
it("ignores new-window modifiers when splitting the preview window", function()
|
|
|
|
-- one modifier
|
|
|
|
feed(':topleft %s/tw/to')
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
{12:to}o lines |
|
|
|
|
Inc substitution on |
|
|
|
|
{12:to}o lines |
|
|
|
|
|
|
|
|
|
{11:[No Name] [+] }|
|
|
|
|
|2| {12:to}o lines |
|
|
|
|
|4| {12:to}o lines |
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
:topleft %s/tw/to^ |
|
|
|
|
]])
|
|
|
|
feed('<Esc>')
|
|
|
|
screen:expect{any=[[two lines]]}
|
|
|
|
|
|
|
|
-- multiple modifiers
|
|
|
|
feed(':topleft vert %s/tw/to')
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
{12:to}o lines |
|
|
|
|
Inc substitution on |
|
|
|
|
{12:to}o lines |
|
|
|
|
|
|
|
|
|
{11:[No Name] [+] }|
|
|
|
|
|2| {12:to}o lines |
|
|
|
|
|4| {12:to}o lines |
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
:topleft vert %s/tw/to^ |
|
|
|
|
]])
|
|
|
|
feed('<Esc>')
|
|
|
|
screen:expect{any=[[two lines]]}
|
|
|
|
end)
|
|
|
|
|
2016-08-12 03:05:18 -07:00
|
|
|
it('shows split window when typing the pattern', function()
|
|
|
|
feed(":%s/tw")
|
|
|
|
screen:expect([[
|
2019-09-24 22:56:29 -07:00
|
|
|
Inc substitution on |
|
|
|
|
{12:tw}o lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
Inc substitution on |
|
2017-09-24 04:57:47 -07:00
|
|
|
{12:tw}o lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
|
{11:[No Name] [+] }|
|
2017-09-24 04:57:47 -07:00
|
|
|
|2| {12:tw}o lines |
|
|
|
|
|4| {12:tw}o lines |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2016-08-12 03:05:18 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2016-11-06 16:08:23 -07:00
|
|
|
{10:[Preview] }|
|
2016-08-12 03:05:18 -07:00
|
|
|
:%s/tw^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2016-11-10 07:47:14 -07:00
|
|
|
it('shows preview with empty replacement', function()
|
2016-08-12 03:05:18 -07:00
|
|
|
feed(":%s/tw/")
|
|
|
|
screen:expect([[
|
2019-09-24 22:56:29 -07:00
|
|
|
Inc substitution on |
|
|
|
|
o lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
Inc substitution on |
|
|
|
|
o lines |
|
|
|
|
|
|
|
|
|
{11:[No Name] [+] }|
|
2016-11-06 16:17:57 -07:00
|
|
|
|2| o lines |
|
|
|
|
|4| o lines |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2016-08-12 03:05:18 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2016-11-06 16:08:23 -07:00
|
|
|
{10:[Preview] }|
|
2016-08-12 03:05:18 -07:00
|
|
|
:%s/tw/^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed("x")
|
|
|
|
screen:expect([[
|
2019-09-24 22:56:29 -07:00
|
|
|
Inc substitution on |
|
|
|
|
{12:x}o lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
Inc substitution on |
|
2017-09-10 04:23:48 -07:00
|
|
|
{12:x}o lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
|
{11:[No Name] [+] }|
|
2016-11-06 16:17:57 -07:00
|
|
|
|2| {12:x}o lines |
|
|
|
|
|4| {12:x}o lines |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2016-08-12 03:05:18 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2016-11-06 16:08:23 -07:00
|
|
|
{10:[Preview] }|
|
2016-08-12 03:05:18 -07:00
|
|
|
:%s/tw/x^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed("<bs>")
|
|
|
|
screen:expect([[
|
2019-09-24 22:56:29 -07:00
|
|
|
Inc substitution on |
|
|
|
|
o lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
Inc substitution on |
|
|
|
|
o lines |
|
|
|
|
|
|
|
|
|
{11:[No Name] [+] }|
|
2016-11-06 16:17:57 -07:00
|
|
|
|2| o lines |
|
|
|
|
|4| o lines |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2016-08-12 03:05:18 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2016-11-06 16:08:23 -07:00
|
|
|
{10:[Preview] }|
|
2016-08-12 03:05:18 -07:00
|
|
|
:%s/tw/^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
it('shows split window when typing replacement', function()
|
|
|
|
feed(":%s/tw/XX")
|
|
|
|
screen:expect([[
|
2019-09-24 22:56:29 -07:00
|
|
|
Inc substitution on |
|
|
|
|
{12:XX}o lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
Inc substitution on |
|
2017-09-10 04:23:48 -07:00
|
|
|
{12:XX}o lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
|
{11:[No Name] [+] }|
|
2016-11-06 16:17:57 -07:00
|
|
|
|2| {12:XX}o lines |
|
|
|
|
|4| {12:XX}o lines |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2016-08-12 03:05:18 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2016-11-06 16:08:23 -07:00
|
|
|
{10:[Preview] }|
|
2016-08-12 03:05:18 -07:00
|
|
|
:%s/tw/XX^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
|
|
|
it('does not show split window for :s/', function()
|
|
|
|
feed("2gg")
|
|
|
|
feed(":s/tw")
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
2017-09-24 04:57:47 -07:00
|
|
|
{12:tw}o lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:s/tw^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2016-11-10 10:28:33 -07:00
|
|
|
it("'hlsearch' is active, 'cursorline' is not", function()
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set hlsearch cursorline")
|
2016-11-10 10:28:33 -07:00
|
|
|
feed("gg")
|
|
|
|
|
|
|
|
-- Assert that 'cursorline' is active.
|
2016-08-12 03:05:18 -07:00
|
|
|
screen:expect([[
|
2016-11-10 10:28:33 -07:00
|
|
|
{16:^Inc substitution on }|
|
|
|
|
two lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
Inc substitution on |
|
2016-11-10 10:28:33 -07:00
|
|
|
two lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2016-11-10 10:28:33 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:set hlsearch cursorline |
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed(":%s/tw")
|
|
|
|
-- 'cursorline' is NOT active during preview.
|
|
|
|
screen:expect([[
|
2019-09-24 22:56:29 -07:00
|
|
|
Inc substitution on |
|
2017-09-24 04:57:47 -07:00
|
|
|
{12:tw}o lines |
|
2016-11-10 10:28:33 -07:00
|
|
|
Inc substitution on |
|
2017-09-24 04:57:47 -07:00
|
|
|
{12:tw}o lines |
|
2016-11-10 10:28:33 -07:00
|
|
|
|
|
2016-08-12 03:05:18 -07:00
|
|
|
{11:[No Name] [+] }|
|
2017-09-24 04:57:47 -07:00
|
|
|
|2| {12:tw}o lines |
|
|
|
|
|4| {12:tw}o lines |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2016-08-12 03:05:18 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2016-11-06 16:08:23 -07:00
|
|
|
{10:[Preview] }|
|
2016-08-12 03:05:18 -07:00
|
|
|
:%s/tw^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2016-11-10 07:47:14 -07:00
|
|
|
it('highlights the replacement text', function()
|
2016-08-12 03:05:18 -07:00
|
|
|
feed('ggO')
|
|
|
|
feed('M M M<esc>')
|
|
|
|
feed(':%s/M/123/g')
|
|
|
|
screen:expect([[
|
2017-09-10 04:23:48 -07:00
|
|
|
{12:123} {12:123} {12:123} |
|
2016-08-12 03:05:18 -07:00
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
{11:[No Name] [+] }|
|
2016-11-06 16:17:57 -07:00
|
|
|
|1| {12:123} {12:123} {12:123} |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2016-08-12 03:05:18 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2016-11-06 16:08:23 -07:00
|
|
|
{10:[Preview] }|
|
2016-08-12 03:05:18 -07:00
|
|
|
:%s/M/123/g^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2017-10-30 17:11:35 -07:00
|
|
|
it("highlights nothing when there's no match", function()
|
2017-09-30 14:20:40 -07:00
|
|
|
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)
|
|
|
|
|
2017-08-28 12:33:31 -07:00
|
|
|
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([[
|
2017-09-10 04:23:48 -07:00
|
|
|
{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} |
|
2017-08-28 12:33:31 -07:00
|
|
|
{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)
|
|
|
|
|
2016-08-12 03:05:18 -07:00
|
|
|
it('actually replaces text', function()
|
2016-11-10 07:47:14 -07:00
|
|
|
feed(":%s/tw/XX/g<Enter>")
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
screen:expect([[
|
2016-11-10 07:47:14 -07:00
|
|
|
Inc substitution on |
|
2016-08-12 03:05:18 -07:00
|
|
|
XXo lines |
|
|
|
|
Inc substitution on |
|
|
|
|
^XXo lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:%s/tw/XX/g |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
|
|
|
it('shows correct line numbers with many lines', function()
|
|
|
|
feed("gg")
|
|
|
|
feed("2yy")
|
|
|
|
feed("2000p")
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("1,1000s/tw/BB/g")
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
feed(":%s/tw/X")
|
|
|
|
screen:expect([[
|
|
|
|
BBo lines |
|
|
|
|
Inc substitution on |
|
2017-09-10 04:23:48 -07:00
|
|
|
{12:X}o lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
Inc substitution on |
|
2017-09-10 04:23:48 -07:00
|
|
|
{12:X}o lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
{11:[No Name] [+] }|
|
2016-11-06 16:17:57 -07:00
|
|
|
|1001| {12:X}o lines |
|
|
|
|
|1003| {12:X}o lines |
|
|
|
|
|1005| {12:X}o lines |
|
|
|
|
|1007| {12:X}o lines |
|
|
|
|
|1009| {12:X}o lines |
|
|
|
|
|1011| {12:X}o lines |
|
|
|
|
|1013| {12:X}o lines |
|
2016-11-06 16:08:23 -07:00
|
|
|
{10:[Preview] }|
|
2016-08-12 03:05:18 -07:00
|
|
|
:%s/tw/X^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2016-11-06 15:58:53 -07:00
|
|
|
it('does not spam the buffer numbers', function()
|
|
|
|
-- The preview buffer is re-used (unless user deleted it), so buffer numbers
|
|
|
|
-- will not increase on each keystroke.
|
|
|
|
feed(":%s/tw/Xo/g")
|
|
|
|
-- Delete and re-type the g a few times.
|
|
|
|
feed("<BS>")
|
2020-10-19 11:17:51 -07:00
|
|
|
poke_eventloop()
|
2016-11-06 15:58:53 -07:00
|
|
|
feed("g")
|
2020-10-19 11:17:51 -07:00
|
|
|
poke_eventloop()
|
2016-11-06 15:58:53 -07:00
|
|
|
feed("<BS>")
|
2020-10-19 11:17:51 -07:00
|
|
|
poke_eventloop()
|
2016-11-06 15:58:53 -07:00
|
|
|
feed("g")
|
2020-10-19 11:17:51 -07:00
|
|
|
poke_eventloop()
|
2016-11-06 15:58:53 -07:00
|
|
|
feed("<CR>")
|
2020-10-19 11:17:51 -07:00
|
|
|
poke_eventloop()
|
2016-08-12 03:05:18 -07:00
|
|
|
feed(":vs tmp<enter>")
|
|
|
|
eq(3, helpers.call('bufnr', '$'))
|
|
|
|
end)
|
|
|
|
|
|
|
|
it('works with the n flag', function()
|
2016-11-10 07:47:14 -07:00
|
|
|
feed(":%s/tw/Mix/n<Enter>")
|
2016-08-12 03:05:18 -07:00
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
2016-11-10 07:47:14 -07:00
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
^ |
|
2016-08-12 03:05:18 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
2 matches on 2 lines |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2016-11-14 19:21:50 -07:00
|
|
|
it("deactivates if 'redrawtime' is exceeded #5602", function()
|
2022-09-18 21:37:25 -07:00
|
|
|
-- prevent redraws from 'incsearch'
|
|
|
|
meths.set_option('incsearch', false)
|
2016-11-14 19:21:50 -07:00
|
|
|
-- Assert that 'inccommand' is ENABLED initially.
|
|
|
|
eq("split", eval("&inccommand"))
|
|
|
|
-- Set 'redrawtime' to minimal value, to ensure timeout is triggered.
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set redrawtime=1 nowrap")
|
2016-11-14 19:21:50 -07:00
|
|
|
-- Load a big file.
|
2017-07-03 00:36:43 -07:00
|
|
|
feed_command("silent edit! test/functional/fixtures/bigfile_oneline.txt")
|
2016-11-14 19:21:50 -07:00
|
|
|
-- Start :substitute with a slow pattern.
|
|
|
|
feed([[:%s/B.*N/x]])
|
2020-10-19 11:17:51 -07:00
|
|
|
poke_eventloop()
|
2016-11-14 19:21:50 -07:00
|
|
|
|
|
|
|
-- Assert that 'inccommand' is DISABLED in cmdline mode.
|
|
|
|
eq("", eval("&inccommand"))
|
|
|
|
-- Assert that preview cleared (or never manifested).
|
|
|
|
screen:expect([[
|
|
|
|
0000;<control>;Cc;0;BN;;;;;N;N|
|
2017-07-03 00:36:43 -07:00
|
|
|
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|
|
2016-11-14 19:21:50 -07:00
|
|
|
:%s/B.*N/x^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
-- Assert that 'inccommand' is again ENABLED after leaving cmdline mode.
|
|
|
|
feed([[<C-\><C-N>]])
|
|
|
|
eq("split", eval("&inccommand"))
|
|
|
|
end)
|
|
|
|
|
2019-01-31 17:40:01 -07:00
|
|
|
it("deactivates if 'foldexpr' is slow #9557", function()
|
|
|
|
insert([[
|
|
|
|
a
|
|
|
|
a
|
|
|
|
a
|
|
|
|
a
|
|
|
|
a
|
|
|
|
a
|
|
|
|
a
|
|
|
|
a
|
|
|
|
]])
|
|
|
|
source([[
|
|
|
|
function! Slowfold(lnum)
|
|
|
|
sleep 5m
|
|
|
|
return a:lnum % 3
|
|
|
|
endfun
|
|
|
|
]])
|
|
|
|
command('set redrawtime=1 inccommand=split')
|
|
|
|
command('set foldmethod=expr foldexpr=Slowfold(v:lnum)')
|
|
|
|
feed(':%s/a/bcdef')
|
|
|
|
|
|
|
|
-- Assert that 'inccommand' is DISABLED in cmdline mode.
|
|
|
|
retry(nil, nil, function()
|
|
|
|
eq('', eval('&inccommand'))
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Assert that 'inccommand' is again ENABLED after leaving cmdline mode.
|
|
|
|
feed([[<C-\><C-N>]])
|
|
|
|
retry(nil, nil, function()
|
|
|
|
eq('split', eval('&inccommand'))
|
|
|
|
end)
|
|
|
|
end)
|
|
|
|
|
2016-11-14 19:21:50 -07:00
|
|
|
it("clears preview if non-previewable command is edited #5585", function()
|
2019-03-09 15:12:33 -07:00
|
|
|
feed('gg')
|
2016-11-14 19:21:50 -07:00
|
|
|
-- Put a non-previewable command in history.
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("echo 'foo'")
|
2016-11-14 19:21:50 -07:00
|
|
|
-- Start an incomplete :substitute command.
|
|
|
|
feed(":1,2s/t/X")
|
|
|
|
|
|
|
|
screen:expect([[
|
2017-09-10 04:23:48 -07:00
|
|
|
Inc subs{12:X}itution on |
|
|
|
|
{12:X}wo lines |
|
2016-11-14 19:21:50 -07:00
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
|
|
|
|
|
{11:[No Name] [+] }|
|
|
|
|
|1| Inc subs{12:X}itution on |
|
|
|
|
|2| {12:X}wo lines |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2016-11-14 19:21:50 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
:1,2s/t/X^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
-- Select the previous command.
|
|
|
|
feed("<C-P>")
|
|
|
|
-- Assert that preview was cleared.
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:echo 'foo'^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2022-05-29 05:52:53 -07:00
|
|
|
it([[preview changes correctly with c_CTRL-R_= and c_CTRL-\_e]], function()
|
|
|
|
feed('gg')
|
|
|
|
feed(":1,2s/t/X")
|
|
|
|
screen:expect([[
|
|
|
|
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:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
:1,2s/t/X^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed([[<C-R>='Y']])
|
|
|
|
-- preview should be unchanged during c_CTRL-R_= editing
|
|
|
|
screen:expect([[
|
|
|
|
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:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
={1:'Y'}^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed('<CR>')
|
|
|
|
-- preview should be changed by the result of the expression
|
|
|
|
screen:expect([[
|
|
|
|
Inc subs{12:XY}itution on |
|
|
|
|
{12:XY}wo lines |
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
|
|
|
|
|
{11:[No Name] [+] }|
|
|
|
|
|1| Inc subs{12:XY}itution on |
|
|
|
|
|2| {12:XY}wo lines |
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
:1,2s/t/XY^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed([[<C-\>e'echo']])
|
|
|
|
-- preview should be unchanged during c_CTRL-\_e editing
|
|
|
|
screen:expect([[
|
|
|
|
Inc subs{12:XY}itution on |
|
|
|
|
{12:XY}wo lines |
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
|
|
|
|
|
{11:[No Name] [+] }|
|
|
|
|
|1| Inc subs{12:XY}itution on |
|
|
|
|
|2| {12:XY}wo lines |
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
={1:'echo'}^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed('<CR>')
|
|
|
|
-- preview should be cleared if command is changed to a non-previewable one
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:echo^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2016-08-12 03:05:18 -07:00
|
|
|
end)
|
|
|
|
|
2016-11-09 04:08:49 -07:00
|
|
|
describe("inccommand=nosplit", function()
|
2016-08-12 03:05:18 -07:00
|
|
|
local screen = Screen.new(20,10)
|
|
|
|
|
|
|
|
before_each(function()
|
|
|
|
clear()
|
|
|
|
common_setup(screen, "nosplit", default_text .. default_text)
|
|
|
|
end)
|
|
|
|
|
2016-11-09 04:08:49 -07:00
|
|
|
it("works with :smagic, :snomagic", function()
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set hlsearch")
|
2016-11-09 04:08:49 -07:00
|
|
|
insert("Line *.3.* here")
|
|
|
|
|
|
|
|
feed(":%smagic/3.*/X") -- start :smagic command
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
2017-09-10 04:23:48 -07:00
|
|
|
Line *.{12:X} |
|
2016-11-09 04:08:49 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:%smagic/3.*/X^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed([[<C-\><C-N>]]) -- cancel
|
|
|
|
feed(":%snomagic/3.*/X") -- start :snomagic command
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
2017-09-10 04:23:48 -07:00
|
|
|
Line *.{12:X} here |
|
2016-11-09 04:08:49 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:%snomagic/3.*/X^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2017-10-23 16:52:23 -07:00
|
|
|
it("shows preview when cmd modifiers are present", function()
|
|
|
|
-- one modifier
|
|
|
|
feed(':keeppatterns %s/tw/to')
|
2018-08-20 09:51:25 -07:00
|
|
|
screen:expect{any=[[{12:to}o lines]]}
|
2017-10-23 16:52:23 -07:00
|
|
|
feed('<Esc>')
|
2018-08-20 09:51:25 -07:00
|
|
|
screen:expect{any=[[two lines]]}
|
2017-10-23 16:52:23 -07:00
|
|
|
|
|
|
|
-- multiple modifiers
|
|
|
|
feed(':keeppatterns silent %s/tw/to')
|
2018-08-20 09:51:25 -07:00
|
|
|
screen:expect{any=[[{12:to}o lines]]}
|
2017-10-23 16:52:23 -07:00
|
|
|
feed('<Esc>')
|
2018-08-20 09:51:25 -07:00
|
|
|
screen:expect{any=[[two lines]]}
|
2017-10-23 16:52:23 -07:00
|
|
|
|
|
|
|
-- non-modifier prefix
|
|
|
|
feed(':silent tabedit %s/tw/to')
|
2017-06-26 05:49:15 -07:00
|
|
|
screen:expect([[
|
2022-08-17 07:19:35 -07:00
|
|
|
Inc substitution on |
|
2017-06-26 05:49:15 -07:00
|
|
|
two lines |
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2022-08-17 07:19:35 -07:00
|
|
|
{11: }|
|
2017-06-26 05:49:15 -07:00
|
|
|
:silent tabedit %s/t|
|
|
|
|
w/to^ |
|
|
|
|
]])
|
2017-10-23 16:52:23 -07:00
|
|
|
end)
|
|
|
|
|
2017-10-30 17:11:35 -07:00
|
|
|
it("does not show window after toggling :set inccommand", function()
|
2017-09-18 13:47:09 -07:00
|
|
|
feed(":%s/tw/OKOK")
|
|
|
|
feed("<Esc>")
|
|
|
|
command("set icm=split")
|
|
|
|
feed(":%s/tw/OKOK")
|
|
|
|
feed("<Esc>")
|
|
|
|
command("set icm=nosplit")
|
|
|
|
feed(":%s/tw/OKOK")
|
2020-10-19 11:17:51 -07:00
|
|
|
poke_eventloop()
|
2017-09-18 13:47:09 -07:00
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
{12:OKOK}o lines |
|
|
|
|
Inc substitution on |
|
|
|
|
{12:OKOK}o lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:%s/tw/OKOK^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2016-11-09 04:08:49 -07:00
|
|
|
it('never shows preview buffer', function()
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set hlsearch")
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
feed(":%s/tw")
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
2017-09-24 04:57:47 -07:00
|
|
|
{12:tw}o lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
Inc substitution on |
|
2017-09-24 04:57:47 -07:00
|
|
|
{12:tw}o lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:%s/tw^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed("/BM")
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
2017-09-10 04:23:48 -07:00
|
|
|
{12:BM}o lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
Inc substitution on |
|
2017-09-10 04:23:48 -07:00
|
|
|
{12:BM}o lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:%s/tw/BM^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed("/")
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
2017-09-10 04:23:48 -07:00
|
|
|
{12:BM}o lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
Inc substitution on |
|
2017-09-10 04:23:48 -07:00
|
|
|
{12:BM}o lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:%s/tw/BM/^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed("<enter>")
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
BMo lines |
|
|
|
|
Inc substitution on |
|
|
|
|
^BMo lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:%s/tw/BM/ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2016-11-14 19:21:50 -07:00
|
|
|
it("clears preview if non-previewable command is edited", function()
|
|
|
|
-- Put a non-previewable command in history.
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("echo 'foo'")
|
2016-11-14 19:21:50 -07:00
|
|
|
-- Start an incomplete :substitute command.
|
|
|
|
feed(":1,2s/t/X")
|
|
|
|
|
|
|
|
screen:expect([[
|
2017-09-10 04:23:48 -07:00
|
|
|
Inc subs{12:X}itution on |
|
|
|
|
{12:X}wo lines |
|
2016-11-14 19:21:50 -07:00
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:1,2s/t/X^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
-- Select the previous command.
|
|
|
|
feed("<C-P>")
|
|
|
|
-- Assert that preview was cleared.
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:echo 'foo'^ |
|
|
|
|
]])
|
|
|
|
end)
|
2018-04-11 09:46:05 -07:00
|
|
|
|
|
|
|
it("does not execute trailing bar-separated commands #7494", function()
|
|
|
|
feed(':%s/two/three/g|q!')
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
{12:three} lines |
|
|
|
|
Inc substitution on |
|
|
|
|
{12:three} lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:%s/two/three/g|q!^ |
|
|
|
|
]])
|
|
|
|
eq(eval('v:null'), eval('v:exiting'))
|
|
|
|
end)
|
2021-09-20 07:33:10 -07:00
|
|
|
|
|
|
|
it("does not break bar-separated command #8796", function()
|
|
|
|
source([[
|
|
|
|
function! F()
|
|
|
|
if v:false | return | endif
|
|
|
|
endfun
|
|
|
|
]])
|
|
|
|
command('call timer_start(10, {-> F()}, {"repeat":-1})')
|
|
|
|
feed(':%s/')
|
|
|
|
sleep(20) -- Allow some timer activity.
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:%s/^ |
|
|
|
|
]])
|
|
|
|
end)
|
2016-08-12 03:05:18 -07:00
|
|
|
end)
|
|
|
|
|
2016-11-06 16:59:32 -07:00
|
|
|
describe(":substitute, 'inccommand' with a failing expression", function()
|
2016-08-12 03:05:18 -07:00
|
|
|
local screen = Screen.new(20,10)
|
|
|
|
local cases = { "", "split", "nosplit" }
|
|
|
|
|
|
|
|
local function refresh(case)
|
|
|
|
clear()
|
|
|
|
common_setup(screen, case, default_text)
|
|
|
|
end
|
|
|
|
|
2016-11-06 12:48:12 -07:00
|
|
|
it('in the pattern does nothing', function()
|
2016-08-12 03:05:18 -07:00
|
|
|
for _, case in pairs(cases) do
|
|
|
|
refresh(case)
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set inccommand=" .. case)
|
2016-08-12 03:05:18 -07:00
|
|
|
feed(":silent! %s/tw\\(/LARD/<enter>")
|
|
|
|
expect(default_text)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
it('in the replacement deletes the matches', function()
|
|
|
|
for _, case in pairs(cases) do
|
|
|
|
refresh(case)
|
|
|
|
local replacements = { "\\='LARD", "\\=xx_novar__xx" }
|
|
|
|
|
|
|
|
for _, repl in pairs(replacements) do
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set inccommand=" .. case)
|
2016-08-12 03:05:18 -07:00
|
|
|
feed(":silent! %s/tw/" .. repl .. "/<enter>")
|
|
|
|
expect(default_text:gsub("tw", ""))
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("undo")
|
2016-08-12 03:05:18 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
2017-01-11 12:52:11 -07:00
|
|
|
it('in the range does not error #5912', function()
|
|
|
|
for _, case in pairs(cases) do
|
|
|
|
refresh(case)
|
|
|
|
feed(':100s/')
|
|
|
|
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:100s/^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed('<enter>')
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
two lines |
|
|
|
|
^ |
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{14:E16: Invalid range} |
|
|
|
|
]])
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
2016-08-12 03:05:18 -07:00
|
|
|
end)
|
|
|
|
|
2016-11-06 16:59:32 -07:00
|
|
|
describe("'inccommand' and :cnoremap", function()
|
2016-08-12 03:05:18 -07:00
|
|
|
local cases = { "", "split", "nosplit" }
|
2022-05-22 07:08:37 -07:00
|
|
|
local screen
|
2016-08-12 03:05:18 -07:00
|
|
|
|
2022-05-22 07:08:37 -07:00
|
|
|
local function refresh(case, visual)
|
2016-08-12 03:05:18 -07:00
|
|
|
clear()
|
2022-05-22 07:08:37 -07:00
|
|
|
screen = visual and Screen.new(50,10) or nil
|
|
|
|
common_setup(screen, case, default_text)
|
2016-08-12 03:05:18 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
it('work with remapped characters', function()
|
|
|
|
for _, case in pairs(cases) do
|
|
|
|
refresh(case)
|
2017-04-10 12:54:19 -07:00
|
|
|
local cmd = "%s/lines/LINES/g"
|
2016-08-12 03:05:18 -07:00
|
|
|
|
2017-04-10 12:54:19 -07:00
|
|
|
for i = 1, string.len(cmd) do
|
|
|
|
local c = string.sub(cmd, i, i)
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("cnoremap ".. c .. " " .. c)
|
2016-08-12 03:05:18 -07:00
|
|
|
end
|
|
|
|
|
2017-04-10 12:54:19 -07:00
|
|
|
feed_command(cmd)
|
2016-08-12 03:05:18 -07:00
|
|
|
expect([[
|
|
|
|
Inc substitution on
|
|
|
|
two LINES
|
|
|
|
]])
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
2016-11-06 15:58:53 -07:00
|
|
|
it('work when mappings move the cursor', function()
|
2016-08-12 03:05:18 -07:00
|
|
|
for _, case in pairs(cases) do
|
|
|
|
refresh(case)
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("cnoremap ,S LINES/<left><left><left><left><left><left>")
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
feed(":%s/lines/,Sor three <enter>")
|
|
|
|
expect([[
|
|
|
|
Inc substitution on
|
|
|
|
two or three LINES
|
|
|
|
]])
|
|
|
|
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("cnoremap ;S /X/<left><left><left>")
|
2016-08-12 03:05:18 -07:00
|
|
|
feed(":%s/;SI<enter>")
|
|
|
|
expect([[
|
|
|
|
Xnc substitution on
|
|
|
|
two or three LXNES
|
|
|
|
]])
|
|
|
|
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("cnoremap ,T //Y/<left><left><left>")
|
2016-08-12 03:05:18 -07:00
|
|
|
feed(":%s,TX<enter>")
|
|
|
|
expect([[
|
|
|
|
Ync substitution on
|
|
|
|
two or three LYNES
|
|
|
|
]])
|
|
|
|
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("cnoremap ;T s//Z/<left><left><left>")
|
2016-08-12 03:05:18 -07:00
|
|
|
feed(":%;TY<enter>")
|
|
|
|
expect([[
|
|
|
|
Znc substitution on
|
|
|
|
two or three LZNES
|
|
|
|
]])
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
2018-10-17 00:51:09 -07:00
|
|
|
it('still works with a broken mapping', function()
|
2016-08-12 03:05:18 -07:00
|
|
|
for _, case in pairs(cases) do
|
2022-05-22 07:08:37 -07:00
|
|
|
refresh(case, true)
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("cnoremap <expr> x execute('bwipeout!')[-1].'x'")
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
feed(":%s/tw/tox<enter>")
|
2022-07-06 13:47:18 -07:00
|
|
|
screen:expect{any=[[{14:^E565:]]}
|
2022-05-22 07:08:37 -07:00
|
|
|
feed('<c-c>')
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
-- error thrown b/c of the mapping
|
2022-07-06 13:47:18 -07:00
|
|
|
neq(nil, eval('v:errmsg'):find('^E565:'))
|
2018-10-14 01:22:40 -07:00
|
|
|
expect([[
|
|
|
|
Inc substitution on
|
|
|
|
toxo lines
|
|
|
|
]])
|
2016-08-12 03:05:18 -07:00
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
it('work when temporarily moving the cursor', function()
|
|
|
|
for _, case in pairs(cases) do
|
|
|
|
refresh(case)
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("cnoremap <expr> x cursor(1, 1)[-1].'x'")
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
feed(":%s/tw/tox/g<enter>")
|
|
|
|
expect(default_text:gsub("tw", "tox"))
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
2016-11-06 16:59:32 -07:00
|
|
|
it("work when a mapping disables 'inccommand'", function()
|
2016-08-12 03:05:18 -07:00
|
|
|
for _, case in pairs(cases) do
|
|
|
|
refresh(case)
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("cnoremap <expr> x execute('set inccommand=')[-1]")
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
feed(":%s/tw/toxa/g<enter>")
|
|
|
|
expect(default_text:gsub("tw", "toa"))
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
it('work with a complex mapping', function()
|
|
|
|
for _, case in pairs(cases) do
|
|
|
|
refresh(case)
|
|
|
|
source([[cnoremap x <C-\>eextend(g:, {'fo': getcmdline()})
|
|
|
|
\.fo<CR><C-c>:new<CR>:bw!<CR>:<C-r>=remove(g:, 'fo')<CR>x]])
|
|
|
|
|
|
|
|
feed(":%s/tw/tox")
|
|
|
|
feed("/<enter>")
|
|
|
|
expect(default_text:gsub("tw", "tox"))
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
end)
|
|
|
|
|
2016-11-09 04:08:49 -07:00
|
|
|
describe("'inccommand' autocommands", function()
|
2016-08-12 03:05:18 -07:00
|
|
|
before_each(clear)
|
|
|
|
|
|
|
|
-- keys are events to be tested
|
2016-11-16 16:33:45 -07:00
|
|
|
-- values are arrays like
|
|
|
|
-- { open = { 1 }, close = { 2, 3} }
|
|
|
|
-- which would mean that during the test below the event fires for
|
2016-11-06 16:59:32 -07:00
|
|
|
-- buffer 1 when opening the preview window, and for buffers 2 and 3
|
|
|
|
-- when closing the preview window
|
2016-08-12 03:05:18 -07:00
|
|
|
local eventsExpected = {
|
|
|
|
BufAdd = {},
|
|
|
|
BufDelete = {},
|
|
|
|
BufEnter = {},
|
|
|
|
BufFilePost = {},
|
|
|
|
BufFilePre = {},
|
|
|
|
BufHidden = {},
|
|
|
|
BufLeave = {},
|
|
|
|
BufNew = {},
|
|
|
|
BufNewFile = {},
|
|
|
|
BufRead = {},
|
|
|
|
BufReadCmd = {},
|
|
|
|
BufReadPre = {},
|
|
|
|
BufUnload = {},
|
|
|
|
BufWinEnter = {},
|
|
|
|
BufWinLeave = {},
|
|
|
|
BufWipeout = {},
|
|
|
|
BufWrite = {},
|
|
|
|
BufWriteCmd = {},
|
|
|
|
BufWritePost = {},
|
|
|
|
Syntax = {},
|
|
|
|
FileType = {},
|
|
|
|
WinEnter = {},
|
|
|
|
WinLeave = {},
|
|
|
|
CmdwinEnter = {},
|
|
|
|
CmdwinLeave = {},
|
|
|
|
}
|
|
|
|
|
|
|
|
local function bufferlist(t)
|
|
|
|
local s = ""
|
|
|
|
for _, buffer in pairs(t) do
|
|
|
|
s = s .. ", " .. tostring(buffer)
|
|
|
|
end
|
|
|
|
return s
|
|
|
|
end
|
|
|
|
|
|
|
|
-- fill the table with default values
|
|
|
|
for event, _ in pairs(eventsExpected) do
|
|
|
|
eventsExpected[event].open = eventsExpected[event].open or {}
|
|
|
|
eventsExpected[event].close = eventsExpected[event].close or {}
|
|
|
|
end
|
|
|
|
|
|
|
|
local function register_autocmd(event)
|
|
|
|
meths.set_var(event .. "_fired", {})
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("autocmd " .. event .. " * call add(g:" .. event .. "_fired, expand('<abuf>'))")
|
2016-08-12 03:05:18 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
it('are not fired when splitting', function()
|
|
|
|
common_setup(nil, "split", default_text)
|
|
|
|
|
|
|
|
local eventsObserved = {}
|
|
|
|
for event, _ in pairs(eventsExpected) do
|
|
|
|
eventsObserved[event] = {}
|
|
|
|
register_autocmd(event)
|
|
|
|
end
|
|
|
|
|
|
|
|
feed(":%s/tw")
|
|
|
|
|
|
|
|
for event, _ in pairs(eventsExpected) do
|
|
|
|
eventsObserved[event].open = meths.get_var(event .. "_fired")
|
|
|
|
meths.set_var(event .. "_fired", {})
|
|
|
|
end
|
|
|
|
|
|
|
|
feed("/<enter>")
|
|
|
|
|
|
|
|
for event, _ in pairs(eventsExpected) do
|
2016-11-16 16:33:45 -07:00
|
|
|
eventsObserved[event].close = meths.get_var(event .. "_fired")
|
2016-08-12 03:05:18 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
for event, _ in pairs(eventsExpected) do
|
|
|
|
eq(event .. bufferlist(eventsExpected[event].open),
|
|
|
|
event .. bufferlist(eventsObserved[event].open))
|
|
|
|
eq(event .. bufferlist(eventsExpected[event].close),
|
|
|
|
event .. bufferlist(eventsObserved[event].close))
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
end)
|
|
|
|
|
2016-11-09 04:08:49 -07:00
|
|
|
describe("'inccommand' split windows", function()
|
2016-08-12 03:05:18 -07:00
|
|
|
local screen
|
|
|
|
local function refresh()
|
|
|
|
clear()
|
|
|
|
screen = Screen.new(40,30)
|
|
|
|
common_setup(screen, "split", default_text)
|
|
|
|
end
|
|
|
|
|
2016-10-30 19:50:19 -07:00
|
|
|
it('work after more splits', function()
|
2016-08-12 03:05:18 -07:00
|
|
|
refresh()
|
|
|
|
|
2016-11-10 07:47:14 -07:00
|
|
|
feed("gg")
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("vsplit")
|
|
|
|
feed_command("split")
|
2016-08-12 03:05:18 -07:00
|
|
|
feed(":%s/tw")
|
|
|
|
screen:expect([[
|
2022-05-15 09:34:44 -07:00
|
|
|
Inc substitution on │Inc substitution on|
|
|
|
|
{12:tw}o lines │{12:tw}o lines |
|
|
|
|
│ |
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{11:[No Name] [+] }│{15:~ }|
|
|
|
|
Inc substitution on │{15:~ }|
|
|
|
|
{12:tw}o lines │{15:~ }|
|
|
|
|
│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
2016-08-12 03:05:18 -07:00
|
|
|
{10:[No Name] [+] [No Name] [+] }|
|
2017-09-24 04:57:47 -07:00
|
|
|
|2| {12:tw}o lines |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2016-08-12 03:05:18 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2016-11-06 16:08:23 -07:00
|
|
|
{10:[Preview] }|
|
2016-08-12 03:05:18 -07:00
|
|
|
:%s/tw^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed("<esc>")
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("only")
|
|
|
|
feed_command("split")
|
|
|
|
feed_command("vsplit")
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
feed(":%s/tw")
|
|
|
|
screen:expect([[
|
2022-05-15 09:34:44 -07:00
|
|
|
Inc substitution on │Inc substitution on|
|
|
|
|
{12:tw}o lines │{12:tw}o lines |
|
|
|
|
│ |
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
|
|
|
{15:~ }│{15:~ }|
|
2016-08-12 03:05:18 -07:00
|
|
|
{11:[No Name] [+] }{10:[No Name] [+] }|
|
|
|
|
Inc substitution on |
|
2017-09-24 04:57:47 -07:00
|
|
|
{12:tw}o lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[No Name] [+] }|
|
2017-09-24 04:57:47 -07:00
|
|
|
|2| {12:tw}o lines |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2016-08-12 03:05:18 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2016-11-06 16:08:23 -07:00
|
|
|
{10:[Preview] }|
|
2016-08-12 03:05:18 -07:00
|
|
|
:%s/tw^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
|
|
|
local settings = {
|
|
|
|
"splitbelow",
|
|
|
|
"splitright",
|
|
|
|
"noequalalways",
|
|
|
|
"equalalways eadirection=ver",
|
|
|
|
"equalalways eadirection=hor",
|
|
|
|
"equalalways eadirection=both",
|
|
|
|
}
|
|
|
|
|
|
|
|
it("are not affected by various settings", function()
|
|
|
|
for _, setting in pairs(settings) do
|
|
|
|
refresh()
|
2017-04-08 14:12:26 -07:00
|
|
|
feed_command("set " .. setting)
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
feed(":%s/tw")
|
|
|
|
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
2017-09-24 04:57:47 -07:00
|
|
|
{12:tw}o lines |
|
2016-08-12 03:05:18 -07:00
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{11:[No Name] [+] }|
|
2017-09-24 04:57:47 -07:00
|
|
|
|2| {12:tw}o lines |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2016-08-12 03:05:18 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
2016-11-06 16:08:23 -07:00
|
|
|
{10:[Preview] }|
|
2016-08-12 03:05:18 -07:00
|
|
|
:%s/tw^ |
|
|
|
|
]])
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
2022-06-12 10:59:04 -07:00
|
|
|
it("don't open if there's not enough room", function()
|
|
|
|
refresh()
|
|
|
|
screen:try_resize(40, 3)
|
|
|
|
feed("gg:%s/tw")
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
{12:tw}o lines |
|
|
|
|
:%s/tw^ |
|
|
|
|
]])
|
|
|
|
end)
|
2016-08-12 03:05:18 -07:00
|
|
|
end)
|
2017-09-09 02:38:19 -07:00
|
|
|
|
|
|
|
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)
|
2017-11-05 09:11:44 -07:00
|
|
|
|
|
|
|
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)
|
|
|
|
|
2017-09-09 02:38:19 -07:00
|
|
|
end)
|
2017-09-18 13:47:09 -07:00
|
|
|
|
|
|
|
describe(":substitute", function()
|
2018-05-18 10:41:14 -07:00
|
|
|
local screen = Screen.new(30,15)
|
2017-09-18 13:47:09 -07:00
|
|
|
before_each(function()
|
|
|
|
clear()
|
|
|
|
end)
|
|
|
|
|
2018-04-22 03:26:16 -07:00
|
|
|
it("inccommand=split, highlights multiline substitutions", function()
|
2017-09-18 13:47:09 -07:00
|
|
|
common_setup(screen, "split", multiline_text)
|
|
|
|
feed("gg")
|
|
|
|
|
2017-09-24 04:57:47 -07:00
|
|
|
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")
|
2017-09-18 13:47:09 -07:00
|
|
|
screen:expect([[
|
|
|
|
1 {12:MMM} Y Z |
|
|
|
|
7 8 9 |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{11:[No Name] [+] }|
|
|
|
|
|1| 1 {12:MMM} Y Z |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2017-09-18 13:47:09 -07:00
|
|
|
{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 |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2017-09-18 13:47:09 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
:%s/2\_.*X/MMM\rK\rLLL^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2018-04-22 03:26:16 -07:00
|
|
|
it("inccommand=nosplit, highlights multiline substitutions", function()
|
2017-09-18 13:47:09 -07:00
|
|
|
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)
|
|
|
|
|
2018-04-22 03:26:16 -07:00
|
|
|
it("inccommand=split, highlights multiple matches on a line", function()
|
2017-09-18 13:47:09 -07:00
|
|
|
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 |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2017-09-18 13:47:09 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
:%s/a/XLK^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2018-04-22 03:26:16 -07:00
|
|
|
it("inccommand=nosplit, highlights multiple matches on a line", function()
|
2017-09-18 13:47:09 -07:00
|
|
|
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)
|
|
|
|
|
2018-04-22 03:26:16 -07:00
|
|
|
it("inccommand=split, with \\zs", function()
|
2017-09-18 13:47:09 -07:00
|
|
|
common_setup(screen, "split", multiline_text)
|
|
|
|
feed("gg")
|
|
|
|
|
|
|
|
feed(":%s/[0-9]\\n\\zs[A-Z]/OKO")
|
|
|
|
screen:expect([[
|
|
|
|
{12:OKO} B C |
|
|
|
|
4 5 6 |
|
|
|
|
{12:OKO} Y Z |
|
|
|
|
7 8 9 |
|
2019-03-09 15:12:33 -07:00
|
|
|
|
|
2017-09-18 13:47:09 -07:00
|
|
|
{11:[No Name] [+] }|
|
|
|
|
|1| 1 2 3 |
|
|
|
|
|2| {12:OKO} B C |
|
|
|
|
|3| 4 5 6 |
|
|
|
|
|4| {12:OKO} Y Z |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2017-09-18 13:47:09 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
:%s/[0-9]\n\zs[A-Z]/OKO^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2018-04-22 03:26:16 -07:00
|
|
|
it("inccommand=nosplit, with \\zs", function()
|
2017-09-18 13:47:09 -07:00
|
|
|
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)
|
|
|
|
|
2018-04-22 03:26:16 -07:00
|
|
|
it("inccommand=split, substitutions of different length",
|
2017-09-18 13:47:09 -07:00
|
|
|
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} |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2017-09-18 13:47:09 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
:%s/T\([0-9]\+\)/\1\1/g^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2018-04-22 03:26:16 -07:00
|
|
|
it("inccommand=nosplit, substitutions of different length", function()
|
2017-09-18 13:47:09 -07:00
|
|
|
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)
|
|
|
|
|
2018-04-22 03:26:16 -07:00
|
|
|
it("inccommand=split, contraction of lines", function()
|
2017-09-18 13:47:09 -07:00
|
|
|
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([[
|
2017-09-24 04:57:47 -07:00
|
|
|
afa {12:Q} |
|
|
|
|
adf la;lkd {12:R} |
|
2017-09-18 13:47:09 -07:00
|
|
|
alx |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{11:[No Name] [+] }|
|
2017-09-24 04:57:47 -07:00
|
|
|
|3| afa {12:Q} |
|
|
|
|
|4|{12: }adf la;lkd {12:R} |
|
|
|
|
|5|{12: }alx |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2017-09-18 13:47:09 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
:%s/[QR]\n^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed("/KKK")
|
|
|
|
screen:expect([[
|
2019-09-24 22:56:29 -07:00
|
|
|
T T123 T T123 T2T TT T23423424|
|
|
|
|
x |
|
2017-09-18 13:47:09 -07:00
|
|
|
afa {12:KKK}adf la;lkd {12:KKK}alx |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{11:[No Name] [+] }|
|
|
|
|
|3| afa {12:KKK}adf la;lkd {12:KKK}alx |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2017-09-18 13:47:09 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
:%s/[QR]\n/KKK^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2018-04-22 03:26:16 -07:00
|
|
|
it("inccommand=nosplit, contraction of lines", function()
|
2017-09-18 13:47:09 -07:00
|
|
|
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)
|
|
|
|
|
2020-02-01 08:16:36 -07:00
|
|
|
it("inccommand=split, contraction of two subsequent NL chars", function()
|
|
|
|
-- luacheck: push ignore 611
|
|
|
|
local text = [[
|
|
|
|
AAA AA
|
|
|
|
|
|
|
|
BBB BB
|
|
|
|
|
|
|
|
CCC CC
|
|
|
|
|
|
|
|
]]
|
|
|
|
-- luacheck: pop
|
|
|
|
|
|
|
|
-- This used to crash, but more than 20 highlight entries are required
|
|
|
|
-- to reproduce it (so that the marktree has multiple nodes)
|
|
|
|
common_setup(screen, "split", string.rep(text,10))
|
|
|
|
feed(":%s/\\n\\n/<c-v><c-m>/g")
|
|
|
|
screen:expect{grid=[[
|
|
|
|
CCC CC |
|
|
|
|
AAA AA |
|
|
|
|
BBB BB |
|
|
|
|
CCC CC |
|
|
|
|
|
|
|
|
|
{11:[No Name] [+] }|
|
|
|
|
| 1| AAA AA |
|
|
|
|
| 2|{12: }BBB BB |
|
|
|
|
| 3|{12: }CCC CC |
|
|
|
|
| 4|{12: }AAA AA |
|
|
|
|
| 5|{12: }BBB BB |
|
|
|
|
| 6|{12: }CCC CC |
|
|
|
|
| 7|{12: }AAA AA |
|
|
|
|
{10:[Preview] }|
|
|
|
|
:%s/\n\n/{17:^M}/g^ |
|
|
|
|
]]}
|
|
|
|
assert_alive()
|
|
|
|
end)
|
|
|
|
|
|
|
|
it("inccommand=nosplit, contraction of two subsequent NL chars", function()
|
|
|
|
-- luacheck: push ignore 611
|
|
|
|
local text = [[
|
|
|
|
AAA AA
|
|
|
|
|
|
|
|
BBB BB
|
|
|
|
|
|
|
|
CCC CC
|
|
|
|
|
|
|
|
]]
|
|
|
|
-- luacheck: pop
|
|
|
|
|
|
|
|
common_setup(screen, "nosplit", string.rep(text,10))
|
|
|
|
feed(":%s/\\n\\n/<c-v><c-m>/g")
|
|
|
|
screen:expect{grid=[[
|
|
|
|
CCC CC |
|
|
|
|
AAA AA |
|
|
|
|
BBB BB |
|
|
|
|
CCC CC |
|
|
|
|
AAA AA |
|
|
|
|
BBB BB |
|
|
|
|
CCC CC |
|
|
|
|
AAA AA |
|
|
|
|
BBB BB |
|
|
|
|
CCC CC |
|
|
|
|
AAA AA |
|
|
|
|
BBB BB |
|
|
|
|
CCC CC |
|
|
|
|
|
|
|
|
|
:%s/\n\n/{17:^M}/g^ |
|
|
|
|
]]}
|
|
|
|
assert_alive()
|
|
|
|
end)
|
|
|
|
|
2018-04-22 03:26:16 -07:00
|
|
|
it("inccommand=split, multibyte text", function()
|
2017-09-18 13:47:09 -07:00
|
|
|
common_setup(screen, "split", multibyte_text)
|
|
|
|
feed(":%s/£.*ѫ/X¥¥")
|
|
|
|
screen:expect([[
|
|
|
|
a{12:X¥¥}¥KOL |
|
|
|
|
£ ¥ libm |
|
|
|
|
£ ¥ |
|
|
|
|
|
|
2019-03-09 15:12:33 -07:00
|
|
|
{15:~ }|
|
2017-09-18 13:47:09 -07:00
|
|
|
{11:[No Name] [+] }|
|
|
|
|
|1| {12:X¥¥} PEPPERS |
|
|
|
|
|2| {12:X¥¥} |
|
|
|
|
|3| a{12:X¥¥}¥KOL |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2017-09-18 13:47:09 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
:%s/£.*ѫ/X¥¥^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed("\\ra££ ¥")
|
|
|
|
screen:expect([[
|
|
|
|
a{12:X¥¥} |
|
|
|
|
{12:a££ ¥}¥KOL |
|
|
|
|
£ ¥ libm |
|
|
|
|
£ ¥ |
|
2019-03-09 15:12:33 -07:00
|
|
|
|
|
2017-09-18 13:47:09 -07:00
|
|
|
{11:[No Name] [+] }|
|
|
|
|
|1| {12:X¥¥} |
|
|
|
|
|2|{12: a££ ¥} PEPPERS |
|
|
|
|
|3| {12:X¥¥} |
|
|
|
|
|4|{12: a££ ¥} |
|
|
|
|
|5| a{12:X¥¥} |
|
|
|
|
|6|{12: a££ ¥}¥KOL |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2017-09-18 13:47:09 -07:00
|
|
|
{10:[Preview] }|
|
|
|
|
:%s/£.*ѫ/X¥¥\ra££ ¥^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2018-04-22 03:26:16 -07:00
|
|
|
it("inccommand=nosplit, multibyte text", function()
|
2017-09-18 13:47:09 -07:00
|
|
|
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)
|
|
|
|
|
2018-04-22 03:26:16 -07:00
|
|
|
it("inccommand=split, small cmdwinheight", function()
|
2017-09-18 13:47:09 -07:00
|
|
|
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 |
|
2017-09-24 04:57:47 -07:00
|
|
|
{12:a} b c |
|
|
|
|
{12:d} e f |
|
|
|
|
{12:q} r s |
|
|
|
|
{12:x} y z |
|
|
|
|
£ {12:m} n |
|
|
|
|
{12:t} œ ¥ |
|
2017-09-18 13:47:09 -07:00
|
|
|
|
|
|
|
|
{11:[No Name] [+] }|
|
2017-09-24 04:57:47 -07:00
|
|
|
| 7| {12:a} b c |
|
|
|
|
| 8| {12:d} e f |
|
2017-09-18 13:47:09 -07:00
|
|
|
{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([[
|
2022-08-17 07:19:35 -07:00
|
|
|
7 8 9 |
|
2017-09-18 13:47:09 -07:00
|
|
|
K L M |
|
|
|
|
{12:JLKR £} |
|
|
|
|
{12:ѫ ab } |
|
|
|
|
{12:XXXX} b c |
|
|
|
|
{12:JLKR £} |
|
|
|
|
{12:ѫ ab } |
|
|
|
|
{12:XXXX} e f |
|
|
|
|
{12:JLKR £} |
|
2019-03-09 15:12:33 -07:00
|
|
|
{12:ѫ ab } |
|
2017-09-18 13:47:09 -07:00
|
|
|
{11:[No Name] [+] }|
|
|
|
|
| 7| {12:JLKR £} |
|
2022-08-17 07:19:35 -07:00
|
|
|
{11: }|
|
2017-09-18 13:47:09 -07:00
|
|
|
:%s/[a-z]/JLKR £\rѫ ab \rXXX|
|
|
|
|
X^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2018-04-22 03:26:16 -07:00
|
|
|
it("inccommand=split, large cmdwinheight", function()
|
2017-09-18 13:47:09 -07:00
|
|
|
common_setup(screen, "split", long_multiline_text)
|
|
|
|
command("set cmdwinheight=11")
|
|
|
|
|
|
|
|
feed(":%s/. .$")
|
|
|
|
screen:expect([[
|
2017-09-24 04:57:47 -07:00
|
|
|
t {12:œ ¥} |
|
2017-09-18 13:47:09 -07:00
|
|
|
{11:[No Name] [+] }|
|
2017-09-24 04:57:47 -07:00
|
|
|
| 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} |
|
2017-09-18 13:47:09 -07:00
|
|
|
{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)
|
|
|
|
|
2018-04-22 03:26:16 -07:00
|
|
|
it("inccommand=split, lookaround", function()
|
2017-09-18 13:47:09 -07:00
|
|
|
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} |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2017-09-18 13:47:09 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
:%s/\(some\)\@<=thing/one/^ |
|
|
|
|
]])
|
|
|
|
|
2017-09-23 13:57:43 -07:00
|
|
|
feed("<C-c>")
|
2019-03-09 15:12:33 -07:00
|
|
|
feed('gg')
|
2020-10-19 11:17:51 -07:00
|
|
|
poke_eventloop()
|
2017-09-18 13:47:09 -07:00
|
|
|
feed([[:%s/\(some\)\@<lt>!thing/one/]])
|
|
|
|
screen:expect([[
|
2019-09-24 22:56:29 -07:00
|
|
|
something |
|
2017-09-18 13:47:09 -07:00
|
|
|
every{12:one} |
|
|
|
|
someone |
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{11:[No Name] [+] }|
|
|
|
|
|2| every{12:one} |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2017-09-18 13:47:09 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
:%s/\(some\)\@<!thing/one/^ |
|
|
|
|
]])
|
|
|
|
|
2017-09-23 13:57:43 -07:00
|
|
|
feed([[<C-c>]])
|
2020-10-19 11:17:51 -07:00
|
|
|
poke_eventloop()
|
2017-09-18 13:47:09 -07:00
|
|
|
feed([[:%s/some\(thing\)\@=/every/]])
|
|
|
|
screen:expect([[
|
|
|
|
{12:every}thing |
|
|
|
|
everything |
|
|
|
|
someone |
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{11:[No Name] [+] }|
|
|
|
|
|1| {12:every}thing |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2017-09-18 13:47:09 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
:%s/some\(thing\)\@=/every/^ |
|
|
|
|
]])
|
|
|
|
|
2017-09-23 13:57:43 -07:00
|
|
|
feed([[<C-c>]])
|
2020-10-19 11:17:51 -07:00
|
|
|
poke_eventloop()
|
2017-09-18 13:47:09 -07:00
|
|
|
feed([[:%s/some\(thing\)\@!/every/]])
|
|
|
|
screen:expect([[
|
2019-09-24 22:56:29 -07:00
|
|
|
something |
|
|
|
|
everything |
|
2017-09-18 13:47:09 -07:00
|
|
|
{12:every}one |
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{11:[No Name] [+] }|
|
|
|
|
|3| {12:every}one |
|
2017-09-23 13:57:43 -07:00
|
|
|
{15:~ }|
|
2017-09-18 13:47:09 -07:00
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
:%s/some\(thing\)\@!/every/^ |
|
|
|
|
]])
|
|
|
|
end)
|
2019-10-29 15:32:25 -07:00
|
|
|
|
|
|
|
it("doesn't prompt to swap cmd range", function()
|
|
|
|
screen = Screen.new(50, 8) -- wide to avoid hit-enter prompt
|
|
|
|
common_setup(screen, "split", default_text)
|
|
|
|
feed(':2,1s/tw/MO/g')
|
|
|
|
|
|
|
|
-- substitution preview should have been made, without prompting
|
|
|
|
screen:expect([[
|
|
|
|
{12:MO}o lines |
|
|
|
|
{11:[No Name] [+] }|
|
|
|
|
|2| {12:MO}o lines |
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
:2,1s/tw/MO/g^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
-- but should be prompted on hitting enter
|
|
|
|
feed('<CR>')
|
|
|
|
screen:expect([[
|
|
|
|
{12:MO}o lines |
|
|
|
|
{11:[No Name] [+] }|
|
|
|
|
|2| {12:MO}o lines |
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
{13:Backwards range given, OK to swap (y/n)?}^ |
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed('y')
|
|
|
|
screen:expect([[
|
|
|
|
Inc substitution on |
|
|
|
|
^MOo lines |
|
|
|
|
|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{13:Backwards range given, OK to swap (y/n)?}y |
|
|
|
|
]])
|
|
|
|
end)
|
2018-05-18 10:41:14 -07:00
|
|
|
end)
|
|
|
|
|
|
|
|
it(':substitute with inccommand during :terminal activity', function()
|
2019-01-01 09:26:56 -07:00
|
|
|
if helpers.skip_fragile(pending) then
|
|
|
|
return
|
|
|
|
end
|
2018-11-10 03:12:04 -07:00
|
|
|
retry(2, 40000, function()
|
2018-05-18 10:41:14 -07:00
|
|
|
local screen = Screen.new(30,15)
|
|
|
|
clear()
|
2018-04-22 03:26:16 -07:00
|
|
|
|
|
|
|
command("set cmdwinheight=3")
|
2022-06-22 05:51:52 -07:00
|
|
|
feed(([[:terminal "%s" REP 5000 xxx<cr>]]):format(testprg('shell-test')))
|
2018-04-22 03:26:16 -07:00
|
|
|
command('file term')
|
2019-08-09 14:31:41 -07:00
|
|
|
feed('G') -- Follow :terminal output.
|
2018-04-22 03:26:16 -07:00
|
|
|
command('new')
|
|
|
|
common_setup(screen, 'split', 'foo bar baz\nbar baz fox\nbar foo baz')
|
|
|
|
command('wincmd =')
|
|
|
|
|
|
|
|
feed('gg')
|
|
|
|
feed(':%s/foo/ZZZ')
|
2018-05-18 10:41:14 -07:00
|
|
|
sleep(20) -- Allow some terminal activity.
|
2023-02-14 16:26:55 -07:00
|
|
|
poke_eventloop()
|
|
|
|
screen:sleep(0)
|
2019-08-09 14:31:41 -07:00
|
|
|
screen:expect_unchanged()
|
2018-04-22 03:26:16 -07:00
|
|
|
end)
|
2017-09-18 13:47:09 -07:00
|
|
|
end)
|
2019-03-24 19:27:24 -07:00
|
|
|
|
|
|
|
it(':substitute with inccommand, timer-induced :redraw #9777', function()
|
|
|
|
local screen = Screen.new(30,12)
|
|
|
|
clear()
|
|
|
|
command('set cmdwinheight=3')
|
|
|
|
command('call timer_start(10, {-> execute("redraw")}, {"repeat":-1})')
|
|
|
|
command('call timer_start(10, {-> execute("redrawstatus")}, {"repeat":-1})')
|
|
|
|
common_setup(screen, 'split', 'foo bar baz\nbar baz fox\nbar foo baz')
|
|
|
|
|
|
|
|
feed('gg')
|
|
|
|
feed(':%s/foo/ZZZ')
|
|
|
|
sleep(20) -- Allow some timer activity.
|
|
|
|
screen:expect([[
|
|
|
|
{12:ZZZ} bar baz |
|
|
|
|
bar baz fox |
|
|
|
|
bar {12:ZZZ} baz |
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{11:[No Name] [+] }|
|
|
|
|
|1| {12:ZZZ} bar baz |
|
|
|
|
|3| bar {12:ZZZ} baz |
|
|
|
|
{15:~ }|
|
|
|
|
{10:[Preview] }|
|
|
|
|
:%s/foo/ZZZ^ |
|
|
|
|
]])
|
|
|
|
end)
|
2019-08-12 05:21:15 -07:00
|
|
|
|
2022-06-10 22:04:19 -07:00
|
|
|
it(':substitute with inccommand, allows :redraw before first separator is typed #18857', function()
|
|
|
|
local screen = Screen.new(30,6)
|
|
|
|
clear()
|
|
|
|
common_setup(screen, 'split', 'foo bar baz\nbar baz fox\nbar foo baz')
|
|
|
|
command('hi! link NormalFloat CursorLine')
|
|
|
|
local float_buf = meths.create_buf(false, true)
|
|
|
|
meths.open_win(float_buf, false, {
|
|
|
|
relative = 'editor', height = 1, width = 5, row = 3, col = 0, focusable = false,
|
|
|
|
})
|
|
|
|
feed(':%s')
|
|
|
|
screen:expect([[
|
|
|
|
foo bar baz |
|
|
|
|
bar baz fox |
|
|
|
|
bar foo baz |
|
|
|
|
{16: }{15: }|
|
|
|
|
{15:~ }|
|
|
|
|
:%s^ |
|
|
|
|
]])
|
|
|
|
meths.buf_set_lines(float_buf, 0, -1, true, {'foo'})
|
|
|
|
command('redraw')
|
|
|
|
screen:expect([[
|
|
|
|
foo bar baz |
|
|
|
|
bar baz fox |
|
|
|
|
bar foo baz |
|
|
|
|
{16:foo }{15: }|
|
|
|
|
{15:~ }|
|
|
|
|
:%s^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2022-06-14 19:18:43 -07:00
|
|
|
it(':substitute with inccommand, does not crash if range contains invalid marks', function()
|
2022-06-13 19:55:04 -07:00
|
|
|
local screen = Screen.new(30, 6)
|
|
|
|
clear()
|
|
|
|
common_setup(screen, 'split', 'test')
|
|
|
|
feed([[:'a,'bs]])
|
|
|
|
screen:expect([[
|
|
|
|
test |
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:'a,'bs^ |
|
|
|
|
]])
|
2022-06-14 19:18:43 -07:00
|
|
|
-- v:errmsg shouldn't be set either before the first separator is typed
|
|
|
|
eq('', eval('v:errmsg'))
|
2022-06-13 19:55:04 -07:00
|
|
|
feed('/')
|
|
|
|
screen:expect([[
|
|
|
|
test |
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:'a,'bs/^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2022-09-18 21:37:25 -07:00
|
|
|
it(':substitute with inccommand, no unnecessary redraw if preview is not shown', function()
|
|
|
|
local screen = Screen.new(60, 6)
|
|
|
|
clear()
|
|
|
|
common_setup(screen, 'split', 'test')
|
|
|
|
feed(':ls<CR>')
|
|
|
|
screen:expect([[
|
|
|
|
test |
|
|
|
|
{15:~ }|
|
|
|
|
{11: }|
|
|
|
|
:ls |
|
|
|
|
1 %a + "[No Name]" line 1 |
|
|
|
|
{13:Press ENTER or type command to continue}^ |
|
|
|
|
]])
|
|
|
|
feed(':s')
|
|
|
|
-- no unnecessary redraw, so messages are still shown
|
|
|
|
screen:expect([[
|
|
|
|
test |
|
|
|
|
{15:~ }|
|
|
|
|
{11: }|
|
|
|
|
:ls |
|
|
|
|
1 %a + "[No Name]" line 1 |
|
|
|
|
:s^ |
|
|
|
|
]])
|
|
|
|
feed('o')
|
|
|
|
screen:expect([[
|
|
|
|
test |
|
|
|
|
{15:~ }|
|
|
|
|
{11: }|
|
|
|
|
:ls |
|
|
|
|
1 %a + "[No Name]" line 1 |
|
|
|
|
:so^ |
|
|
|
|
]])
|
|
|
|
feed('<BS>')
|
|
|
|
screen:expect([[
|
|
|
|
test |
|
|
|
|
{15:~ }|
|
|
|
|
{11: }|
|
|
|
|
:ls |
|
|
|
|
1 %a + "[No Name]" line 1 |
|
|
|
|
:s^ |
|
|
|
|
]])
|
|
|
|
feed('/test')
|
|
|
|
-- now inccommand is shown, so screen is redrawn
|
|
|
|
screen:expect([[
|
|
|
|
{12:test} |
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:s/test^ |
|
|
|
|
]])
|
|
|
|
end)
|
|
|
|
|
2020-09-22 18:33:18 -07:00
|
|
|
it(":substitute doesn't crash with inccommand, if undo is empty #12932", function()
|
|
|
|
local screen = Screen.new(10,5)
|
|
|
|
clear()
|
|
|
|
command('set undolevels=-1')
|
|
|
|
common_setup(screen, 'split', 'test')
|
|
|
|
feed(':%s/test')
|
|
|
|
sleep(100)
|
|
|
|
feed('/')
|
|
|
|
sleep(100)
|
|
|
|
feed('f')
|
|
|
|
screen:expect([[
|
|
|
|
{12:f} |
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
{15:~ }|
|
|
|
|
:%s/test/f^ |
|
|
|
|
]])
|
|
|
|
assert_alive()
|
|
|
|
end)
|
|
|
|
|
2022-09-25 16:00:37 -07:00
|
|
|
it(':substitute with inccommand works properly if undo is not synced #20029', function()
|
|
|
|
local screen = Screen.new(30, 6)
|
|
|
|
clear()
|
|
|
|
common_setup(screen, 'nosplit', 'foo\nbar\nbaz')
|
|
|
|
meths.set_keymap('x', '<F2>', '<Esc>`<Oaaaaa asdf<Esc>`>obbbbb asdf<Esc>V`<k:s/asdf/', {})
|
|
|
|
feed('gg0<C-V>lljj<F2>')
|
|
|
|
screen:expect([[
|
|
|
|
aaaaa |
|
|
|
|
foo |
|
|
|
|
bar |
|
|
|
|
baz |
|
|
|
|
bbbbb |
|
|
|
|
:'<,'>s/asdf/^ |
|
|
|
|
]])
|
|
|
|
feed('hjkl')
|
|
|
|
screen:expect([[
|
|
|
|
aaaaa {12:hjkl} |
|
|
|
|
foo |
|
|
|
|
bar |
|
|
|
|
baz |
|
|
|
|
bbbbb {12:hjkl} |
|
|
|
|
:'<,'>s/asdf/hjkl^ |
|
|
|
|
]])
|
|
|
|
feed('<CR>')
|
|
|
|
expect([[
|
|
|
|
aaaaa hjkl
|
|
|
|
foo
|
|
|
|
bar
|
|
|
|
baz
|
|
|
|
bbbbb hjkl]])
|
|
|
|
feed('u')
|
|
|
|
expect([[
|
|
|
|
foo
|
|
|
|
bar
|
|
|
|
baz]])
|
|
|
|
end)
|
|
|
|
|
2019-08-12 05:21:15 -07:00
|
|
|
it('long :%s/ with inccommand does not collapse cmdline', function()
|
|
|
|
local screen = Screen.new(10,5)
|
|
|
|
clear()
|
|
|
|
common_setup(screen)
|
|
|
|
command('set inccommand=nosplit')
|
|
|
|
feed(':%s/AAAAAAA', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
|
|
|
|
'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A')
|
|
|
|
screen:expect([[
|
2022-08-17 07:19:35 -07:00
|
|
|
|
|
|
|
|
{11: }|
|
2019-08-12 05:21:15 -07:00
|
|
|
:%s/AAAAAAAA|
|
|
|
|
AAAAAAAAAAAA|
|
|
|
|
AAAAAAA^ |
|
|
|
|
]])
|
|
|
|
end)
|
2022-06-27 22:00:05 -07:00
|
|
|
|
|
|
|
it("with 'inccommand' typing :filter doesn't segfault or leak memory #19057", function()
|
|
|
|
clear()
|
|
|
|
common_setup(nil, 'nosplit')
|
|
|
|
feed(':filter s')
|
|
|
|
assert_alive()
|
|
|
|
feed(' ')
|
|
|
|
assert_alive()
|
|
|
|
feed('h')
|
|
|
|
assert_alive()
|
|
|
|
feed('i')
|
|
|
|
assert_alive()
|
|
|
|
end)
|