inccommand_spec.lua 82 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local Screen = require('test.functional.ui.screen')
  4. local clear = n.clear
  5. local command = n.command
  6. local eq = t.eq
  7. local eval = n.eval
  8. local expect = n.expect
  9. local feed = n.feed
  10. local insert = n.insert
  11. local fn = n.fn
  12. local api = n.api
  13. local neq = t.neq
  14. local ok = t.ok
  15. local retry = t.retry
  16. local source = n.source
  17. local poke_eventloop = n.poke_eventloop
  18. local sleep = vim.uv.sleep
  19. local testprg = n.testprg
  20. local assert_alive = n.assert_alive
  21. local default_text = [[
  22. Inc substitution on
  23. two lines
  24. ]]
  25. local multiline_text = [[
  26. 1 2 3
  27. A B C
  28. 4 5 6
  29. X Y Z
  30. 7 8 9
  31. ]]
  32. local multimatch_text = [[
  33. a bdc eae a fgl lzia r
  34. x
  35. ]]
  36. local multibyte_text = [[
  37. £ ¥ ѫѫ PEPPERS
  38. £ ¥ ѫfѫ
  39. a£ ѫ¥KOL
  40. £ ¥ libm
  41. £ ¥
  42. ]]
  43. local long_multiline_text = [[
  44. 1 2 3
  45. A B C
  46. 4 5 6
  47. X Y Z
  48. 7 8 9
  49. K L M
  50. a b c
  51. d e f
  52. q r s
  53. x y z
  54. £ m n
  55. t œ ¥
  56. ]]
  57. local function common_setup(screen, inccommand, text)
  58. if screen then
  59. command('syntax on')
  60. command('set nohlsearch')
  61. command('hi Substitute guifg=red guibg=yellow')
  62. screen:add_extra_attr_ids {
  63. [100] = { underline = true },
  64. [101] = { underline = true, foreground = Screen.colors.SlateBlue, bold = true },
  65. vis = { background = Screen.colors.LightGrey },
  66. }
  67. end
  68. command('set inccommand=' .. (inccommand or ''))
  69. if text then
  70. insert(text)
  71. end
  72. end
  73. describe(':substitute, inccommand=split interactivity', function()
  74. before_each(function()
  75. clear()
  76. common_setup(nil, 'split', default_text)
  77. end)
  78. -- Test the tests: verify that the `1==bufnr('$')` assertion
  79. -- in the "no preview" tests (below) actually means something.
  80. it('previews interactive cmdline', function()
  81. feed(':%s/tw/MO/g')
  82. retry(nil, 1000, function()
  83. eq(2, eval("bufnr('$')"))
  84. end)
  85. end)
  86. it('no preview if invoked by a script', function()
  87. source('%s/tw/MO/g')
  88. poke_eventloop()
  89. eq(1, eval("bufnr('$')"))
  90. -- sanity check: assert the buffer state
  91. expect(default_text:gsub('tw', 'MO'))
  92. end)
  93. it('no preview if invoked by feedkeys()', function()
  94. -- in a script...
  95. source([[:call feedkeys(":%s/tw/MO/g\<CR>")]])
  96. -- or interactively...
  97. feed([[:call feedkeys(":%s/bs/BUU/g\<lt>CR>")<CR>]])
  98. eq(1, eval("bufnr('$')"))
  99. -- sanity check: assert the buffer state
  100. expect(default_text:gsub('tw', 'MO'):gsub('bs', 'BUU'))
  101. end)
  102. end)
  103. describe(":substitute, 'inccommand' preserves", function()
  104. before_each(clear)
  105. it('listed buffers (:ls)', function()
  106. local screen = Screen.new(30, 10)
  107. common_setup(screen, 'split', 'ABC')
  108. feed(':%s/AB/BA/')
  109. poke_eventloop()
  110. feed('<CR>')
  111. feed(':ls<CR>')
  112. screen:expect([[
  113. BAC |
  114. {1:~ }|*3
  115. {3: }|
  116. :ls |
  117. 1 %a + "[No Name]" |
  118. line 1 |
  119. {6:Press ENTER or type command to}|
  120. {6: continue}^ |
  121. ]])
  122. end)
  123. it("'[ and '] marks #26439", function()
  124. local screen = Screen.new(30, 10)
  125. common_setup(screen, 'nosplit', ('abc\ndef\n'):rep(50))
  126. feed('ggyG')
  127. local X = api.nvim_get_vvar('maxcol')
  128. eq({ 0, 1, 1, 0 }, fn.getpos("'["))
  129. eq({ 0, 101, X, 0 }, fn.getpos("']"))
  130. feed(":'[,']s/def/")
  131. poke_eventloop()
  132. eq({ 0, 1, 1, 0 }, fn.getpos("'["))
  133. eq({ 0, 101, X, 0 }, fn.getpos("']"))
  134. feed('DEF/g')
  135. poke_eventloop()
  136. eq({ 0, 1, 1, 0 }, fn.getpos("'["))
  137. eq({ 0, 101, X, 0 }, fn.getpos("']"))
  138. feed('<CR>')
  139. expect(('abc\nDEF\n'):rep(50))
  140. end)
  141. for _, case in pairs { '', 'split', 'nosplit' } do
  142. it('various delimiters (inccommand=' .. case .. ')', function()
  143. insert(default_text)
  144. command('set inccommand=' .. case)
  145. local delims = { '/', '#', ';', '%', ',', '@', '!' }
  146. for _, delim in pairs(delims) do
  147. feed(':%s' .. delim .. 'lines' .. delim .. 'LINES' .. delim .. 'g')
  148. poke_eventloop()
  149. feed('<CR>')
  150. expect([[
  151. Inc substitution on
  152. two LINES
  153. ]])
  154. command('undo')
  155. end
  156. end)
  157. end
  158. for _, case in pairs { '', 'split', 'nosplit' } do
  159. it("'undolevels' (inccommand=" .. case .. ')', function()
  160. command('set undolevels=139')
  161. command('setlocal undolevels=34')
  162. command('split') -- Show the buffer in multiple windows
  163. command('set inccommand=' .. case)
  164. insert('as')
  165. feed(':%s/as/glork/')
  166. poke_eventloop()
  167. feed('<enter>')
  168. eq(139, api.nvim_get_option_value('undolevels', { scope = 'global' }))
  169. eq(34, api.nvim_get_option_value('undolevels', { buf = 0 }))
  170. end)
  171. end
  172. for _, case in ipairs({ '', 'split', 'nosplit' }) do
  173. it('empty undotree() (inccommand=' .. case .. ')', function()
  174. command('set undolevels=1000')
  175. command('set inccommand=' .. case)
  176. local expected_undotree = eval('undotree()')
  177. -- Start typing an incomplete :substitute command.
  178. feed([[:%s/e/YYYY/g]])
  179. poke_eventloop()
  180. -- Cancel the :substitute.
  181. feed([[<C-\><C-N>]])
  182. -- The undo tree should be unchanged.
  183. eq(expected_undotree, eval('undotree()'))
  184. eq({}, eval('undotree()')['entries'])
  185. end)
  186. end
  187. for _, case in ipairs({ '', 'split', 'nosplit' }) do
  188. it('undotree() with branches (inccommand=' .. case .. ')', function()
  189. command('set undolevels=1000')
  190. command('set inccommand=' .. case)
  191. -- Make some changes.
  192. feed([[isome text 1<C-\><C-N>]])
  193. feed([[osome text 2<C-\><C-N>]])
  194. -- Add an undo branch.
  195. feed([[u]])
  196. -- More changes, more undo branches.
  197. feed([[osome text 3<C-\><C-N>]])
  198. feed([[AX<C-\><C-N>]])
  199. feed([[...]])
  200. feed([[uu]])
  201. feed([[osome text 4<C-\><C-N>]])
  202. feed([[u<C-R>u]])
  203. feed([[osome text 5<C-\><C-N>]])
  204. expect([[
  205. some text 1
  206. some text 3XX
  207. some text 5]])
  208. local expected_undotree = eval('undotree()')
  209. eq(5, #expected_undotree['entries']) -- sanity
  210. -- Start typing an incomplete :substitute command.
  211. feed([[:%s/e/YYYY/g]])
  212. poke_eventloop()
  213. -- Cancel the :substitute.
  214. feed([[<C-\><C-N>]])
  215. -- The undo tree should be unchanged.
  216. eq(expected_undotree, eval('undotree()'))
  217. end)
  218. end
  219. for _, case in pairs { '', 'split', 'nosplit' } do
  220. it('b:changedtick (inccommand=' .. case .. ')', function()
  221. command('set inccommand=' .. case)
  222. feed([[isome text 1<C-\><C-N>]])
  223. feed([[osome text 2<C-\><C-N>]])
  224. local expected_tick = eval('b:changedtick')
  225. ok(expected_tick > 0)
  226. expect([[
  227. some text 1
  228. some text 2]])
  229. feed(':%s/e/XXX/')
  230. poke_eventloop()
  231. eq(expected_tick, eval('b:changedtick'))
  232. end)
  233. end
  234. for _, case in ipairs({ '', 'split', 'nosplit' }) do
  235. it('previous substitute string ~ (inccommand=' .. case .. ') #12109', function()
  236. local screen = Screen.new(30, 10)
  237. common_setup(screen, case, default_text)
  238. feed(':%s/Inc/SUB<CR>')
  239. expect([[
  240. SUB substitution on
  241. two lines
  242. ]])
  243. feed(':%s/line/')
  244. poke_eventloop()
  245. feed('~')
  246. poke_eventloop()
  247. feed('<CR>')
  248. expect([[
  249. SUB substitution on
  250. two SUBs
  251. ]])
  252. feed(':%s/sti/')
  253. poke_eventloop()
  254. feed('~')
  255. poke_eventloop()
  256. feed('B')
  257. poke_eventloop()
  258. feed('<CR>')
  259. expect([[
  260. SUB subSUBBtution on
  261. two SUBs
  262. ]])
  263. feed(':%s/ion/NEW<CR>')
  264. expect([[
  265. SUB subSUBBtutNEW on
  266. two SUBs
  267. ]])
  268. feed(':%s/two/')
  269. poke_eventloop()
  270. feed('N')
  271. poke_eventloop()
  272. feed('~')
  273. poke_eventloop()
  274. feed('<CR>')
  275. expect([[
  276. SUB subSUBBtutNEW on
  277. NNEW SUBs
  278. ]])
  279. feed(':%s/bS/')
  280. poke_eventloop()
  281. feed('~')
  282. poke_eventloop()
  283. feed('W')
  284. poke_eventloop()
  285. feed('<CR>')
  286. expect([[
  287. SUB suNNEWWUBBtutNEW on
  288. NNEW SUBs
  289. ]])
  290. end)
  291. end
  292. end)
  293. describe(":substitute, 'inccommand' preserves undo", function()
  294. local cases = { '', 'split', 'nosplit' }
  295. local substrings = {
  296. { ':%s/', '1' },
  297. { ':%s/', '1', '/' },
  298. { ':%s/', '1', '/', '<bs>' },
  299. { ':%s/', '1', '/', 'a' },
  300. { ':%s/', '1', '/', 'a', '<bs>' },
  301. { ':%s/', '1', '/', 'a', 'x' },
  302. { ':%s/', '1', '/', 'a', 'x', '<bs>' },
  303. { ':%s/', '1', '/', 'a', 'x', '<bs>', '<bs>' },
  304. { ':%s/', '1', '/', 'a', 'x', '<bs>', '<bs>', '<bs>' },
  305. { ':%s/', '1', '/', 'a', 'x', '/' },
  306. { ':%s/', '1', '/', 'a', 'x', '/', '<bs>' },
  307. { ':%s/', '1', '/', 'a', 'x', '/', '<bs>', '/' },
  308. { ':%s/', '1', '/', 'a', 'x', '/', 'g' },
  309. { ':%s/', '1', '/', 'a', 'x', '/', 'g', '<bs>' },
  310. { ':%s/', '1', '/', 'a', 'x', '/', 'g', '<bs>', '<bs>' },
  311. }
  312. local function test_sub(substring, split, redoable)
  313. command('bwipe!')
  314. command('set inccommand=' .. split)
  315. insert('1')
  316. feed('o2<esc>')
  317. command('undo')
  318. feed('o3<esc>')
  319. if redoable then
  320. feed('o4<esc>')
  321. command('undo')
  322. end
  323. for _, s in pairs(substring) do
  324. feed(s)
  325. end
  326. poke_eventloop()
  327. feed('<enter>')
  328. command('undo')
  329. feed('g-')
  330. expect([[
  331. 1
  332. 2]])
  333. feed('g+')
  334. expect([[
  335. 1
  336. 3]])
  337. end
  338. local function test_notsub(substring, split, redoable)
  339. command('bwipe!')
  340. command('set inccommand=' .. split)
  341. insert('1')
  342. feed('o2<esc>')
  343. command('undo')
  344. feed('o3<esc>')
  345. if redoable then
  346. feed('o4<esc>')
  347. command('undo')
  348. end
  349. for _, s in pairs(substring) do
  350. feed(s)
  351. end
  352. poke_eventloop()
  353. feed('<esc>')
  354. feed('g-')
  355. expect([[
  356. 1
  357. 2]])
  358. feed('g+')
  359. expect([[
  360. 1
  361. 3]])
  362. if redoable then
  363. feed('<c-r>')
  364. expect([[
  365. 1
  366. 3
  367. 4]])
  368. end
  369. end
  370. local function test_threetree(substring, split)
  371. command('bwipe!')
  372. command('set inccommand=' .. split)
  373. insert('1')
  374. feed('o2<esc>')
  375. feed('o3<esc>')
  376. feed('uu')
  377. feed('oa<esc>')
  378. feed('ob<esc>')
  379. feed('uu')
  380. feed('oA<esc>')
  381. feed('oB<esc>')
  382. -- This is the undo tree (x-Axis is timeline), we're at B now
  383. -- ----------------A - B
  384. -- /
  385. -- | --------a - b
  386. -- |/
  387. -- 1 - 2 - 3
  388. feed('2u')
  389. for _, s in pairs(substring) do
  390. feed(s)
  391. poke_eventloop()
  392. end
  393. feed('<esc>')
  394. expect([[
  395. 1]])
  396. feed('g-')
  397. expect([[
  398. ]])
  399. feed('g+')
  400. expect([[
  401. 1]])
  402. feed('<c-r>')
  403. expect([[
  404. 1
  405. A]])
  406. feed('g-') -- go to b
  407. feed('2u')
  408. for _, s in pairs(substring) do
  409. feed(s)
  410. poke_eventloop()
  411. end
  412. feed('<esc>')
  413. feed('<c-r>')
  414. expect([[
  415. 1
  416. a]])
  417. feed('g-') -- go to 3
  418. feed('2u')
  419. for _, s in pairs(substring) do
  420. feed(s)
  421. poke_eventloop()
  422. end
  423. feed('<esc>')
  424. feed('<c-r>')
  425. expect([[
  426. 1
  427. 2]])
  428. end
  429. before_each(clear)
  430. it('at a non-leaf of the undo tree', function()
  431. for _, case in pairs(cases) do
  432. for _, str in pairs(substrings) do
  433. for _, redoable in pairs({ true }) do
  434. test_sub(str, case, redoable)
  435. end
  436. end
  437. end
  438. end)
  439. it('at a leaf of the undo tree', function()
  440. for _, case in pairs(cases) do
  441. for _, str in pairs(substrings) do
  442. for _, redoable in pairs({ false }) do
  443. test_sub(str, case, redoable)
  444. end
  445. end
  446. end
  447. end)
  448. it('when interrupting substitution', function()
  449. for _, case in pairs(cases) do
  450. for _, str in pairs(substrings) do
  451. for _, redoable in pairs({ true, false }) do
  452. test_notsub(str, case, redoable)
  453. end
  454. end
  455. end
  456. end)
  457. it('in a complex undo scenario', function()
  458. for _, case in pairs(cases) do
  459. for _, str in pairs(substrings) do
  460. test_threetree(str, case)
  461. end
  462. end
  463. end)
  464. it('with undolevels=0', function()
  465. for _, case in pairs(cases) do
  466. clear()
  467. common_setup(nil, case, default_text)
  468. command('set undolevels=0')
  469. feed('1G0')
  470. insert('X')
  471. feed(':%s/tw/MO/')
  472. poke_eventloop()
  473. feed('<esc>')
  474. command('undo')
  475. expect(default_text)
  476. command('undo')
  477. expect(default_text:gsub('Inc', 'XInc'))
  478. command('undo')
  479. feed(':%s/tw/MO/g')
  480. poke_eventloop()
  481. feed('<CR>')
  482. expect(default_text:gsub('tw', 'MO'))
  483. command('undo')
  484. expect(default_text)
  485. command('undo')
  486. expect(default_text:gsub('tw', 'MO'))
  487. end
  488. end)
  489. it('with undolevels=1', function()
  490. for _, case in pairs(cases) do
  491. clear()
  492. local screen = Screen.new(20, 10)
  493. common_setup(screen, case, default_text)
  494. screen:expect([[
  495. Inc substitution on |
  496. two lines |
  497. ^ |
  498. {1:~ }|*6
  499. |
  500. ]])
  501. command('set undolevels=1')
  502. feed('1G0')
  503. insert('X')
  504. feed('IY<esc>')
  505. feed(':%s/tw/MO/')
  506. poke_eventloop()
  507. feed('<esc>')
  508. feed('u')
  509. expect(default_text:gsub('Inc', 'XInc'))
  510. feed('u')
  511. expect(default_text)
  512. feed(':%s/tw/MO/g')
  513. poke_eventloop()
  514. feed('<enter>')
  515. feed(':%s/MO/GO/g')
  516. poke_eventloop()
  517. feed('<enter>')
  518. feed(':%s/GO/NO/g')
  519. poke_eventloop()
  520. feed('<enter>')
  521. feed('u')
  522. expect(default_text:gsub('tw', 'GO'))
  523. feed('u')
  524. expect(default_text:gsub('tw', 'MO'))
  525. feed('u')
  526. if case == 'split' then
  527. screen:expect([[
  528. Inc substitution on |
  529. ^MOo lines |
  530. |
  531. {1:~ }|*6
  532. Already ...t change |
  533. ]])
  534. else
  535. screen:expect([[
  536. Inc substitution on |
  537. ^MOo lines |
  538. |
  539. {1:~ }|*6
  540. Already ...t change |
  541. ]])
  542. end
  543. end
  544. end)
  545. it('with undolevels=2', function()
  546. for _, case in pairs(cases) do
  547. clear()
  548. local screen = Screen.new(20, 10)
  549. common_setup(screen, case, default_text)
  550. command('set undolevels=2')
  551. feed('2GAx<esc>')
  552. feed('Ay<esc>')
  553. feed('Az<esc>')
  554. feed(':%s/tw/AR')
  555. poke_eventloop()
  556. feed('<esc>')
  557. feed('u')
  558. expect(default_text:gsub('lines', 'linesxy'))
  559. feed('u')
  560. expect(default_text:gsub('lines', 'linesx'))
  561. feed('u')
  562. expect(default_text)
  563. feed('u')
  564. if case == 'split' then
  565. screen:expect([[
  566. Inc substitution on |
  567. two line^s |
  568. |
  569. {1:~ }|*6
  570. Already ...t change |
  571. ]])
  572. else
  573. screen:expect([[
  574. Inc substitution on |
  575. two line^s |
  576. |
  577. {1:~ }|*6
  578. Already ...t change |
  579. ]])
  580. end
  581. feed(':%s/tw/MO/g')
  582. poke_eventloop()
  583. feed('<enter>')
  584. feed(':%s/MO/GO/g')
  585. poke_eventloop()
  586. feed('<enter>')
  587. feed(':%s/GO/NO/g')
  588. poke_eventloop()
  589. feed('<enter>')
  590. feed(':%s/NO/LO/g')
  591. poke_eventloop()
  592. feed('<enter>')
  593. feed('u')
  594. expect(default_text:gsub('tw', 'NO'))
  595. feed('u')
  596. expect(default_text:gsub('tw', 'GO'))
  597. feed('u')
  598. expect(default_text:gsub('tw', 'MO'))
  599. feed('u')
  600. if case == 'split' then
  601. screen:expect([[
  602. Inc substitution on |
  603. ^MOo lines |
  604. |
  605. {1:~ }|*6
  606. Already ...t change |
  607. ]])
  608. else
  609. screen:expect([[
  610. Inc substitution on |
  611. ^MOo lines |
  612. |
  613. {1:~ }|*6
  614. Already ...t change |
  615. ]])
  616. end
  617. end
  618. end)
  619. it('with undolevels=-1', function()
  620. for _, case in pairs(cases) do
  621. clear()
  622. local screen = Screen.new(20, 10)
  623. common_setup(screen, case, default_text)
  624. command('set undolevels=-1')
  625. feed(':%s/tw/MO/g')
  626. poke_eventloop()
  627. feed('<enter>')
  628. feed('u')
  629. if case == 'split' then
  630. screen:expect([[
  631. Inc substitution on |
  632. ^MOo lines |
  633. |
  634. {1:~ }|*6
  635. Already ...t change |
  636. ]])
  637. else
  638. screen:expect([[
  639. Inc substitution on |
  640. ^MOo lines |
  641. |
  642. {1:~ }|*6
  643. Already ...t change |
  644. ]])
  645. end
  646. -- repeat with an interrupted substitution
  647. clear()
  648. screen = Screen.new(20, 10)
  649. common_setup(screen, case, default_text)
  650. command('set undolevels=-1')
  651. feed('1G')
  652. feed('IL<esc>')
  653. feed(':%s/tw/MO/g')
  654. poke_eventloop()
  655. feed('<esc>')
  656. feed('u')
  657. screen:expect([[
  658. ^LInc substitution on|
  659. two lines |
  660. |
  661. {1:~ }|*6
  662. Already ...t change |
  663. ]])
  664. end
  665. end)
  666. end)
  667. describe(':substitute, inccommand=split', function()
  668. local screen
  669. before_each(function()
  670. clear()
  671. screen = Screen.new(30, 15)
  672. common_setup(screen, 'split', default_text .. default_text)
  673. end)
  674. it("preserves 'modified' buffer flag", function()
  675. command('set nomodified')
  676. feed(':%s/tw')
  677. screen:expect([[
  678. Inc substitution on |
  679. {20:tw}o lines |
  680. Inc substitution on |
  681. {20:tw}o lines |
  682. |
  683. {3:[No Name] }|
  684. |2| {20:tw}o lines |
  685. |4| {20:tw}o lines |
  686. {1:~ }|*5
  687. {2:[Preview] }|
  688. :%s/tw^ |
  689. ]])
  690. feed([[<C-\><C-N>]]) -- Cancel the :substitute command.
  691. eq(0, eval('&modified'))
  692. end)
  693. it('shows preview when cmd modifiers are present', function()
  694. -- one modifier
  695. feed(':keeppatterns %s/tw/to')
  696. screen:expect { any = [[{20:to}o lines]] }
  697. feed('<Esc>')
  698. screen:expect { any = [[two lines]] }
  699. -- multiple modifiers
  700. feed(':keeppatterns silent %s/tw/to')
  701. screen:expect { any = [[{20:to}o lines]] }
  702. feed('<Esc>')
  703. screen:expect { any = [[two lines]] }
  704. -- non-modifier prefix
  705. feed(':silent tabedit %s/tw/to')
  706. screen:expect([[
  707. Inc substitution on |
  708. two lines |
  709. Inc substitution on |
  710. two lines |
  711. |
  712. {1:~ }|*9
  713. :silent tabedit %s/tw/to^ |
  714. ]])
  715. feed('<Esc>')
  716. -- leading colons
  717. feed(':::%s/tw/to')
  718. screen:expect { any = [[{20:to}o lines]] }
  719. feed('<Esc>')
  720. screen:expect { any = [[two lines]] }
  721. end)
  722. it('ignores new-window modifiers when splitting the preview window', function()
  723. -- one modifier
  724. feed(':topleft %s/tw/to')
  725. screen:expect([[
  726. Inc substitution on |
  727. {20:to}o lines |
  728. Inc substitution on |
  729. {20:to}o lines |
  730. |
  731. {3:[No Name] [+] }|
  732. |2| {20:to}o lines |
  733. |4| {20:to}o lines |
  734. {1:~ }|*5
  735. {2:[Preview] }|
  736. :topleft %s/tw/to^ |
  737. ]])
  738. feed('<Esc>')
  739. screen:expect { any = [[two lines]] }
  740. -- multiple modifiers
  741. feed(':topleft vert %s/tw/to')
  742. screen:expect([[
  743. Inc substitution on |
  744. {20:to}o lines |
  745. Inc substitution on |
  746. {20:to}o lines |
  747. |
  748. {3:[No Name] [+] }|
  749. |2| {20:to}o lines |
  750. |4| {20:to}o lines |
  751. {1:~ }|*5
  752. {2:[Preview] }|
  753. :topleft vert %s/tw/to^ |
  754. ]])
  755. feed('<Esc>')
  756. screen:expect { any = [[two lines]] }
  757. end)
  758. it('shows split window when typing the pattern', function()
  759. feed(':%s/tw')
  760. screen:expect([[
  761. Inc substitution on |
  762. {20:tw}o lines |
  763. Inc substitution on |
  764. {20:tw}o lines |
  765. |
  766. {3:[No Name] [+] }|
  767. |2| {20:tw}o lines |
  768. |4| {20:tw}o lines |
  769. {1:~ }|*5
  770. {2:[Preview] }|
  771. :%s/tw^ |
  772. ]])
  773. end)
  774. it('shows preview with empty replacement', function()
  775. feed(':%s/tw/')
  776. screen:expect([[
  777. Inc substitution on |
  778. o lines |
  779. Inc substitution on |
  780. o lines |
  781. |
  782. {3:[No Name] [+] }|
  783. |2| o lines |
  784. |4| o lines |
  785. {1:~ }|*5
  786. {2:[Preview] }|
  787. :%s/tw/^ |
  788. ]])
  789. feed('x')
  790. screen:expect([[
  791. Inc substitution on |
  792. {20:x}o lines |
  793. Inc substitution on |
  794. {20:x}o lines |
  795. |
  796. {3:[No Name] [+] }|
  797. |2| {20:x}o lines |
  798. |4| {20:x}o lines |
  799. {1:~ }|*5
  800. {2:[Preview] }|
  801. :%s/tw/x^ |
  802. ]])
  803. feed('<bs>')
  804. screen:expect([[
  805. Inc substitution on |
  806. o lines |
  807. Inc substitution on |
  808. o lines |
  809. |
  810. {3:[No Name] [+] }|
  811. |2| o lines |
  812. |4| o lines |
  813. {1:~ }|*5
  814. {2:[Preview] }|
  815. :%s/tw/^ |
  816. ]])
  817. end)
  818. it('shows split window when typing replacement', function()
  819. feed(':%s/tw/XX')
  820. screen:expect([[
  821. Inc substitution on |
  822. {20:XX}o lines |
  823. Inc substitution on |
  824. {20:XX}o lines |
  825. |
  826. {3:[No Name] [+] }|
  827. |2| {20:XX}o lines |
  828. |4| {20:XX}o lines |
  829. {1:~ }|*5
  830. {2:[Preview] }|
  831. :%s/tw/XX^ |
  832. ]])
  833. end)
  834. it('does not show split window for :s/', function()
  835. feed('2gg')
  836. feed(':s/tw')
  837. screen:expect([[
  838. Inc substitution on |
  839. {20:tw}o lines |
  840. Inc substitution on |
  841. two lines |
  842. |
  843. {1:~ }|*9
  844. :s/tw^ |
  845. ]])
  846. end)
  847. it("'hlsearch' is active, 'cursorline' is not", function()
  848. command('set hlsearch cursorline')
  849. feed('gg')
  850. -- Assert that 'cursorline' is active.
  851. screen:expect([[
  852. {21:^Inc substitution on }|
  853. two lines |
  854. Inc substitution on |
  855. two lines |
  856. |
  857. {1:~ }|*9
  858. |
  859. ]])
  860. feed(':%s/tw')
  861. -- 'cursorline' is NOT active during preview.
  862. screen:expect([[
  863. Inc substitution on |
  864. {20:tw}o lines |
  865. Inc substitution on |
  866. {20:tw}o lines |
  867. |
  868. {3:[No Name] [+] }|
  869. |2| {20:tw}o lines |
  870. |4| {20:tw}o lines |
  871. {1:~ }|*5
  872. {2:[Preview] }|
  873. :%s/tw^ |
  874. ]])
  875. end)
  876. it('highlights the replacement text', function()
  877. feed('ggO')
  878. feed('M M M<esc>')
  879. feed(':%s/M/123/g')
  880. screen:expect([[
  881. {20:123} {20:123} {20:123} |
  882. Inc substitution on |
  883. two lines |
  884. Inc substitution on |
  885. two lines |
  886. {3:[No Name] [+] }|
  887. |1| {20:123} {20:123} {20:123} |
  888. {1:~ }|*6
  889. {2:[Preview] }|
  890. :%s/M/123/g^ |
  891. ]])
  892. end)
  893. it("highlights nothing when there's no match", function()
  894. feed('gg')
  895. feed(':%s/Inx')
  896. screen:expect([[
  897. Inc substitution on |
  898. two lines |
  899. Inc substitution on |
  900. two lines |
  901. |
  902. {3:[No Name] [+] }|
  903. |
  904. {1:~ }|*6
  905. {2:[Preview] }|
  906. :%s/Inx^ |
  907. ]])
  908. end)
  909. it('previews correctly when previewhight is small', function()
  910. command('set cwh=3')
  911. command('set hls')
  912. feed('ggdG')
  913. insert(string.rep('abc abc abc\n', 20))
  914. feed(':%s/abc/MMM/g')
  915. screen:expect([[
  916. {20:MMM} {20:MMM} {20:MMM} |*9
  917. {3:[No Name] [+] }|
  918. | 1| {20:MMM} {20:MMM} {20:MMM} |
  919. | 2| {20:MMM} {20:MMM} {20:MMM} |
  920. | 3| {20:MMM} {20:MMM} {20:MMM} |
  921. {2:[Preview] }|
  922. :%s/abc/MMM/g^ |
  923. ]])
  924. end)
  925. it('actually replaces text', function()
  926. feed(':%s/tw/XX/g')
  927. poke_eventloop()
  928. feed('<Enter>')
  929. screen:expect([[
  930. Inc substitution on |
  931. XXo lines |
  932. Inc substitution on |
  933. ^XXo lines |
  934. |
  935. {1:~ }|*9
  936. :%s/tw/XX/g |
  937. ]])
  938. end)
  939. it('shows correct line numbers with many lines', function()
  940. feed('gg')
  941. feed('2yy')
  942. feed('2000p')
  943. command('1,1000s/tw/BB/g')
  944. feed(':%s/tw/X')
  945. screen:expect([[
  946. Inc substitution on |
  947. BBo lines |
  948. Inc substitution on |
  949. {20:X}o lines |
  950. Inc substitution on |
  951. {3:[No Name] [+] }|
  952. |1001| {20:X}o lines |
  953. |1003| {20:X}o lines |
  954. |1005| {20:X}o lines |
  955. |1007| {20:X}o lines |
  956. |1009| {20:X}o lines |
  957. |1011| {20:X}o lines |
  958. |1013| {20:X}o lines |
  959. {2:[Preview] }|
  960. :%s/tw/X^ |
  961. ]])
  962. end)
  963. it('does not spam the buffer numbers', function()
  964. -- The preview buffer is re-used (unless user deleted it), so buffer numbers
  965. -- will not increase on each keystroke.
  966. feed(':%s/tw/Xo/g')
  967. -- Delete and re-type the g a few times.
  968. feed('<BS>')
  969. poke_eventloop()
  970. feed('g')
  971. poke_eventloop()
  972. feed('<BS>')
  973. poke_eventloop()
  974. feed('g')
  975. poke_eventloop()
  976. feed('<CR>')
  977. poke_eventloop()
  978. feed(':vs tmp<enter>')
  979. eq(3, fn.bufnr('$'))
  980. end)
  981. it('works with the n flag', function()
  982. feed(':%s/tw/Mix/n')
  983. poke_eventloop()
  984. feed('<Enter>')
  985. screen:expect([[
  986. Inc substitution on |
  987. two lines |
  988. Inc substitution on |
  989. two lines |
  990. ^ |
  991. {1:~ }|*9
  992. 2 matches on 2 lines |
  993. ]])
  994. end)
  995. it("deactivates if 'redrawtime' is exceeded #5602", function()
  996. -- prevent redraws from 'incsearch'
  997. api.nvim_set_option_value('incsearch', false, {})
  998. -- Assert that 'inccommand' is ENABLED initially.
  999. eq('split', eval('&inccommand'))
  1000. -- Set 'redrawtime' to minimal value, to ensure timeout is triggered.
  1001. command('set redrawtime=1 nowrap')
  1002. -- Load a big file.
  1003. command('silent edit! test/functional/fixtures/bigfile_oneline.txt')
  1004. -- Start :substitute with a slow pattern.
  1005. feed([[:%s/B.*N/x]])
  1006. poke_eventloop()
  1007. -- Assert that 'inccommand' is DISABLED in cmdline mode.
  1008. eq('', eval('&inccommand'))
  1009. -- Assert that preview cleared (or never manifested).
  1010. screen:expect([[
  1011. 0000;<control>;Cc;0;BN;;;;;N;N|
  1012. 2F923;CJK COMPATIBILITY IDEOGR|
  1013. 2F924;CJK COMPATIBILITY IDEOGR|
  1014. 2F925;CJK COMPATIBILITY IDEOGR|
  1015. 2F926;CJK COMPATIBILITY IDEOGR|
  1016. 2F927;CJK COMPATIBILITY IDEOGR|
  1017. 2F928;CJK COMPATIBILITY IDEOGR|
  1018. 2F929;CJK COMPATIBILITY IDEOGR|
  1019. 2F92A;CJK COMPATIBILITY IDEOGR|
  1020. 2F92B;CJK COMPATIBILITY IDEOGR|
  1021. 2F92C;CJK COMPATIBILITY IDEOGR|
  1022. 2F92D;CJK COMPATIBILITY IDEOGR|
  1023. 2F92E;CJK COMPATIBILITY IDEOGR|
  1024. 2F92F;CJK COMPATIBILITY IDEOGR|
  1025. :%s/B.*N/x^ |
  1026. ]])
  1027. -- Assert that 'inccommand' is again ENABLED after leaving cmdline mode.
  1028. feed([[<C-\><C-N>]])
  1029. eq('split', eval('&inccommand'))
  1030. end)
  1031. it("deactivates if 'foldexpr' is slow #9557", function()
  1032. insert([[
  1033. a
  1034. a
  1035. a
  1036. a
  1037. a
  1038. a
  1039. a
  1040. a
  1041. ]])
  1042. source([[
  1043. function! Slowfold(lnum)
  1044. sleep 5m
  1045. return a:lnum % 3
  1046. endfun
  1047. ]])
  1048. command('set redrawtime=1 inccommand=split')
  1049. command('set foldmethod=expr foldexpr=Slowfold(v:lnum)')
  1050. feed(':%s/a/bcdef')
  1051. -- Assert that 'inccommand' is DISABLED in cmdline mode.
  1052. retry(nil, nil, function()
  1053. eq('', eval('&inccommand'))
  1054. end)
  1055. -- Assert that 'inccommand' is again ENABLED after leaving cmdline mode.
  1056. feed([[<C-\><C-N>]])
  1057. retry(nil, nil, function()
  1058. eq('split', eval('&inccommand'))
  1059. end)
  1060. end)
  1061. it('clears preview if non-previewable command is edited #5585', function()
  1062. feed('gg')
  1063. -- Put a non-previewable command in history.
  1064. feed(":echo 'foo'<CR>")
  1065. -- Start an incomplete :substitute command.
  1066. feed(':1,2s/t/X')
  1067. screen:expect([[
  1068. Inc subs{20:X}itution on |
  1069. {20:X}wo lines |
  1070. Inc substitution on |
  1071. two lines |
  1072. |
  1073. {3:[No Name] [+] }|
  1074. |1| Inc subs{20:X}itution on |
  1075. |2| {20:X}wo lines |
  1076. {1:~ }|*5
  1077. {2:[Preview] }|
  1078. :1,2s/t/X^ |
  1079. ]])
  1080. -- Select the previous command.
  1081. feed('<C-P>')
  1082. -- Assert that preview was cleared.
  1083. screen:expect([[
  1084. Inc substitution on |
  1085. two lines |
  1086. Inc substitution on |
  1087. two lines |
  1088. |
  1089. {1:~ }|*9
  1090. :echo 'foo'^ |
  1091. ]])
  1092. end)
  1093. it([[preview changes correctly with c_CTRL-R_= and c_CTRL-\_e]], function()
  1094. feed('gg')
  1095. feed(':1,2s/t/X')
  1096. screen:expect([[
  1097. Inc subs{20:X}itution on |
  1098. {20:X}wo lines |
  1099. Inc substitution on |
  1100. two lines |
  1101. |
  1102. {3:[No Name] [+] }|
  1103. |1| Inc subs{20:X}itution on |
  1104. |2| {20:X}wo lines |
  1105. {1:~ }|*5
  1106. {2:[Preview] }|
  1107. :1,2s/t/X^ |
  1108. ]])
  1109. feed([[<C-R>='Y']])
  1110. -- preview should be unchanged during c_CTRL-R_= editing
  1111. screen:expect([[
  1112. Inc subs{20:X}itution on |
  1113. {20:X}wo lines |
  1114. Inc substitution on |
  1115. two lines |
  1116. |
  1117. {3:[No Name] [+] }|
  1118. |1| Inc subs{20:X}itution on |
  1119. |2| {20:X}wo lines |
  1120. {1:~ }|*5
  1121. {2:[Preview] }|
  1122. ={26:'Y'}^ |
  1123. ]])
  1124. feed('<CR>')
  1125. -- preview should be changed by the result of the expression
  1126. screen:expect([[
  1127. Inc subs{20:XY}itution on |
  1128. {20:XY}wo lines |
  1129. Inc substitution on |
  1130. two lines |
  1131. |
  1132. {3:[No Name] [+] }|
  1133. |1| Inc subs{20:XY}itution on |
  1134. |2| {20:XY}wo lines |
  1135. {1:~ }|*5
  1136. {2:[Preview] }|
  1137. :1,2s/t/XY^ |
  1138. ]])
  1139. feed([[<C-\>e'echo']])
  1140. -- preview should be unchanged during c_CTRL-\_e editing
  1141. screen:expect([[
  1142. Inc subs{20:XY}itution on |
  1143. {20:XY}wo lines |
  1144. Inc substitution on |
  1145. two lines |
  1146. |
  1147. {3:[No Name] [+] }|
  1148. |1| Inc subs{20:XY}itution on |
  1149. |2| {20:XY}wo lines |
  1150. {1:~ }|*5
  1151. {2:[Preview] }|
  1152. ={26:'echo'}^ |
  1153. ]])
  1154. feed('<CR>')
  1155. -- preview should be cleared if command is changed to a non-previewable one
  1156. screen:expect([[
  1157. Inc substitution on |
  1158. two lines |
  1159. Inc substitution on |
  1160. two lines |
  1161. |
  1162. {1:~ }|*9
  1163. :echo^ |
  1164. ]])
  1165. end)
  1166. end)
  1167. describe('inccommand=nosplit', function()
  1168. local screen
  1169. before_each(function()
  1170. clear()
  1171. screen = Screen.new(20, 10)
  1172. common_setup(screen, 'nosplit', default_text .. default_text)
  1173. end)
  1174. it('works with :smagic, :snomagic', function()
  1175. command('set hlsearch')
  1176. insert('Line *.3.* here')
  1177. feed(':%smagic/3.*/X') -- start :smagic command
  1178. screen:expect([[
  1179. Inc substitution on |
  1180. two lines |
  1181. Inc substitution on |
  1182. two lines |
  1183. Line *.{20:X} |
  1184. {1:~ }|*4
  1185. :%smagic/3.*/X^ |
  1186. ]])
  1187. feed([[<C-\><C-N>]]) -- cancel
  1188. feed(':%snomagic/3.*/X') -- start :snomagic command
  1189. screen:expect([[
  1190. Inc substitution on |
  1191. two lines |
  1192. Inc substitution on |
  1193. two lines |
  1194. Line *.{20:X} here |
  1195. {1:~ }|*4
  1196. :%snomagic/3.*/X^ |
  1197. ]])
  1198. end)
  1199. it('shows preview when cmd modifiers are present', function()
  1200. -- one modifier
  1201. feed(':keeppatterns %s/tw/to')
  1202. screen:expect { any = [[{20:to}o lines]] }
  1203. feed('<Esc>')
  1204. screen:expect { any = [[two lines]] }
  1205. -- multiple modifiers
  1206. feed(':keeppatterns silent %s/tw/to')
  1207. screen:expect { any = [[{20:to}o lines]] }
  1208. feed('<Esc>')
  1209. screen:expect { any = [[two lines]] }
  1210. -- non-modifier prefix
  1211. feed(':silent tabedit %s/tw/to')
  1212. screen:expect([[
  1213. Inc substitution on |
  1214. two lines |
  1215. Inc substitution on |
  1216. two lines |
  1217. |
  1218. {1:~ }|*2
  1219. {3: }|
  1220. :silent tabedit %s/t|
  1221. w/to^ |
  1222. ]])
  1223. end)
  1224. it('does not show window after toggling :set inccommand', function()
  1225. feed(':%s/tw/OKOK')
  1226. feed('<Esc>')
  1227. command('set icm=split')
  1228. feed(':%s/tw/OKOK')
  1229. feed('<Esc>')
  1230. command('set icm=nosplit')
  1231. feed(':%s/tw/OKOK')
  1232. poke_eventloop()
  1233. screen:expect([[
  1234. Inc substitution on |
  1235. {20:OKOK}o lines |
  1236. Inc substitution on |
  1237. {20:OKOK}o lines |
  1238. |
  1239. {1:~ }|*4
  1240. :%s/tw/OKOK^ |
  1241. ]])
  1242. end)
  1243. it('never shows preview buffer', function()
  1244. command('set hlsearch')
  1245. feed(':%s/tw')
  1246. screen:expect([[
  1247. Inc substitution on |
  1248. {20:tw}o lines |
  1249. Inc substitution on |
  1250. {20:tw}o lines |
  1251. |
  1252. {1:~ }|*4
  1253. :%s/tw^ |
  1254. ]])
  1255. feed('/BM')
  1256. screen:expect([[
  1257. Inc substitution on |
  1258. {20:BM}o lines |
  1259. Inc substitution on |
  1260. {20:BM}o lines |
  1261. |
  1262. {1:~ }|*4
  1263. :%s/tw/BM^ |
  1264. ]])
  1265. feed('/')
  1266. screen:expect([[
  1267. Inc substitution on |
  1268. {20:BM}o lines |
  1269. Inc substitution on |
  1270. {20:BM}o lines |
  1271. |
  1272. {1:~ }|*4
  1273. :%s/tw/BM/^ |
  1274. ]])
  1275. feed('<enter>')
  1276. screen:expect([[
  1277. Inc substitution on |
  1278. BMo lines |
  1279. Inc substitution on |
  1280. ^BMo lines |
  1281. |
  1282. {1:~ }|*4
  1283. :%s/tw/BM/ |
  1284. ]])
  1285. end)
  1286. it('clears preview if non-previewable command is edited', function()
  1287. -- Put a non-previewable command in history.
  1288. feed(":echo 'foo'<CR>")
  1289. -- Start an incomplete :substitute command.
  1290. feed(':1,2s/t/X')
  1291. screen:expect([[
  1292. Inc subs{20:X}itution on |
  1293. {20:X}wo lines |
  1294. Inc substitution on |
  1295. two lines |
  1296. |
  1297. {1:~ }|*4
  1298. :1,2s/t/X^ |
  1299. ]])
  1300. -- Select the previous command.
  1301. feed('<C-P>')
  1302. -- Assert that preview was cleared.
  1303. screen:expect([[
  1304. Inc substitution on |
  1305. two lines |
  1306. Inc substitution on |
  1307. two lines |
  1308. |
  1309. {1:~ }|*4
  1310. :echo 'foo'^ |
  1311. ]])
  1312. end)
  1313. it('does not execute trailing bar-separated commands #7494', function()
  1314. feed(':%s/two/three/g|q!')
  1315. screen:expect([[
  1316. Inc substitution on |
  1317. {20:three} lines |
  1318. Inc substitution on |
  1319. {20:three} lines |
  1320. |
  1321. {1:~ }|*4
  1322. :%s/two/three/g|q!^ |
  1323. ]])
  1324. eq(eval('v:null'), eval('v:exiting'))
  1325. end)
  1326. it('does not break bar-separated command #8796', function()
  1327. source([[
  1328. function! F()
  1329. if v:false | return | endif
  1330. endfun
  1331. ]])
  1332. command('call timer_start(10, {-> F()}, {"repeat":-1})')
  1333. feed(':%s/')
  1334. sleep(20) -- Allow some timer activity.
  1335. screen:expect([[
  1336. Inc substitution on |
  1337. two lines |
  1338. Inc substitution on |
  1339. two lines |
  1340. |
  1341. {1:~ }|*4
  1342. :%s/^ |
  1343. ]])
  1344. end)
  1345. end)
  1346. describe(":substitute, 'inccommand' with a failing expression", function()
  1347. local screen
  1348. local cases = { '', 'split', 'nosplit' }
  1349. local function refresh(case)
  1350. clear()
  1351. screen = Screen.new(20, 10)
  1352. common_setup(screen, case, default_text)
  1353. end
  1354. it('in the pattern does nothing', function()
  1355. for _, case in pairs(cases) do
  1356. refresh(case)
  1357. command('set inccommand=' .. case)
  1358. feed(':silent! %s/tw\\(/LARD/')
  1359. poke_eventloop()
  1360. feed('<enter>')
  1361. expect(default_text)
  1362. end
  1363. end)
  1364. it('in the replacement deletes the matches', function()
  1365. for _, case in pairs(cases) do
  1366. refresh(case)
  1367. local replacements = { "\\='LARD", '\\=xx_novar__xx' }
  1368. for _, repl in pairs(replacements) do
  1369. command('set inccommand=' .. case)
  1370. feed(':silent! %s/tw/' .. repl .. '/')
  1371. poke_eventloop()
  1372. feed('<enter>')
  1373. expect(default_text:gsub('tw', ''))
  1374. command('undo')
  1375. end
  1376. end
  1377. end)
  1378. it('in the range does not error #5912', function()
  1379. for _, case in pairs(cases) do
  1380. refresh(case)
  1381. feed(':100s/')
  1382. screen:expect([[
  1383. Inc substitution on |
  1384. two lines |
  1385. |
  1386. {1:~ }|*6
  1387. :100s/^ |
  1388. ]])
  1389. feed('<enter>')
  1390. screen:expect([[
  1391. Inc substitution on |
  1392. two lines |
  1393. ^ |
  1394. {1:~ }|*6
  1395. {9:E16: Invalid range} |
  1396. ]])
  1397. end
  1398. end)
  1399. end)
  1400. describe("'inccommand' and :cnoremap", function()
  1401. local cases = { '', 'split', 'nosplit' }
  1402. local screen
  1403. local function refresh(case, visual)
  1404. clear()
  1405. screen = visual and Screen.new(80, 10) or nil
  1406. common_setup(screen, case, default_text)
  1407. end
  1408. it('work with remapped characters', function()
  1409. for _, case in pairs(cases) do
  1410. refresh(case)
  1411. local cmd = '%s/lines/LINES/g'
  1412. for i = 1, string.len(cmd) do
  1413. local c = string.sub(cmd, i, i)
  1414. command('cnoremap ' .. c .. ' ' .. c)
  1415. end
  1416. feed(':' .. cmd)
  1417. poke_eventloop()
  1418. feed('<CR>')
  1419. expect([[
  1420. Inc substitution on
  1421. two LINES
  1422. ]])
  1423. end
  1424. end)
  1425. it('work when mappings move the cursor', function()
  1426. for _, case in pairs(cases) do
  1427. refresh(case)
  1428. command('cnoremap ,S LINES/<left><left><left><left><left><left>')
  1429. feed(':%s/lines/')
  1430. poke_eventloop()
  1431. feed(',S')
  1432. poke_eventloop()
  1433. feed('or three <enter>')
  1434. poke_eventloop()
  1435. expect([[
  1436. Inc substitution on
  1437. two or three LINES
  1438. ]])
  1439. command('cnoremap ;S /X/<left><left><left>')
  1440. feed(':%s/')
  1441. poke_eventloop()
  1442. feed(';S')
  1443. poke_eventloop()
  1444. feed('I<enter>')
  1445. expect([[
  1446. Xnc substitution on
  1447. two or three LXNES
  1448. ]])
  1449. command('cnoremap ,T //Y/<left><left><left>')
  1450. feed(':%s')
  1451. poke_eventloop()
  1452. feed(',T')
  1453. poke_eventloop()
  1454. feed('X<enter>')
  1455. expect([[
  1456. Ync substitution on
  1457. two or three LYNES
  1458. ]])
  1459. command('cnoremap ;T s//Z/<left><left><left>')
  1460. feed(':%')
  1461. poke_eventloop()
  1462. feed(';T')
  1463. poke_eventloop()
  1464. feed('Y<enter>')
  1465. expect([[
  1466. Znc substitution on
  1467. two or three LZNES
  1468. ]])
  1469. end
  1470. end)
  1471. it('still works with a broken mapping', function()
  1472. for _, case in pairs(cases) do
  1473. refresh(case, true)
  1474. command("cnoremap <expr> x execute('bwipeout!')[-1].'x'")
  1475. feed(':%s/tw/tox<enter>')
  1476. screen:expect { any = [[{9:^E565:]] }
  1477. feed('<c-c>')
  1478. -- error thrown b/c of the mapping
  1479. neq(nil, eval('v:errmsg'):find('^E565:'))
  1480. expect([[
  1481. Inc substitution on
  1482. toxo lines
  1483. ]])
  1484. end
  1485. end)
  1486. it('work when temporarily moving the cursor', function()
  1487. for _, case in pairs(cases) do
  1488. refresh(case)
  1489. command("cnoremap <expr> x cursor(1, 1)[-1].'x'")
  1490. feed(':%s/tw/tox')
  1491. poke_eventloop()
  1492. feed('/g<enter>')
  1493. expect(default_text:gsub('tw', 'tox'))
  1494. end
  1495. end)
  1496. it("work when a mapping disables 'inccommand'", function()
  1497. for _, case in pairs(cases) do
  1498. refresh(case)
  1499. command("cnoremap <expr> x execute('set inccommand=')[-1]")
  1500. feed(':%s/tw/tox')
  1501. poke_eventloop()
  1502. feed('a/g<enter>')
  1503. expect(default_text:gsub('tw', 'toa'))
  1504. end
  1505. end)
  1506. it('work with a complex mapping', function()
  1507. for _, case in pairs(cases) do
  1508. refresh(case)
  1509. source([[cnoremap x <C-\>eextend(g:, {'fo': getcmdline()})
  1510. \.fo<CR><C-c>:new<CR>:bw!<CR>:<C-r>=remove(g:, 'fo')<CR>x]])
  1511. feed(':%s/tw/tox')
  1512. poke_eventloop()
  1513. feed('/<enter>')
  1514. expect(default_text:gsub('tw', 'tox'))
  1515. end
  1516. end)
  1517. end)
  1518. describe("'inccommand' autocommands", function()
  1519. before_each(clear)
  1520. -- keys are events to be tested
  1521. -- values are arrays like
  1522. -- { open = { 1 }, close = { 2, 3} }
  1523. -- which would mean that during the test below the event fires for
  1524. -- buffer 1 when opening the preview window, and for buffers 2 and 3
  1525. -- when closing the preview window
  1526. local eventsExpected = {
  1527. BufAdd = {},
  1528. BufDelete = {},
  1529. BufEnter = {},
  1530. BufFilePost = {},
  1531. BufFilePre = {},
  1532. BufHidden = {},
  1533. BufLeave = {},
  1534. BufNew = {},
  1535. BufNewFile = {},
  1536. BufRead = {},
  1537. BufReadCmd = {},
  1538. BufReadPre = {},
  1539. BufUnload = {},
  1540. BufWinEnter = {},
  1541. BufWinLeave = {},
  1542. BufWipeout = {},
  1543. BufWrite = {},
  1544. BufWriteCmd = {},
  1545. BufWritePost = {},
  1546. Syntax = {},
  1547. FileType = {},
  1548. WinEnter = {},
  1549. WinLeave = {},
  1550. CmdwinEnter = {},
  1551. CmdwinLeave = {},
  1552. }
  1553. local function bufferlist(q)
  1554. local s = ''
  1555. for _, buffer in pairs(q) do
  1556. s = s .. ', ' .. tostring(buffer)
  1557. end
  1558. return s
  1559. end
  1560. -- fill the table with default values
  1561. for event, _ in pairs(eventsExpected) do
  1562. eventsExpected[event].open = eventsExpected[event].open or {}
  1563. eventsExpected[event].close = eventsExpected[event].close or {}
  1564. end
  1565. local function register_autocmd(event)
  1566. api.nvim_set_var(event .. '_fired', {})
  1567. command('autocmd ' .. event .. ' * call add(g:' .. event .. "_fired, expand('<abuf>'))")
  1568. end
  1569. it('are not fired when splitting', function()
  1570. common_setup(nil, 'split', default_text)
  1571. local eventsObserved = {}
  1572. for event, _ in pairs(eventsExpected) do
  1573. eventsObserved[event] = {}
  1574. register_autocmd(event)
  1575. end
  1576. feed(':%s/tw')
  1577. for event, _ in pairs(eventsExpected) do
  1578. eventsObserved[event].open = api.nvim_get_var(event .. '_fired')
  1579. api.nvim_set_var(event .. '_fired', {})
  1580. end
  1581. feed('/<enter>')
  1582. for event, _ in pairs(eventsExpected) do
  1583. eventsObserved[event].close = api.nvim_get_var(event .. '_fired')
  1584. end
  1585. for event, _ in pairs(eventsExpected) do
  1586. eq(
  1587. event .. bufferlist(eventsExpected[event].open),
  1588. event .. bufferlist(eventsObserved[event].open)
  1589. )
  1590. eq(
  1591. event .. bufferlist(eventsExpected[event].close),
  1592. event .. bufferlist(eventsObserved[event].close)
  1593. )
  1594. end
  1595. end)
  1596. end)
  1597. describe("'inccommand' split windows", function()
  1598. local screen
  1599. local function refresh()
  1600. clear()
  1601. screen = Screen.new(40, 30)
  1602. common_setup(screen, 'split', default_text)
  1603. end
  1604. it('work after more splits', function()
  1605. refresh()
  1606. feed('gg')
  1607. command('vsplit')
  1608. command('split')
  1609. feed(':%s/tw')
  1610. screen:expect([[
  1611. Inc substitution on │Inc substitution on|
  1612. {20:tw}o lines │{20:tw}o lines |
  1613. │ |
  1614. {1:~ }│{1:~ }|*11
  1615. {3:[No Name] [+] }│{1:~ }|
  1616. Inc substitution on │{1:~ }|
  1617. {20:tw}o lines │{1:~ }|
  1618. │{1:~ }|
  1619. {1:~ }│{1:~ }|*2
  1620. {2:[No Name] [+] [No Name] [+] }|
  1621. |2| {20:tw}o lines |
  1622. {1:~ }|*6
  1623. {2:[Preview] }|
  1624. :%s/tw^ |
  1625. ]])
  1626. feed('<esc>')
  1627. command('only')
  1628. command('split')
  1629. command('vsplit')
  1630. feed(':%s/tw')
  1631. screen:expect([[
  1632. Inc substitution on │Inc substitution on|
  1633. {20:tw}o lines │{20:tw}o lines |
  1634. │ |
  1635. {1:~ }│{1:~ }|*11
  1636. {3:[No Name] [+] }{2:[No Name] [+] }|
  1637. Inc substitution on |
  1638. {20:tw}o lines |
  1639. |
  1640. {1:~ }|*2
  1641. {2:[No Name] [+] }|
  1642. |2| {20:tw}o lines |
  1643. {1:~ }|*6
  1644. {2:[Preview] }|
  1645. :%s/tw^ |
  1646. ]])
  1647. end)
  1648. local settings = {
  1649. 'splitbelow',
  1650. 'splitright',
  1651. 'noequalalways',
  1652. 'equalalways eadirection=ver',
  1653. 'equalalways eadirection=hor',
  1654. 'equalalways eadirection=both',
  1655. }
  1656. it('are not affected by various settings', function()
  1657. for _, setting in pairs(settings) do
  1658. refresh()
  1659. command('set ' .. setting)
  1660. feed(':%s/tw')
  1661. screen:expect([[
  1662. Inc substitution on |
  1663. {20:tw}o lines |
  1664. |
  1665. {1:~ }|*17
  1666. {3:[No Name] [+] }|
  1667. |2| {20:tw}o lines |
  1668. {1:~ }|*6
  1669. {2:[Preview] }|
  1670. :%s/tw^ |
  1671. ]])
  1672. end
  1673. end)
  1674. it("don't open if there's not enough room", function()
  1675. refresh()
  1676. screen:try_resize(40, 3)
  1677. feed('gg:%s/tw')
  1678. screen:expect([[
  1679. Inc substitution on |
  1680. {20:tw}o lines |
  1681. :%s/tw^ |
  1682. ]])
  1683. end)
  1684. end)
  1685. describe("'inccommand' with 'gdefault'", function()
  1686. before_each(function()
  1687. clear()
  1688. end)
  1689. it('does not lock up #7244', function()
  1690. common_setup(nil, 'nosplit', '{')
  1691. command('set gdefault')
  1692. feed(':s/{\\n')
  1693. eq({ mode = 'c', blocking = false }, api.nvim_get_mode())
  1694. feed('/A<Enter>')
  1695. expect('A')
  1696. eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
  1697. end)
  1698. it('with multiline text and range, does not lock up #7244', function()
  1699. common_setup(nil, 'nosplit', '{\n\n{')
  1700. command('set gdefault')
  1701. feed(':%s/{\\n')
  1702. eq({ mode = 'c', blocking = false }, api.nvim_get_mode())
  1703. feed('/A<Enter>')
  1704. expect('A\nA')
  1705. eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
  1706. end)
  1707. it('does not crash on zero-width matches #7485', function()
  1708. common_setup(nil, 'split', default_text)
  1709. command('set gdefault')
  1710. feed('gg')
  1711. feed('Vj')
  1712. feed(':s/\\%V')
  1713. eq({ mode = 'c', blocking = false }, api.nvim_get_mode())
  1714. feed('<Esc>')
  1715. eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
  1716. end)
  1717. it('removes highlights after abort for a zero-width match', function()
  1718. local screen = Screen.new(30, 5)
  1719. common_setup(screen, 'nosplit', default_text)
  1720. command('set gdefault')
  1721. feed(':%s/\\%1c/a/')
  1722. screen:expect([[
  1723. {20:a}Inc substitution on |
  1724. {20:a}two lines |
  1725. {20:a} |
  1726. {1:~ }|
  1727. :%s/\%1c/a/^ |
  1728. ]])
  1729. feed('<Esc>')
  1730. screen:expect([[
  1731. Inc substitution on |
  1732. two lines |
  1733. ^ |
  1734. {1:~ }|
  1735. |
  1736. ]])
  1737. end)
  1738. end)
  1739. describe(':substitute', function()
  1740. local screen
  1741. before_each(function()
  1742. clear()
  1743. screen = Screen.new(30, 15)
  1744. end)
  1745. it('inccommand=split, highlights multiline substitutions', function()
  1746. common_setup(screen, 'split', multiline_text)
  1747. feed('gg')
  1748. feed(':%s/2\\_.*X')
  1749. screen:expect([[
  1750. 1 {20:2 3} |
  1751. {20:A B C} |
  1752. {20:4 5 6} |
  1753. {20:X} Y Z |
  1754. 7 8 9 |
  1755. {3:[No Name] [+] }|
  1756. |1| 1 {20:2 3} |
  1757. |2|{20: A B C} |
  1758. |3|{20: 4 5 6} |
  1759. |4|{20: X} Y Z |
  1760. {1:~ }|*3
  1761. {2:[Preview] }|
  1762. :%s/2\_.*X^ |
  1763. ]])
  1764. feed('/MMM')
  1765. screen:expect([[
  1766. 1 {20:MMM} Y Z |
  1767. 7 8 9 |
  1768. |
  1769. {1:~ }|*2
  1770. {3:[No Name] [+] }|
  1771. |1| 1 {20:MMM} Y Z |
  1772. {1:~ }|*6
  1773. {2:[Preview] }|
  1774. :%s/2\_.*X/MMM^ |
  1775. ]])
  1776. feed('\\rK\\rLLL')
  1777. screen:expect([[
  1778. 1 {20:MMM} |
  1779. {20:K} |
  1780. {20:LLL} Y Z |
  1781. 7 8 9 |
  1782. |
  1783. {3:[No Name] [+] }|
  1784. |1| 1 {20:MMM} |
  1785. |2|{20: K} |
  1786. |3|{20: LLL} Y Z |
  1787. {1:~ }|*4
  1788. {2:[Preview] }|
  1789. :%s/2\_.*X/MMM\rK\rLLL^ |
  1790. ]])
  1791. end)
  1792. it('inccommand=nosplit, highlights multiline substitutions', function()
  1793. common_setup(screen, 'nosplit', multiline_text)
  1794. feed('gg')
  1795. feed(':%s/2\\_.*X/MMM')
  1796. screen:expect([[
  1797. 1 {20:MMM} Y Z |
  1798. 7 8 9 |
  1799. |
  1800. {1:~ }|*11
  1801. :%s/2\_.*X/MMM^ |
  1802. ]])
  1803. feed('\\rK\\rLLL')
  1804. screen:expect([[
  1805. 1 {20:MMM} |
  1806. {20:K} |
  1807. {20:LLL} Y Z |
  1808. 7 8 9 |
  1809. |
  1810. {1:~ }|*9
  1811. :%s/2\_.*X/MMM\rK\rLLL^ |
  1812. ]])
  1813. end)
  1814. it('inccommand=split, highlights multiple matches on a line', function()
  1815. common_setup(screen, 'split', multimatch_text)
  1816. command('set gdefault')
  1817. feed('gg')
  1818. feed(':%s/a/XLK')
  1819. screen:expect([[
  1820. {20:XLK} bdc e{20:XLK}e {20:XLK} fgl lzi{20:XLK} r|
  1821. x |
  1822. |
  1823. {1:~ }|*2
  1824. {3:[No Name] [+] }|
  1825. |1| {20:XLK} bdc e{20:XLK}e {20:XLK} fgl lzi{20:X}|
  1826. {20:LK} r |
  1827. {1:~ }|*5
  1828. {2:[Preview] }|
  1829. :%s/a/XLK^ |
  1830. ]])
  1831. end)
  1832. it('inccommand=nosplit, highlights multiple matches on a line', function()
  1833. common_setup(screen, 'nosplit', multimatch_text)
  1834. command('set gdefault')
  1835. feed('gg')
  1836. feed(':%s/a/XLK')
  1837. screen:expect([[
  1838. {20:XLK} bdc e{20:XLK}e {20:XLK} fgl lzi{20:XLK} r|
  1839. x |
  1840. |
  1841. {1:~ }|*11
  1842. :%s/a/XLK^ |
  1843. ]])
  1844. end)
  1845. it('inccommand=split, with \\zs', function()
  1846. common_setup(screen, 'split', multiline_text)
  1847. feed('gg')
  1848. feed(':%s/[0-9]\\n\\zs[A-Z]/OKO')
  1849. screen:expect([[
  1850. {20:OKO} B C |
  1851. 4 5 6 |
  1852. {20:OKO} Y Z |
  1853. 7 8 9 |
  1854. |
  1855. {3:[No Name] [+] }|
  1856. |1| 1 2 3 |
  1857. |2| {20:OKO} B C |
  1858. |3| 4 5 6 |
  1859. |4| {20:OKO} Y Z |
  1860. {1:~ }|*3
  1861. {2:[Preview] }|
  1862. :%s/[0-9]\n\zs[A-Z]/OKO^ |
  1863. ]])
  1864. end)
  1865. it('inccommand=nosplit, with \\zs', function()
  1866. common_setup(screen, 'nosplit', multiline_text)
  1867. feed('gg')
  1868. feed(':%s/[0-9]\\n\\zs[A-Z]/OKO')
  1869. screen:expect([[
  1870. 1 2 3 |
  1871. {20:OKO} B C |
  1872. 4 5 6 |
  1873. {20:OKO} Y Z |
  1874. 7 8 9 |
  1875. |
  1876. {1:~ }|*8
  1877. :%s/[0-9]\n\zs[A-Z]/OKO^ |
  1878. ]])
  1879. end)
  1880. it('inccommand=split, substitutions of different length', function()
  1881. common_setup(screen, 'split', 'T T123 T2T TTT T090804\nx')
  1882. feed(':%s/T\\([0-9]\\+\\)/\\1\\1/g')
  1883. screen:expect([[
  1884. T {20:123123} {20:22}T TTT {20:090804090804} |
  1885. x |
  1886. {1:~ }|*3
  1887. {3:[No Name] [+] }|
  1888. |1| T {20:123123} {20:22}T TTT {20:090804090}|
  1889. {20:804} |
  1890. {1:~ }|*5
  1891. {2:[Preview] }|
  1892. :%s/T\([0-9]\+\)/\1\1/g^ |
  1893. ]])
  1894. end)
  1895. it('inccommand=nosplit, substitutions of different length', function()
  1896. common_setup(screen, 'nosplit', 'T T123 T2T TTT T090804\nx')
  1897. feed(':%s/T\\([0-9]\\+\\)/\\1\\1/g')
  1898. screen:expect([[
  1899. T {20:123123} {20:22}T TTT {20:090804090804} |
  1900. x |
  1901. {1:~ }|*12
  1902. :%s/T\([0-9]\+\)/\1\1/g^ |
  1903. ]])
  1904. end)
  1905. it('inccommand=split, contraction of lines', function()
  1906. local text = [[
  1907. T T123 T T123 T2T TT T23423424
  1908. x
  1909. afa Q
  1910. adf la;lkd R
  1911. alx
  1912. ]]
  1913. common_setup(screen, 'split', text)
  1914. feed(':%s/[QR]\\n')
  1915. screen:expect([[
  1916. afa {20:Q} |
  1917. adf la;lkd {20:R} |
  1918. alx |
  1919. |
  1920. {1:~ }|
  1921. {3:[No Name] [+] }|
  1922. |3| afa {20:Q} |
  1923. |4|{20: }adf la;lkd {20:R} |
  1924. |5|{20: }alx |
  1925. {1:~ }|*4
  1926. {2:[Preview] }|
  1927. :%s/[QR]\n^ |
  1928. ]])
  1929. feed('/KKK')
  1930. screen:expect([[
  1931. T T123 T T123 T2T TT T23423424|
  1932. x |
  1933. afa {20:KKK}adf la;lkd {20:KKK}alx |
  1934. |
  1935. {1:~ }|
  1936. {3:[No Name] [+] }|
  1937. |3| afa {20:KKK}adf la;lkd {20:KKK}alx |
  1938. {1:~ }|*6
  1939. {2:[Preview] }|
  1940. :%s/[QR]\n/KKK^ |
  1941. ]])
  1942. end)
  1943. it('inccommand=nosplit, contraction of lines', function()
  1944. local text = [[
  1945. T T123 T T123 T2T TT T23423424
  1946. x
  1947. afa Q
  1948. adf la;lkd R
  1949. alx
  1950. ]]
  1951. common_setup(screen, 'nosplit', text)
  1952. feed(':%s/[QR]\\n/KKK')
  1953. screen:expect([[
  1954. T T123 T T123 T2T TT T23423424|
  1955. x |
  1956. afa {20:KKK}adf la;lkd {20:KKK}alx |
  1957. |
  1958. {1:~ }|*10
  1959. :%s/[QR]\n/KKK^ |
  1960. ]])
  1961. end)
  1962. it('inccommand=split, contraction of two subsequent NL chars', function()
  1963. local text = [[
  1964. AAA AA
  1965. BBB BB
  1966. CCC CC
  1967. ]]
  1968. -- This used to crash, but more than 20 highlight entries are required
  1969. -- to reproduce it (so that the marktree has multiple nodes)
  1970. common_setup(screen, 'split', string.rep(text, 10))
  1971. feed(':%s/\\n\\n/<c-v><c-m>/g')
  1972. screen:expect {
  1973. grid = [[
  1974. CCC CC |
  1975. AAA AA |
  1976. BBB BB |
  1977. CCC CC |
  1978. |
  1979. {3:[No Name] [+] }|
  1980. | 1| AAA AA |
  1981. | 2|{20: }BBB BB |
  1982. | 3|{20: }CCC CC |
  1983. | 4|{20: }AAA AA |
  1984. | 5|{20: }BBB BB |
  1985. | 6|{20: }CCC CC |
  1986. | 7|{20: }AAA AA |
  1987. {2:[Preview] }|
  1988. :%s/\n\n/{18:^M}/g^ |
  1989. ]],
  1990. }
  1991. assert_alive()
  1992. end)
  1993. it('inccommand=nosplit, contraction of two subsequent NL chars', function()
  1994. local text = [[
  1995. AAA AA
  1996. BBB BB
  1997. CCC CC
  1998. ]]
  1999. common_setup(screen, 'nosplit', string.rep(text, 10))
  2000. feed(':%s/\\n\\n/<c-v><c-m>/g')
  2001. screen:expect {
  2002. grid = [[
  2003. CCC CC |
  2004. AAA AA |
  2005. BBB BB |
  2006. CCC CC |
  2007. AAA AA |
  2008. BBB BB |
  2009. CCC CC |
  2010. AAA AA |
  2011. BBB BB |
  2012. CCC CC |
  2013. AAA AA |
  2014. BBB BB |
  2015. CCC CC |
  2016. |
  2017. :%s/\n\n/{18:^M}/g^ |
  2018. ]],
  2019. }
  2020. assert_alive()
  2021. end)
  2022. it('inccommand=split, multibyte text', function()
  2023. common_setup(screen, 'split', multibyte_text)
  2024. feed(':%s/£.*ѫ/X¥¥')
  2025. screen:expect([[
  2026. a{20:X¥¥}¥KOL |
  2027. £ ¥ libm |
  2028. £ ¥ |
  2029. |
  2030. {1:~ }|
  2031. {3:[No Name] [+] }|
  2032. |1| {20:X¥¥} PEPPERS |
  2033. |2| {20:X¥¥} |
  2034. |3| a{20:X¥¥}¥KOL |
  2035. {1:~ }|*4
  2036. {2:[Preview] }|
  2037. :%s/£.*ѫ/X¥¥^ |
  2038. ]])
  2039. feed('\\ra££ ¥')
  2040. screen:expect([[
  2041. a{20:X¥¥} |
  2042. {20:a££ ¥}¥KOL |
  2043. £ ¥ libm |
  2044. £ ¥ |
  2045. |
  2046. {3:[No Name] [+] }|
  2047. |1| {20:X¥¥} |
  2048. |2|{20: a££ ¥} PEPPERS |
  2049. |3| {20:X¥¥} |
  2050. |4|{20: a££ ¥} |
  2051. |5| a{20:X¥¥} |
  2052. |6|{20: a££ ¥}¥KOL |
  2053. {1:~ }|
  2054. {2:[Preview] }|
  2055. :%s/£.*ѫ/X¥¥\ra££ ¥^ |
  2056. ]])
  2057. end)
  2058. it('inccommand=nosplit, multibyte text', function()
  2059. common_setup(screen, 'nosplit', multibyte_text)
  2060. feed(':%s/£.*ѫ/X¥¥')
  2061. screen:expect([[
  2062. {20:X¥¥} PEPPERS |
  2063. {20:X¥¥} |
  2064. a{20:X¥¥}¥KOL |
  2065. £ ¥ libm |
  2066. £ ¥ |
  2067. |
  2068. {1:~ }|*8
  2069. :%s/£.*ѫ/X¥¥^ |
  2070. ]])
  2071. feed('\\ra££ ¥')
  2072. screen:expect([[
  2073. {20:X¥¥} |
  2074. {20:a££ ¥} PEPPERS |
  2075. {20:X¥¥} |
  2076. {20:a££ ¥} |
  2077. a{20:X¥¥} |
  2078. {20:a££ ¥}¥KOL |
  2079. £ ¥ libm |
  2080. £ ¥ |
  2081. |
  2082. {1:~ }|*5
  2083. :%s/£.*ѫ/X¥¥\ra££ ¥^ |
  2084. ]])
  2085. end)
  2086. it('inccommand=split, small cmdwinheight', function()
  2087. common_setup(screen, 'split', long_multiline_text)
  2088. command('set cmdwinheight=2')
  2089. feed(':%s/[a-z]')
  2090. screen:expect([[
  2091. X Y Z |
  2092. 7 8 9 |
  2093. K L M |
  2094. {20:a} b c |
  2095. {20:d} e f |
  2096. {20:q} r s |
  2097. {20:x} y z |
  2098. £ {20:m} n |
  2099. {20:t} œ ¥ |
  2100. |
  2101. {3:[No Name] [+] }|
  2102. | 7| {20:a} b c |
  2103. | 8| {20:d} e f |
  2104. {2:[Preview] }|
  2105. :%s/[a-z]^ |
  2106. ]])
  2107. feed('/JLKR £')
  2108. screen:expect([[
  2109. X Y Z |
  2110. 7 8 9 |
  2111. K L M |
  2112. {20:JLKR £} b c |
  2113. {20:JLKR £} e f |
  2114. {20:JLKR £} r s |
  2115. {20:JLKR £} y z |
  2116. £ {20:JLKR £} n |
  2117. {20:JLKR £} œ ¥ |
  2118. |
  2119. {3:[No Name] [+] }|
  2120. | 7| {20:JLKR £} b c |
  2121. | 8| {20:JLKR £} e f |
  2122. {2:[Preview] }|
  2123. :%s/[a-z]/JLKR £^ |
  2124. ]])
  2125. feed('\\rѫ ab \\rXXXX')
  2126. screen:expect([[
  2127. 7 8 9 |
  2128. K L M |
  2129. {20:JLKR £} |
  2130. {20:ѫ ab } |
  2131. {20:XXXX} b c |
  2132. {20:JLKR £} |
  2133. {20:ѫ ab } |
  2134. {20:XXXX} e f |
  2135. {20:JLKR £} |
  2136. {20:ѫ ab } |
  2137. {3:[No Name] [+] }|
  2138. | 7| {20:JLKR £} |
  2139. {3: }|
  2140. :%s/[a-z]/JLKR £\rѫ ab \rXXX|
  2141. X^ |
  2142. ]])
  2143. end)
  2144. it('inccommand=split, large cmdwinheight', function()
  2145. common_setup(screen, 'split', long_multiline_text)
  2146. command('set cmdwinheight=11')
  2147. feed(':%s/. .$')
  2148. screen:expect([[
  2149. t {20:œ ¥} |
  2150. {3:[No Name] [+] }|
  2151. | 1| 1 {20:2 3} |
  2152. | 2| A {20:B C} |
  2153. | 3| 4 {20:5 6} |
  2154. | 4| X {20:Y Z} |
  2155. | 5| 7 {20:8 9} |
  2156. | 6| K {20:L M} |
  2157. | 7| a {20:b c} |
  2158. | 8| d {20:e f} |
  2159. | 9| q {20:r s} |
  2160. |10| x {20:y z} |
  2161. |11| £ {20:m n} |
  2162. {2:[Preview] }|
  2163. :%s/. .$^ |
  2164. ]])
  2165. feed('/ YYY')
  2166. screen:expect([[
  2167. t {20: YYY} |
  2168. {3:[No Name] [+] }|
  2169. | 1| 1 {20: YYY} |
  2170. | 2| A {20: YYY} |
  2171. | 3| 4 {20: YYY} |
  2172. | 4| X {20: YYY} |
  2173. | 5| 7 {20: YYY} |
  2174. | 6| K {20: YYY} |
  2175. | 7| a {20: YYY} |
  2176. | 8| d {20: YYY} |
  2177. | 9| q {20: YYY} |
  2178. |10| x {20: YYY} |
  2179. |11| £ {20: YYY} |
  2180. {2:[Preview] }|
  2181. :%s/. .$/ YYY^ |
  2182. ]])
  2183. feed('\\r KKK')
  2184. screen:expect([[
  2185. a {20: YYY} |
  2186. {3:[No Name] [+] }|
  2187. | 1| 1 {20: YYY} |
  2188. | 2|{20: KKK} |
  2189. | 3| A {20: YYY} |
  2190. | 4|{20: KKK} |
  2191. | 5| 4 {20: YYY} |
  2192. | 6|{20: KKK} |
  2193. | 7| X {20: YYY} |
  2194. | 8|{20: KKK} |
  2195. | 9| 7 {20: YYY} |
  2196. |10|{20: KKK} |
  2197. |11| K {20: YYY} |
  2198. {2:[Preview] }|
  2199. :%s/. .$/ YYY\r KKK^ |
  2200. ]])
  2201. end)
  2202. it('inccommand=split, lookaround', function()
  2203. common_setup(screen, 'split', 'something\neverything\nsomeone')
  2204. feed([[:%s/\(some\)\@<lt>=thing/one/]])
  2205. screen:expect([[
  2206. some{20:one} |
  2207. everything |
  2208. someone |
  2209. {1:~ }|*2
  2210. {3:[No Name] [+] }|
  2211. |1| some{20:one} |
  2212. {1:~ }|*6
  2213. {2:[Preview] }|
  2214. :%s/\(some\)\@<=thing/one/^ |
  2215. ]])
  2216. feed('<C-c>')
  2217. feed('gg')
  2218. poke_eventloop()
  2219. feed([[:%s/\(some\)\@<lt>!thing/one/]])
  2220. screen:expect([[
  2221. something |
  2222. every{20:one} |
  2223. someone |
  2224. {1:~ }|*2
  2225. {3:[No Name] [+] }|
  2226. |2| every{20:one} |
  2227. {1:~ }|*6
  2228. {2:[Preview] }|
  2229. :%s/\(some\)\@<!thing/one/^ |
  2230. ]])
  2231. feed([[<C-c>]])
  2232. poke_eventloop()
  2233. feed([[:%s/some\(thing\)\@=/every/]])
  2234. screen:expect([[
  2235. {20:every}thing |
  2236. everything |
  2237. someone |
  2238. {1:~ }|*2
  2239. {3:[No Name] [+] }|
  2240. |1| {20:every}thing |
  2241. {1:~ }|*6
  2242. {2:[Preview] }|
  2243. :%s/some\(thing\)\@=/every/^ |
  2244. ]])
  2245. feed([[<C-c>]])
  2246. poke_eventloop()
  2247. feed([[:%s/some\(thing\)\@!/every/]])
  2248. screen:expect([[
  2249. something |
  2250. everything |
  2251. {20:every}one |
  2252. {1:~ }|*2
  2253. {3:[No Name] [+] }|
  2254. |3| {20:every}one |
  2255. {1:~ }|*6
  2256. {2:[Preview] }|
  2257. :%s/some\(thing\)\@!/every/^ |
  2258. ]])
  2259. end)
  2260. it("doesn't prompt to swap cmd range", function()
  2261. screen:try_resize(50, 8) -- wide to avoid hit-enter prompt
  2262. common_setup(screen, 'split', default_text)
  2263. feed(':2,1s/tw/MO/g')
  2264. -- substitution preview should have been made, without prompting
  2265. screen:expect([[
  2266. {20:MO}o lines |
  2267. {3:[No Name] [+] }|
  2268. |2| {20:MO}o lines |
  2269. {1:~ }|*3
  2270. {2:[Preview] }|
  2271. :2,1s/tw/MO/g^ |
  2272. ]])
  2273. -- but should be prompted on hitting enter
  2274. feed('<CR>')
  2275. screen:expect([[
  2276. {20:MO}o lines |
  2277. {3:[No Name] [+] }|
  2278. |2| {20:MO}o lines |
  2279. {1:~ }|*3
  2280. {2:[Preview] }|
  2281. {6:Backwards range given, OK to swap (y/n)?}^ |
  2282. ]])
  2283. feed('y')
  2284. screen:expect([[
  2285. Inc substitution on |
  2286. ^MOo lines |
  2287. |
  2288. {1:~ }|*4
  2289. {6:Backwards range given, OK to swap (y/n)?}y |
  2290. ]])
  2291. end)
  2292. end)
  2293. it(':substitute with inccommand during :terminal activity', function()
  2294. if t.skip_fragile(pending) then
  2295. return
  2296. end
  2297. retry(2, 40000, function()
  2298. clear()
  2299. local screen = Screen.new(30, 15)
  2300. command('set cmdwinheight=3')
  2301. feed(([[:terminal "%s" REP 5000 xxx<cr>]]):format(testprg('shell-test')))
  2302. command('file term')
  2303. feed('G') -- Follow :terminal output.
  2304. command('new')
  2305. common_setup(screen, 'split', 'foo bar baz\nbar baz fox\nbar foo baz')
  2306. command('wincmd =')
  2307. feed('gg')
  2308. feed(':%s/foo/ZZZ')
  2309. sleep(20) -- Allow some terminal activity.
  2310. poke_eventloop()
  2311. screen:sleep(0)
  2312. screen:expect_unchanged()
  2313. end)
  2314. end)
  2315. it(':substitute with inccommand, timer-induced :redraw #9777', function()
  2316. clear()
  2317. local screen = Screen.new(30, 12)
  2318. command('set cmdwinheight=3')
  2319. command('call timer_start(10, {-> execute("redraw")}, {"repeat":-1})')
  2320. command('call timer_start(10, {-> execute("redrawstatus")}, {"repeat":-1})')
  2321. common_setup(screen, 'split', 'foo bar baz\nbar baz fox\nbar foo baz')
  2322. feed('gg')
  2323. feed(':%s/foo/ZZZ')
  2324. sleep(20) -- Allow some timer activity.
  2325. screen:expect([[
  2326. {20:ZZZ} bar baz |
  2327. bar baz fox |
  2328. bar {20:ZZZ} baz |
  2329. {1:~ }|*3
  2330. {3:[No Name] [+] }|
  2331. |1| {20:ZZZ} bar baz |
  2332. |3| bar {20:ZZZ} baz |
  2333. {1:~ }|
  2334. {2:[Preview] }|
  2335. :%s/foo/ZZZ^ |
  2336. ]])
  2337. -- Also with nvim__redraw()
  2338. command('call timer_start(10, {-> nvim__redraw(#{flush:1})}, {"repeat":-1})')
  2339. command('call timer_start(10, {-> nvim__redraw(#{statusline:1})}, {"repeat":-1})')
  2340. sleep(20) -- Allow some timer activity.
  2341. screen:expect_unchanged()
  2342. end)
  2343. it(':substitute with inccommand, allows :redraw before first separator is typed #18857', function()
  2344. clear()
  2345. local screen = Screen.new(30, 6)
  2346. common_setup(screen, 'split', 'foo bar baz\nbar baz fox\nbar foo baz')
  2347. command('hi! link NormalFloat CursorLine')
  2348. local float_buf = api.nvim_create_buf(false, true)
  2349. api.nvim_open_win(float_buf, false, {
  2350. relative = 'editor',
  2351. height = 1,
  2352. width = 5,
  2353. row = 3,
  2354. col = 0,
  2355. focusable = false,
  2356. })
  2357. feed(':')
  2358. screen:expect([[
  2359. foo bar baz |
  2360. bar baz fox |
  2361. bar foo baz |
  2362. {21: }{1: }|
  2363. {1:~ }|
  2364. :^ |
  2365. ]])
  2366. feed('%s')
  2367. screen:expect([[
  2368. foo bar baz |
  2369. bar baz fox |
  2370. bar foo baz |
  2371. {21: }{1: }|
  2372. {1:~ }|
  2373. :%s^ |
  2374. ]])
  2375. api.nvim_buf_set_lines(float_buf, 0, -1, true, { 'foo' })
  2376. command('redraw')
  2377. screen:expect([[
  2378. foo bar baz |
  2379. bar baz fox |
  2380. bar foo baz |
  2381. {21:foo }{1: }|
  2382. {1:~ }|
  2383. :%s^ |
  2384. ]])
  2385. end)
  2386. it(':substitute with inccommand, does not crash if range contains invalid marks', function()
  2387. clear()
  2388. local screen = Screen.new(30, 6)
  2389. common_setup(screen, 'split', 'test')
  2390. feed([[:'a,'bs]])
  2391. screen:expect([[
  2392. test |
  2393. {1:~ }|*4
  2394. :'a,'bs^ |
  2395. ]])
  2396. -- v:errmsg shouldn't be set either before the first separator is typed
  2397. eq('', eval('v:errmsg'))
  2398. feed('/')
  2399. screen:expect([[
  2400. test |
  2401. {1:~ }|*4
  2402. :'a,'bs/^ |
  2403. ]])
  2404. end)
  2405. it(':substitute with inccommand, no unnecessary redraw if preview is not shown', function()
  2406. clear()
  2407. local screen = Screen.new(60, 6)
  2408. common_setup(screen, 'split', 'test')
  2409. feed(':ls<CR>')
  2410. screen:expect([[
  2411. test |
  2412. {1:~ }|
  2413. {3: }|
  2414. :ls |
  2415. 1 %a + "[No Name]" line 1 |
  2416. {6:Press ENTER or type command to continue}^ |
  2417. ]])
  2418. feed(':s')
  2419. -- no unnecessary redraw, so messages are still shown
  2420. screen:expect([[
  2421. test |
  2422. {1:~ }|
  2423. {3: }|
  2424. :ls |
  2425. 1 %a + "[No Name]" line 1 |
  2426. :s^ |
  2427. ]])
  2428. feed('o')
  2429. screen:expect([[
  2430. test |
  2431. {1:~ }|
  2432. {3: }|
  2433. :ls |
  2434. 1 %a + "[No Name]" line 1 |
  2435. :so^ |
  2436. ]])
  2437. feed('<BS>')
  2438. screen:expect([[
  2439. test |
  2440. {1:~ }|
  2441. {3: }|
  2442. :ls |
  2443. 1 %a + "[No Name]" line 1 |
  2444. :s^ |
  2445. ]])
  2446. feed('/test')
  2447. -- now inccommand is shown, so screen is redrawn
  2448. screen:expect([[
  2449. {20:test} |
  2450. {1:~ }|*4
  2451. :s/test^ |
  2452. ]])
  2453. end)
  2454. it(":substitute doesn't crash with inccommand, if undo is empty #12932", function()
  2455. clear()
  2456. local screen = Screen.new(10, 5)
  2457. command('set undolevels=-1')
  2458. common_setup(screen, 'split', 'test')
  2459. feed(':%s/test')
  2460. sleep(100)
  2461. feed('/')
  2462. sleep(100)
  2463. feed('f')
  2464. screen:expect([[
  2465. {20:f} |
  2466. {1:~ }|*3
  2467. :%s/test/f^ |
  2468. ]])
  2469. assert_alive()
  2470. end)
  2471. it(':substitute with inccommand works properly if undo is not synced #20029', function()
  2472. clear()
  2473. local screen = Screen.new(30, 6)
  2474. common_setup(screen, 'nosplit', 'foo\nbar\nbaz')
  2475. api.nvim_set_keymap('x', '<F2>', '<Esc>`<Oaaaaa asdf<Esc>`>obbbbb asdf<Esc>V`<k:s/asdf/', {})
  2476. feed('gg0<C-V>lljj<F2>')
  2477. screen:expect([[
  2478. aaaaa |
  2479. foo |
  2480. bar |
  2481. baz |
  2482. bbbbb |
  2483. :'<,'>s/asdf/^ |
  2484. ]])
  2485. feed('hjkl')
  2486. screen:expect([[
  2487. aaaaa {20:hjkl} |
  2488. foo |
  2489. bar |
  2490. baz |
  2491. bbbbb {20:hjkl} |
  2492. :'<,'>s/asdf/hjkl^ |
  2493. ]])
  2494. feed('<CR>')
  2495. expect([[
  2496. aaaaa hjkl
  2497. foo
  2498. bar
  2499. baz
  2500. bbbbb hjkl]])
  2501. feed('u')
  2502. expect([[
  2503. foo
  2504. bar
  2505. baz]])
  2506. end)
  2507. it(':substitute with inccommand does not unexpectedly change viewport #25697', function()
  2508. clear()
  2509. local screen = Screen.new(45, 5)
  2510. common_setup(screen, 'nosplit', long_multiline_text)
  2511. command('vnew | tabnew | tabclose')
  2512. screen:expect([[
  2513. ^ │£ m n |
  2514. {1:~ }│t œ ¥ |
  2515. {1:~ }│ |
  2516. {3:[No Name] }{2:[No Name] [+] }|
  2517. |
  2518. ]])
  2519. feed(':s/')
  2520. screen:expect([[
  2521. │£ m n |
  2522. {1:~ }│t œ ¥ |
  2523. {1:~ }│ |
  2524. {3:[No Name] }{2:[No Name] [+] }|
  2525. :s/^ |
  2526. ]])
  2527. feed('<Esc>')
  2528. screen:expect([[
  2529. ^ │£ m n |
  2530. {1:~ }│t œ ¥ |
  2531. {1:~ }│ |
  2532. {3:[No Name] }{2:[No Name] [+] }|
  2533. |
  2534. ]])
  2535. end)
  2536. it('long :%s/ with inccommand does not collapse cmdline', function()
  2537. clear()
  2538. local screen = Screen.new(10, 5)
  2539. common_setup(screen, 'nosplit')
  2540. feed(
  2541. ':%s/AAAAAAA',
  2542. 'A',
  2543. 'A',
  2544. 'A',
  2545. 'A',
  2546. 'A',
  2547. 'A',
  2548. 'A',
  2549. 'A',
  2550. 'A',
  2551. 'A',
  2552. 'A',
  2553. 'A',
  2554. 'A',
  2555. 'A',
  2556. 'A',
  2557. 'A',
  2558. 'A',
  2559. 'A',
  2560. 'A',
  2561. 'A'
  2562. )
  2563. screen:expect([[
  2564. |
  2565. {3: }|
  2566. :%s/AAAAAAAA|
  2567. AAAAAAAAAAAA|
  2568. AAAAAAA^ |
  2569. ]])
  2570. end)
  2571. it("with 'inccommand' typing invalid `={expr}` does not show error", function()
  2572. clear()
  2573. local screen = Screen.new(30, 6)
  2574. common_setup(screen, 'nosplit')
  2575. feed(':edit `=`')
  2576. screen:expect([[
  2577. |
  2578. {1:~ }|*4
  2579. :edit `=`^ |
  2580. ]])
  2581. end)
  2582. it("with 'inccommand' typing :filter doesn't segfault or leak memory #19057", function()
  2583. clear()
  2584. common_setup(nil, 'nosplit')
  2585. feed(':filter s')
  2586. assert_alive()
  2587. feed(' ')
  2588. assert_alive()
  2589. feed('h')
  2590. assert_alive()
  2591. feed('i')
  2592. assert_alive()
  2593. end)
  2594. it("'inccommand' cannot be changed during preview #23136", function()
  2595. clear()
  2596. local screen = Screen.new(30, 6)
  2597. common_setup(screen, 'nosplit', 'foo\nbar\nbaz')
  2598. source([[
  2599. function! IncCommandToggle()
  2600. let prev = &inccommand
  2601. if &inccommand ==# 'split'
  2602. set inccommand=nosplit
  2603. elseif &inccommand ==# 'nosplit'
  2604. set inccommand=split
  2605. elseif &inccommand ==# ''
  2606. set inccommand=nosplit
  2607. else
  2608. throw 'unknown inccommand'
  2609. endif
  2610. return " \<BS>"
  2611. endfun
  2612. cnoremap <expr> <C-E> IncCommandToggle()
  2613. ]])
  2614. feed(':%s/foo/bar<C-E><C-E><C-E>')
  2615. assert_alive()
  2616. end)
  2617. it("'inccommand' value can be changed multiple times #27086", function()
  2618. clear()
  2619. local screen = Screen.new(30, 20)
  2620. common_setup(screen, 'split', 'foo1\nfoo2\nfoo3')
  2621. for _ = 1, 3 do
  2622. feed(':%s/foo/bar')
  2623. screen:expect([[
  2624. {20:bar}1 |
  2625. {20:bar}2 |
  2626. {20:bar}3 |
  2627. {1:~ }|*7
  2628. {3:[No Name] [+] }|
  2629. |1| {20:bar}1 |
  2630. |2| {20:bar}2 |
  2631. |3| {20:bar}3 |
  2632. {1:~ }|*4
  2633. {2:[Preview] }|
  2634. :%s/foo/bar^ |
  2635. ]])
  2636. feed('<Esc>')
  2637. command('set inccommand=nosplit')
  2638. feed(':%s/foo/bar')
  2639. screen:expect([[
  2640. {20:bar}1 |
  2641. {20:bar}2 |
  2642. {20:bar}3 |
  2643. {1:~ }|*16
  2644. :%s/foo/bar^ |
  2645. ]])
  2646. feed('<Esc>')
  2647. command('set inccommand=split')
  2648. end
  2649. end)
  2650. it("'inccommand' disables preview if preview buffer can't be created #27086", function()
  2651. clear()
  2652. api.nvim_buf_set_name(0, '[Preview]')
  2653. local screen = Screen.new(30, 20)
  2654. common_setup(screen, 'split', 'foo1\nfoo2\nfoo3')
  2655. eq('split', api.nvim_get_option_value('inccommand', {}))
  2656. feed(':%s/foo/bar')
  2657. screen:expect([[
  2658. {20:bar}1 |
  2659. {20:bar}2 |
  2660. {20:bar}3 |
  2661. {1:~ }|*16
  2662. :%s/foo/bar^ |
  2663. ]])
  2664. eq('nosplit', api.nvim_get_option_value('inccommand', {}))
  2665. end)