blob: d03ec8f2d81dbeea606bcf16307ca90d30f0f3f7 [file] [log] [blame]
Bram Moolenaar59cb0412019-12-18 22:26:31 +01001" Test editing line in Ex mode (see :help Q and :help gQ).
2
Bram Moolenaare20b9ec2020-02-03 21:40:04 +01003source check.vim
Bram Moolenaar3b6d57f2020-11-01 21:56:40 +01004source shared.vim
Bram Moolenaare20b9ec2020-02-03 21:40:04 +01005
Bram Moolenaar59cb0412019-12-18 22:26:31 +01006" Helper function to test editing line in Q Ex mode
7func Ex_Q(cmd)
8 " Is there a simpler way to test editing Ex line?
9 call feedkeys("Q"
10 \ .. "let s:test_ex =<< END\<CR>"
11 \ .. a:cmd .. "\<CR>"
12 \ .. "END\<CR>"
13 \ .. "visual\<CR>", 'tx')
14 return s:test_ex[0]
15endfunc
16
17" Helper function to test editing line in gQ Ex mode
18func Ex_gQ(cmd)
19 call feedkeys("gQ" .. a:cmd .. "\<C-b>\"\<CR>", 'tx')
20 let ret = @:[1:] " Remove leading quote.
21 call feedkeys("visual\<CR>", 'tx')
22 return ret
23endfunc
24
25" Helper function to test editing line with both Q and gQ Ex mode.
26func Ex(cmd)
27 return [Ex_Q(a:cmd), Ex_gQ(a:cmd)]
28endfunc
29
30" Test editing line in Ex mode (both Q and gQ)
31func Test_ex_mode()
32 let encoding_save = &encoding
33 set sw=2
34
35 for e in ['utf8', 'latin1']
36 exe 'set encoding=' . e
37
38 call assert_equal(['bar', 'bar'], Ex("foo bar\<C-u>bar"), e)
39 call assert_equal(["1\<C-u>2", "1\<C-u>2"], Ex("1\<C-v>\<C-u>2"), e)
40 call assert_equal(["1\<C-b>2\<C-e>3", '213'], Ex("1\<C-b>2\<C-e>3"), e)
41 call assert_equal(['0123', '2013'], Ex("01\<Home>2\<End>3"), e)
42 call assert_equal(['0123', '0213'], Ex("01\<Left>2\<Right>3"), e)
43 call assert_equal(['01234', '0342'], Ex("012\<Left>\<Left>\<Insert>3\<Insert>4"), e)
44 call assert_equal(["foo bar\<C-w>", 'foo '], Ex("foo bar\<C-w>"), e)
45 call assert_equal(['foo', 'foo'], Ex("fooba\<Del>\<Del>"), e)
46 call assert_equal(["foo\tbar", 'foobar'], Ex("foo\<Tab>bar"), e)
47 call assert_equal(["abbrev\t", 'abbreviate'], Ex("abbrev\<Tab>"), e)
48 call assert_equal([' 1', "1\<C-t>\<C-t>"], Ex("1\<C-t>\<C-t>"), e)
49 call assert_equal([' 1', "1\<C-t>\<C-t>"], Ex("1\<C-t>\<C-t>\<C-d>"), e)
50 call assert_equal([' foo', ' foo'], Ex(" foo\<C-d>"), e)
51 call assert_equal(['foo', ' foo0'], Ex(" foo0\<C-d>"), e)
52 call assert_equal(['foo', ' foo^'], Ex(" foo^\<C-d>"), e)
Bram Moolenaar0546d7d2020-03-01 16:53:09 +010053 call assert_equal(['foo', 'foo'],
Bram Moolenaar91ffc8a2020-03-02 20:54:22 +010054 \ Ex("\<BS>\<C-H>\<Del>\<kDel>foo"), e)
55 " default wildchar <Tab> interferes with this test
56 set wildchar=<c-e>
57 call assert_equal(["a\tb", "a\tb"], Ex("a\t\t\<C-H>b"), e)
Bram Moolenaarbd7206e2020-03-06 20:36:04 +010058 call assert_equal(["\t mn", "\tm\<C-T>n"], Ex("\tm\<C-T>n"), e)
Bram Moolenaar91ffc8a2020-03-02 20:54:22 +010059 set wildchar&
Bram Moolenaar59cb0412019-12-18 22:26:31 +010060 endfor
61
62 set sw&
63 let &encoding = encoding_save
64endfunc
Bram Moolenaare20b9ec2020-02-03 21:40:04 +010065
Bram Moolenaarbc2b71d2020-02-17 21:33:30 +010066" Test substitute confirmation prompt :%s/pat/str/c in Ex mode
Bram Moolenaare20b9ec2020-02-03 21:40:04 +010067func Test_Ex_substitute()
68 CheckRunVimInTerminal
69 let buf = RunVimInTerminal('', {'rows': 6})
70
71 call term_sendkeys(buf, ":call setline(1, ['foo foo', 'foo foo', 'foo foo'])\<CR>")
72 call term_sendkeys(buf, ":set number\<CR>")
73 call term_sendkeys(buf, "gQ")
74 call WaitForAssert({-> assert_match(':', term_getline(buf, 6))}, 1000)
75
76 call term_sendkeys(buf, "%s/foo/bar/gc\<CR>")
77 call WaitForAssert({-> assert_match(' 1 foo foo', term_getline(buf, 5))},
78 \ 1000)
79 call WaitForAssert({-> assert_match(' ^^^', term_getline(buf, 6))}, 1000)
Bram Moolenaare5b0b982021-04-07 19:42:57 +020080 call term_sendkeys(buf, "N\<CR>")
81 call term_wait(buf)
82 call WaitForAssert({-> assert_match(' ^^^', term_getline(buf, 6))}, 1000)
Bram Moolenaare20b9ec2020-02-03 21:40:04 +010083 call term_sendkeys(buf, "n\<CR>")
84 call WaitForAssert({-> assert_match(' ^^^', term_getline(buf, 6))},
85 \ 1000)
86 call term_sendkeys(buf, "y\<CR>")
87
88 call term_sendkeys(buf, "q\<CR>")
89 call WaitForAssert({-> assert_match(':', term_getline(buf, 6))}, 1000)
90
Bram Moolenaarbc2b71d2020-02-17 21:33:30 +010091 " Pressing enter in ex mode should print the current line
92 call term_sendkeys(buf, "\<CR>")
93 call WaitForAssert({-> assert_match(' 3 foo foo',
94 \ term_getline(buf, 5))}, 1000)
95
Bram Moolenaare20b9ec2020-02-03 21:40:04 +010096 call term_sendkeys(buf, ":vi\<CR>")
97 call WaitForAssert({-> assert_match('foo bar', term_getline(buf, 1))}, 1000)
98
Bram Moolenaare20b9ec2020-02-03 21:40:04 +010099 call StopVimInTerminal(buf)
100endfunc
101
Bram Moolenaar9f6277b2020-02-11 22:04:02 +0100102" Test for displaying lines from an empty buffer in Ex mode
103func Test_Ex_emptybuf()
104 new
105 call assert_fails('call feedkeys("Q\<CR>", "xt")', 'E749:')
106 call setline(1, "abc")
107 call assert_fails('call feedkeys("Q\<CR>", "xt")', 'E501:')
108 call assert_fails('call feedkeys("Q%d\<CR>", "xt")', 'E749:')
109 close!
110endfunc
111
112" Test for the :open command
113func Test_open_command()
114 new
115 call setline(1, ['foo foo', 'foo bar', 'foo baz'])
116 call feedkeys("Qopen\<CR>j", 'xt')
117 call assert_equal('foo bar', getline('.'))
118 call feedkeys("Qopen /bar/\<CR>", 'xt')
119 call assert_equal(5, col('.'))
120 call assert_fails('call feedkeys("Qopen /baz/\<CR>", "xt")', 'E479:')
121 close!
122endfunc
123
Bram Moolenaare031fe92021-12-05 12:06:24 +0000124func Test_open_command_flush_line()
125 " this was accessing freed memory: the regexp match uses a pointer to the
126 " current line which becomes invalid when searching for the ') mark.
127 new
128 call setline(1, ['one', 'two. three'])
129 s/one/ONE
130 try
131 open /\%')/
132 catch /E479/
133 endtry
134 bwipe!
135endfunc
136
Bram Moolenaar7ac50232023-03-07 21:05:04 +0000137" FIXME: this doesn't fail without the fix but hangs
138func Skip_Test_open_command_state()
139 " Tricky script that failed because State was not set properly
140 let lines =<< trim END
141 !ls ƒ
142 0scìi
143 so! Xsourced
144 set t_û0=0
145 v/-/o
146 END
147 call writefile(lines, 'XopenScript', '')
148
149 let sourced = ["!f\u0083\x02\<Esc>z=0"]
150 call writefile(sourced, 'Xsourced', 'b')
151
152 CheckRunVimInTerminal
153 let buf = RunVimInTerminal('-u NONE -i NONE -n -m -X -Z -e -s -S XopenScript -c qa!', #{rows: 6, wait_for_ruler: 0, no_clean: 1})
154 sleep 3
155
156 call StopVimInTerminal(buf)
157endfunc
158
Bram Moolenaar818fc9a2020-02-21 17:54:45 +0100159" Test for :g/pat/visual to run vi commands in Ex mode
160" This used to hang Vim before 8.2.0274.
161func Test_Ex_global()
Bram Moolenaar9e2bcb52020-02-18 21:33:00 +0100162 new
Bram Moolenaar818fc9a2020-02-21 17:54:45 +0100163 call setline(1, ['', 'foo', 'bar', 'foo', 'bar', 'foo'])
Bram Moolenaar578fe942020-02-27 21:32:51 +0100164 call feedkeys("Q\<bs>g/bar/visual\<CR>$rxQ$ryQvisual\<CR>j", "xt")
Bram Moolenaar818fc9a2020-02-21 17:54:45 +0100165 call assert_equal('bax', getline(3))
166 call assert_equal('bay', getline(5))
Bram Moolenaar9e2bcb52020-02-18 21:33:00 +0100167 bwipe!
168endfunc
169
zeertzjqf754fe62022-07-14 17:06:12 +0100170" Test for pressing Ctrl-C in :append inside a loop in Ex mode
171" This used to hang Vim
172func Test_Ex_append_in_loop()
173 CheckRunVimInTerminal
174 let buf = RunVimInTerminal('', {'rows': 6})
175
176 call term_sendkeys(buf, "gQ")
177 call term_sendkeys(buf, "for i in range(1)\<CR>")
178 call term_sendkeys(buf, "append\<CR>")
179 call WaitForAssert({-> assert_match(': append', term_getline(buf, 5))}, 1000)
180 call term_sendkeys(buf, "\<C-C>")
zeertzjq3cfae392022-07-26 17:48:13 +0100181 " Wait for input to be flushed
zeertzjqf754fe62022-07-14 17:06:12 +0100182 call term_wait(buf)
183 call term_sendkeys(buf, "foo\<CR>")
184 call WaitForAssert({-> assert_match('foo', term_getline(buf, 5))}, 1000)
185 call term_sendkeys(buf, ".\<CR>")
186 call WaitForAssert({-> assert_match('.', term_getline(buf, 5))}, 1000)
187 call term_sendkeys(buf, "endfor\<CR>")
188 call term_sendkeys(buf, "vi\<CR>")
189 call WaitForAssert({-> assert_match('foo', term_getline(buf, 1))}, 1000)
190
191 call StopVimInTerminal(buf)
192endfunc
193
Bram Moolenaar578fe942020-02-27 21:32:51 +0100194" In Ex-mode, a backslash escapes a newline
195func Test_Ex_escape_enter()
196 call feedkeys("gQlet l = \"a\\\<kEnter>b\"\<cr>vi\<cr>", 'xt')
197 call assert_equal("a\rb", l)
198endfunc
199
Bram Moolenaar0546d7d2020-03-01 16:53:09 +0100200" Test for :append! command in Ex mode
201func Test_Ex_append()
202 new
203 call setline(1, "\t abc")
204 call feedkeys("Qappend!\npqr\nxyz\n.\nvisual\n", 'xt')
205 call assert_equal(["\t abc", "\t pqr", "\t xyz"], getline(1, '$'))
206 close!
207endfunc
208
Bram Moolenaar91ffc8a2020-03-02 20:54:22 +0100209" In Ex-mode, backslashes at the end of a command should be halved.
210func Test_Ex_echo_backslash()
211 " This test works only when the language is English
Bram Moolenaarcde0ff32020-04-04 14:00:39 +0200212 CheckEnglish
Bram Moolenaar91ffc8a2020-03-02 20:54:22 +0100213 let bsl = '\\\\'
214 let bsl2 = '\\\'
215 call assert_fails('call feedkeys("Qecho " .. bsl .. "\nvisual\n", "xt")',
Bram Moolenaar6b02b382021-05-16 16:19:37 +0200216 \ 'E15: Invalid expression: "\\"')
Bram Moolenaar91ffc8a2020-03-02 20:54:22 +0100217 call assert_fails('call feedkeys("Qecho " .. bsl2 .. "\nm\nvisual\n", "xt")',
Bram Moolenaar6b02b382021-05-16 16:19:37 +0200218 \ "E15: Invalid expression: \"\\\nm\"")
Bram Moolenaar91ffc8a2020-03-02 20:54:22 +0100219endfunc
220
Bram Moolenaar1671f442020-03-10 07:48:13 +0100221func Test_ex_mode_errors()
222 " Not allowed to enter ex mode when text is locked
223 au InsertCharPre <buffer> normal! gQ<CR>
Bram Moolenaarff06f282020-04-21 22:01:14 +0200224 let caught_e565 = 0
Bram Moolenaar1671f442020-03-10 07:48:13 +0100225 try
226 call feedkeys("ix\<esc>", 'xt')
Bram Moolenaarff06f282020-04-21 22:01:14 +0200227 catch /^Vim\%((\a\+)\)\=:E565/ " catch E565
228 let caught_e565 = 1
Bram Moolenaar1671f442020-03-10 07:48:13 +0100229 endtry
Bram Moolenaarff06f282020-04-21 22:01:14 +0200230 call assert_equal(1, caught_e565)
Bram Moolenaar1671f442020-03-10 07:48:13 +0100231 au! InsertCharPre
Bram Moolenaar158ea172020-06-18 17:28:39 +0200232
233 new
234 au CmdLineEnter * call ExEnterFunc()
235 func ExEnterFunc()
236
237 endfunc
238 call feedkeys("gQvi\r", 'xt')
239
240 au! CmdLineEnter
241 delfunc ExEnterFunc
242 quit
Bram Moolenaar1671f442020-03-10 07:48:13 +0100243endfunc
244
Bram Moolenaar3b6d57f2020-11-01 21:56:40 +0100245func Test_ex_mode_with_global()
Bram Moolenaar399db042020-11-01 22:31:08 +0100246 CheckNotGui
Bram Moolenaar3b6d57f2020-11-01 21:56:40 +0100247 CheckFeature timers
248
249 " This will get stuck in Normal mode after the failed "J", use a timer to
250 " get going again.
251 let lines =<< trim END
252 call ch_logfile('logfile', 'w')
253 pedit
254 func FeedQ(id)
255 call feedkeys('Q', 't')
256 endfunc
257 call timer_start(10, 'FeedQ')
258 g/^/vi|HJ
259 call writefile(['done'], 'Xdidexmode')
260 qall!
261 END
Bram Moolenaar5c645a22022-09-21 22:00:03 +0100262 call writefile(lines, 'Xexmodescript', 'D')
Bram Moolenaar3b6d57f2020-11-01 21:56:40 +0100263 call assert_equal(1, RunVim([], [], '-e -s -S Xexmodescript'))
264 call assert_equal(['done'], readfile('Xdidexmode'))
265
Bram Moolenaarf637bce2020-11-23 18:14:56 +0100266 call delete('logfile')
Bram Moolenaar3b6d57f2020-11-01 21:56:40 +0100267 call delete('Xdidexmode')
Bram Moolenaar3b6d57f2020-11-01 21:56:40 +0100268endfunc
269
Bram Moolenaar1d859e22021-01-28 17:24:58 +0100270func Test_ex_mode_count_overflow()
Bram Moolenaar97202d92021-01-28 18:34:35 +0100271 " The multiplication causes an integer overflow
272 CheckNotAsan
273
Bram Moolenaar1d859e22021-01-28 17:24:58 +0100274 " this used to cause a crash
275 let lines =<< trim END
276 call feedkeys("\<Esc>Q\<CR>")
277 v9|9silent! vi|333333233333y32333333%O
278 call writefile(['done'], 'Xdidexmode')
279 qall!
280 END
Bram Moolenaar5c645a22022-09-21 22:00:03 +0100281 call writefile(lines, 'Xexmodescript', 'D')
Bram Moolenaar1d859e22021-01-28 17:24:58 +0100282 call assert_equal(1, RunVim([], [], '-e -s -S Xexmodescript -c qa'))
283 call assert_equal(['done'], readfile('Xdidexmode'))
284
285 call delete('Xdidexmode')
Bram Moolenaar1d859e22021-01-28 17:24:58 +0100286endfunc
287
Bram Moolenaar85b67472022-01-25 11:55:02 +0000288func Test_ex_mode_large_indent()
289 new
290 set ts=500 ai
291 call setline(1, "\t")
292 exe "normal gQi\<CR>."
293 set ts=8 noai
294 bwipe!
295endfunc
296
Bram Moolenaarf50808e2022-04-16 18:52:17 +0100297" This was accessing illegal memory when using "+" for eap->cmd.
298func Test_empty_command_visual_mode()
299 let lines =<< trim END
300 r<sfile>
301 0norm0V:
302 :qall!
303 END
Bram Moolenaar5c645a22022-09-21 22:00:03 +0100304 call writefile(lines, 'Xexmodescript', 'D')
Bram Moolenaarf50808e2022-04-16 18:52:17 +0100305 call assert_equal(1, RunVim([], [], '-u NONE -e -s -S Xexmodescript'))
306
Bram Moolenaar217ea512022-06-14 17:13:59 +0100307 " This may cause a dialog to be displayed for an empty command, ignore it.
308 call delete('guidialogfile')
Bram Moolenaarf50808e2022-04-16 18:52:17 +0100309endfunc
310
Bram Moolenaar85b67472022-01-25 11:55:02 +0000311
Bram Moolenaare20b9ec2020-02-03 21:40:04 +0100312" vim: shiftwidth=2 sts=2 expandtab