@@ -162,12 +162,38 @@ endif
162162if has (' modify_fname' )
163163 let s: base_dir = expand (' <sfile>:p:h' )
164164
165- function ! s: set_shell ( shell )
166- let shell = a: shell
167- " de-quote
168- if shell [ 0 ] == # ' " '
169- let shell = shell [1 :-2 ]
165+ " Unescape ' shell' option in case that the user escaped it.
166+ function ! UnescapeShell ( shell )
167+ if ( has ( ' nvim ' ) || has ( ' win32 ' )) && a: shell = ~# ' ^".\+"$ '
168+ " de-quote
169+ return a: shell [1 :-2 ]
170170 endif
171+ if ! has (' nvim' ) && has (' unix' ) && a: shell = ~# ' \'
172+ " strip backslashes
173+ return substitute (a: shell , ' \' , ' ' , ' g' )
174+ endif
175+ return a: shell
176+ endfunction
177+
178+ " Escape 'shell' option depending on the editor.
179+ function ! EscapeShell (shell )
180+ if a: shell = ~# ' '
181+ if has (' nvim' ) || (has (' win32' ) && has (' patch-8.1.2115' ))
182+ " quote
183+ return ' "' . a: shell . ' "'
184+ endif
185+ " TODO: Investigate the patch that added support for escaped 'shell'.
186+ if ! has (' nvim' ) && has (' unix' ) && has (' patch-8.0.1176' )
187+ " add backslashes
188+ return escape (a: shell , ' ' )
189+ endif
190+ endif
191+ return a: shell
192+ endfunction
193+
194+ " If shell is supported, return 1. Else, return 0.
195+ function ! SetShell (shell )
196+ let shell = UnescapeShell (a: shell )
171197 let tail = fnamemodify (shell , ' :t' )
172198
173199 if tail = ~# ' ^cmd\.exe'
@@ -214,16 +240,19 @@ if has('modify_fname')
214240 let &shellxquote = (! has (' nvim' ) && has (' win32' )) ? ' "' : ' '
215241 else
216242 echoerr a: shell ' is not supported in Vim' v: version
217- return
243+ return 0
218244 endif
219- let &shell = match (shell , ' ' ) == -1 ? shell : ' "' . shell . ' "'
245+ let &shell = EscapeShell (shell )
246+ return 1
220247 endfunction
221248
222- if has (' win32' )
223- call s: set_shell (has (' nvim' ) || ! executable ($COMSPEC ) ? ' cmd.exe' : $COMSPEC )
224- elseif has (' unix' )
225- call s: set_shell (filter ([$SHELL , ' sh' ], ' executable(v:val)' )[0 ])
226- endif
249+ let s: shells = filter (has (' win32' ) ? [$COMSPEC , ' cmd.exe' ] : [$SHELL , ' sh' ], ' executable(v:val)' )
250+ for s: shell in s: shells
251+ if SetShell (s: shell )
252+ break
253+ endif
254+ endfor
255+ unlet s: shell s: shells
227256endif
228257
229258" Moved from normal to tiny version since 8.1.1901
@@ -429,7 +458,7 @@ if has('user_commands')
429458 endif
430459
431460 if has (' modify_fname' )
432- command ! -nargs =1 -complete =shellcmd SetShell call s: set_shell (<f-args> )
461+ command ! -nargs =1 -complete =shellcmd SetShell call SetShell (<f-args> )
433462 endif
434463
435464 if has (' syntax' )
0 commit comments