1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
|
" Tests for system() and systemlist()
func Test_System()
if !has('win32')
call assert_equal("123\n", system('echo 123'))
call assert_equal(['123'], systemlist('echo 123'))
call assert_equal('123', system('cat', '123'))
call assert_equal(['123'], systemlist('cat', '123'))
call assert_equal(["as\<NL>df"], systemlist('cat', ["as\<NL>df"]))
else
call assert_equal("123\n", system('echo 123'))
call assert_equal(["123\r"], systemlist('echo 123'))
call assert_equal("123\n", system('more.com', '123'))
call assert_equal(["123\r"], systemlist('more.com', '123'))
call assert_equal(["as\r", "df\r"], systemlist('more.com', ["as\<NL>df"]))
endif
new Xdummy
call setline(1, ['asdf', "pw\<NL>er", 'xxxx'])
if executable('wc')
let out = system('wc -l', bufnr('%'))
" On OS/X we get leading spaces
let out = substitute(out, '^ *', '', '')
call assert_equal("3\n", out)
let out = systemlist('wc -l', bufnr('%'))
" On Windows we may get a trailing CR.
if out != ["3\r"]
" On OS/X we get leading spaces
if type(out) == v:t_list
let out[0] = substitute(out[0], '^ *', '', '')
endif
call assert_equal(['3'], out)
endif
endif
if !has('win32')
let out = systemlist('cat', bufnr('%'))
call assert_equal(['asdf', "pw\<NL>er", 'xxxx'], out)
else
let out = systemlist('more.com', bufnr('%'))
call assert_equal(["asdf\r", "pw\r", "er\r", "xxxx\r"], out)
endif
bwipe!
call assert_fails('call system("wc -l", 99999)', 'E86:')
endfunc
func Test_system_exmode()
if has('unix') " echo $? only works on Unix
let cmd = ' -es -c "source Xscript" +q; echo "result=$?"'
" Need to put this in a script, "catch" isn't found after an unknown
" function.
call writefile(['try', 'call doesnotexist()', 'catch', 'endtry'], 'Xscript', 'D')
let a = system(GetMNVCommand() . cmd)
call assert_match('result=0', a)
call assert_equal(0, v:shell_error)
endif
" Error before try does set error flag.
call writefile(['call nosuchfunction()', 'try', 'call doesnotexist()', 'catch', 'endtry'], 'Xscript')
if has('unix') " echo $? only works on Unix
let a = system(GetMNVCommand() . cmd)
call assert_notequal('0', a[0])
endif
let cmd = ' -es -c "source Xscript" +q'
let a = system(GetMNVCommand() . cmd)
call assert_notequal(0, v:shell_error)
if has('unix') " echo $? only works on Unix
let cmd = ' -es -c "call doesnotexist()" +q; echo $?'
let a = system(GetMNVCommand() . cmd)
call assert_notequal(0, a[0])
endif
let cmd = ' -es -c "call doesnotexist()" +q'
let a = system(GetMNVCommand(). cmd)
call assert_notequal(0, v:shell_error)
if has('unix') " echo $? only works on Unix
let cmd = ' -es -c "call doesnotexist()|let a=1" +q; echo $?'
let a = system(GetMNVCommand() . cmd)
call assert_notequal(0, a[0])
endif
let cmd = ' -es -c "call doesnotexist()|let a=1" +q'
let a = system(GetMNVCommand() . cmd)
call assert_notequal(0, v:shell_error)
endfunc
func Test_system_with_shell_quote()
CheckMSWindows
call mkdir('Xdir with spaces', 'p')
call system('copy "%COMSPEC%" "Xdir with spaces\cmd.exe"')
let shell_save = &shell
let shellxquote_save = &shellxquote
try
" Set 'shell' always needs noshellslash.
let shellslash_save = &shellslash
set noshellslash
let shell_tests = [
\ expand('$COMSPEC'),
\ '"' . fnamemodify('Xdir with spaces\cmd.exe', ':p') . '"',
\]
let &shellslash = shellslash_save
let sxq_tests = ['', '(', '"']
" Matrix tests: 'shell' * 'shellxquote'
for shell in shell_tests
let &shell = shell
for sxq in sxq_tests
let &shellxquote = sxq
let msg = printf('shell=%s shellxquote=%s', &shell, &shellxquote)
try
let out = 'echo 123'->system()
catch
call assert_report(printf('%s: %s', msg, v:exception))
continue
endtry
" On Windows we may get a trailing space and CR.
if out != "123 \n"
call assert_equal("123\n", out, msg)
endif
endfor
endfor
finally
let &shell = shell_save
let &shellxquote = shellxquote_save
call delete('Xdir with spaces', 'rf')
endtry
endfunc
" Check that MNV does not execute anything from current directory
func Test_windows_external_cmd_in_cwd()
CheckMSWindows
" just in case
call system('rd /S /Q Xfolder')
call mkdir('Xfolder', 'R')
cd Xfolder
let contents = ['@echo off', 'echo filename1.txt:1:AAAA']
call writefile(contents, 'findstr.cmd')
let file1 = ['AAAA', 'THIS FILE SHOULD NOT BE FOUND']
let file2 = ['BBBB', 'THIS FILE SHOULD BE FOUND']
call writefile(file1, 'filename1.txt')
call writefile(file2, 'filename2.txt')
if has('quickfix')
" use silent to avoid hit-enter-prompt
sil grep BBBB filename*.txt
call assert_equal('filename2.txt', @%)
endif
let output = system('findstr BBBB filename*')
" Match trailing newline byte
call assert_match('filename2.txt:BBBB.', output)
if has('gui')
set guioptions+=!
let output = system('findstr BBBB filename*')
call assert_match('filename2.txt:BBBB.', output)
endif
cd -
set guioptions&
endfunc
func Test_system_with_powershell()
CheckPowerShell
let shell_save = &shell
let shellcmdflag_save = &shellcmdflag
let shellxquote_save = &shellxquote
let shellpipe_save = &shellpipe
let shellredir_save = &shellredir
try
if executable('powershell')
let &shell = 'powershell'
let &shellcmdflag = '-Command'
let &shellredir = '2>&1 | Out-File -Encoding default'
else
let &shell = 'pwsh'
let &shellcmdflag = '-c'
let &shellredir = '>%s 2>&1'
endif
let &shellxquote = has('win32') ? '"' : ''
let &shellpipe = &shellredir
" Make sure compound commands are handled properly.
call assert_equal("123\n456\n", system('echo 123; echo 456'))
finally
let &shell = shell_save
let &shellcmdflag = shellcmdflag_save
let &shellxquote = shellxquote_save
let &shellpipe = shellpipe_save
let &shellredir = shellredir_save
endtry
endfunc
func Test_system_list_arg()
CheckExecutable python3
" When the command is a List, it is executed directly without the shell.
" Shell meta characters should not be interpreted but passed as-is.
" Redirect characters should be passed literally.
let out = system(['python3', '-c', 'import sys; print(sys.argv[1])', '<foo>'])
call assert_match('^<foo>', out)
" Environment variable syntax should not be expanded.
if has('win32')
let out = system(['python3', '-c', 'import sys; print(sys.argv[1])', '%USERPROFILE%'])
call assert_match('^%USERPROFILE%', out)
else
let out = system(['python3', '-c', 'import sys; print(sys.argv[1])', '$HOME'])
call assert_match('^\$HOME', out)
endif
" Spaces in arguments should be preserved without shell word splitting.
let out = system(['python3', '-c', 'import sys; print(sys.argv[1])', 'hello world'])
call assert_match('^hello world', out)
" Pipe and ampersand should be passed literally.
let out = system(['python3', '-c', 'import sys; print(sys.argv[1])', 'a&b|c'])
call assert_match('^a&b|c', out)
" systemlist() should work too.
let out = systemlist(['python3', '-c', 'print("line1"); print("line2")'])
call assert_match('^line1', out[0])
call assert_match('^line2', out[1])
" v:shell_error should be set.
call system(['python3', '-c', 'import sys; sys.exit(42)'])
call assert_equal(42, v:shell_error)
call system(['python3', '-c', 'import sys; sys.exit(0)'])
call assert_equal(0, v:shell_error)
" Invalid arguments.
call assert_fails('call system([])', 'E474:')
call assert_fails('call systemlist([])', 'E474:')
endfunc
" mnv: shiftwidth=2 sts=2 expandtab
|