blob: 88d7a3a0e61c933d2833f9dea64010082244b05f [file] [log] [blame]
Bram Moolenaar9964e462007-05-05 17:54:07 +00001" ---------------------------------------------------------------------
2" getscript.vim
Christian Brabandtf9ca1392024-02-19 20:37:11 +01003" Maintainer: This runtime file is looking for a new maintainer.
4" Original Author: Charles E. Campbell
Bram Moolenaar8d043172014-01-23 14:24:41 +01005" Date: Jan 21, 2014
GuyBrushc854efc2024-09-26 16:14:08 +02006" Version: 37
Bram Moolenaar9964e462007-05-05 17:54:07 +00007" Installing: :help glvs-install
8" Usage: :help glvs
GuyBrush609599c2024-09-08 19:54:43 +02009" Last Change: {{{1
GuyBrushc854efc2024-09-26 16:14:08 +020010" 2024 Sep 08 by Vim Project: several small fixes (#15640)
11" 2024 Sep 23 by Vim Project: runtime dir selection fix (#15722)
12" autoloading search path fix
13" substitution of hardcoded commands with global variables
GuyBrush13a66052024-11-12 20:18:14 +010014" 2024 Nov 12 by Vim Project: fix problems on Windows (#16036)
Jim Zhou56957ed2025-02-28 18:06:14 +010015" 2025 Feb 28 by Vim Project: add support for bzip3 (#16755)
Christian Brabandt74e8f282025-05-11 14:43:11 +020016" 2025 May 11 by Vim Project: check network connectivity (#17249)
GuyBrush609599c2024-09-08 19:54:43 +020017" }}}
Bram Moolenaar9964e462007-05-05 17:54:07 +000018"
19" GetLatestVimScripts: 642 1 :AutoInstall: getscript.vim
Bram Moolenaar9e368db2007-05-12 13:25:01 +000020"redraw!|call inputsave()|call input("Press <cr> to continue")|call inputrestore()
Bram Moolenaar9964e462007-05-05 17:54:07 +000021" ---------------------------------------------------------------------
22" Initialization: {{{1
23" if you're sourcing this file, surely you can't be
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000024" expecting vim to be in its vi-compatible mode!
Bram Moolenaar5c736222010-01-06 20:54:52 +010025if exists("g:loaded_getscript")
26 finish
27endif
GuyBrushc854efc2024-09-26 16:14:08 +020028let g:loaded_getscript= "v37"
Bram Moolenaar9964e462007-05-05 17:54:07 +000029if &cp
30 echoerr "GetLatestVimScripts is not vi-compatible; not loaded (you need to set nocp)"
31 finish
32endif
GuyBrush13a66052024-11-12 20:18:14 +010033if v:version < 901
Bram Moolenaar5c736222010-01-06 20:54:52 +010034 echohl WarningMsg
GuyBrush13a66052024-11-12 20:18:14 +010035 echo "***warning*** this version of GetLatestVimScripts needs vim 9.1"
Bram Moolenaar5c736222010-01-06 20:54:52 +010036 echohl Normal
37 finish
38endif
Bram Moolenaar9964e462007-05-05 17:54:07 +000039let s:keepcpo = &cpo
40set cpo&vim
Bram Moolenaar82038d72007-05-10 17:15:45 +000041"DechoTabOn
Bram Moolenaar9964e462007-05-05 17:54:07 +000042
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000043" ---------------------------
44" Global Variables: {{{1
45" ---------------------------
46" Cygwin Detection ------- {{{2
47if !exists("g:getscript_cygwin")
48 if has("win32") || has("win95") || has("win64") || has("win16")
49 if &shell =~ '\%(\<bash\>\|\<zsh\>\)\%(\.exe\)\=$'
50 let g:getscript_cygwin= 1
51 else
52 let g:getscript_cygwin= 0
53 endif
54 else
55 let g:getscript_cygwin= 0
56 endif
57endif
Bram Moolenaar3577c6f2008-06-24 21:16:56 +000058
59" wget vs curl {{{2
Bram Moolenaar9964e462007-05-05 17:54:07 +000060if !exists("g:GetLatestVimScripts_wget")
61 if executable("wget")
62 let g:GetLatestVimScripts_wget= "wget"
GuyBrush13a66052024-11-12 20:18:14 +010063 elseif executable("curl.exe")
64 " enforce extension: windows powershell desktop version has a curl alias that hides curl.exe
65 let g:GetLatestVimScripts_wget= "curl.exe"
Bram Moolenaar9964e462007-05-05 17:54:07 +000066 elseif executable("curl")
67 let g:GetLatestVimScripts_wget= "curl"
68 else
69 let g:GetLatestVimScripts_wget = 'echo "GetLatestVimScripts needs wget or curl"'
70 let g:GetLatestVimScripts_options = ""
71 endif
72endif
73
74" options that wget and curl require:
75if !exists("g:GetLatestVimScripts_options")
76 if g:GetLatestVimScripts_wget == "wget"
77 let g:GetLatestVimScripts_options= "-q -O"
GuyBrush13a66052024-11-12 20:18:14 +010078 elseif g:GetLatestVimScripts_wget =~ "curl"
GuyBrush609599c2024-09-08 19:54:43 +020079 let g:GetLatestVimScripts_options= "-s -o"
Bram Moolenaar9964e462007-05-05 17:54:07 +000080 else
81 let g:GetLatestVimScripts_options= ""
82 endif
83endif
84
85" by default, allow autoinstall lines to work
86if !exists("g:GetLatestVimScripts_allowautoinstall")
87 let g:GetLatestVimScripts_allowautoinstall= 1
88endif
89
Bram Moolenaarff034192013-04-24 18:51:19 +020090" set up default scriptaddr address
91if !exists("g:GetLatestVimScripts_scriptaddr")
GuyBrush609599c2024-09-08 19:54:43 +020092 let g:GetLatestVimScripts_scriptaddr = 'https://www.vim.org/scripts/script.php?script_id='
93endif
94
95if !exists("g:GetLatestVimScripts_downloadaddr")
96 let g:GetLatestVimScripts_downloadaddr = 'https://www.vim.org/scripts/download_script.php?src_id='
Bram Moolenaarff034192013-04-24 18:51:19 +020097endif
98
GuyBrushc854efc2024-09-26 16:14:08 +020099" define decompression tools (on windows this allows redirection to wsl or git tools).
100" Note tar is available as builtin since Windows 11.
101if !exists("g:GetLatestVimScripts_bunzip2")
102 let g:GetLatestVimScripts_bunzip2= "bunzip2"
103endif
104
Jim Zhou56957ed2025-02-28 18:06:14 +0100105if !exists("g:GetLatestVimScripts_bunzip3")
106 let g:GetLatestVimScripts_bunzip3= "bunzip3"
107endif
108
GuyBrushc854efc2024-09-26 16:14:08 +0200109if !exists("g:GetLatestVimScripts_gunzip")
110 let g:GetLatestVimScripts_gunzip= "gunzip"
111endif
112
113if !exists("g:GetLatestVimScripts_unxz")
114 let g:GetLatestVimScripts_unxz= "unxz"
115endif
116
117if !exists("g:GetLatestVimScripts_unzip")
118 let g:GetLatestVimScripts_unzip= "unzip"
119endif
120
Bram Moolenaar9964e462007-05-05 17:54:07 +0000121"" For debugging:
122"let g:GetLatestVimScripts_wget = "echo"
123"let g:GetLatestVimScripts_options = "options"
124
125" ---------------------------------------------------------------------
126" Check If AutoInstall Capable: {{{1
127let s:autoinstall= ""
128if g:GetLatestVimScripts_allowautoinstall
129
GuyBrushc854efc2024-09-26 16:14:08 +0200130 let s:is_windows = has("win32") || has("gui_win32") || has("gui_win32s") || has("win16") || has("win64") || has("win32unix") || has("win95")
131 let s:dotvim= s:is_windows ? "vimfiles" : ".vim"
Bram Moolenaar9964e462007-05-05 17:54:07 +0000132
GuyBrushc854efc2024-09-26 16:14:08 +0200133 if !exists("g:GetLatestVimScripts_mv")
GuyBrush13a66052024-11-12 20:18:14 +0100134 if &shell =~? '\<pwsh\>\|\<powershell\>'
135 let g:GetLatestVimScripts_mv= "move -Force"
136 elseif s:is_windows && &shell =~? '\<cmd\>'
GuyBrushc854efc2024-09-26 16:14:08 +0200137 " windows (but not cygwin/bash)
GuyBrush13a66052024-11-12 20:18:14 +0100138 let g:GetLatestVimScripts_mv= "move /Y"
GuyBrushc854efc2024-09-26 16:14:08 +0200139 else
GuyBrush13a66052024-11-12 20:18:14 +0100140 " unix or cygwin bash/zsh
141 " 'mv' overrides existing files without asking
GuyBrushc854efc2024-09-26 16:14:08 +0200142 let g:GetLatestVimScripts_mv= "mv"
Bram Moolenaar9964e462007-05-05 17:54:07 +0000143 endif
144 endif
145
Bram Moolenaar5c736222010-01-06 20:54:52 +0100146 if exists("g:GetLatestVimScripts_autoinstalldir") && isdirectory(g:GetLatestVimScripts_autoinstalldir)
147 let s:autoinstall= g:GetLatestVimScripts_autoinstalldir"
148 elseif exists('$HOME') && isdirectory(expand("$HOME")."/".s:dotvim)
Bram Moolenaar9964e462007-05-05 17:54:07 +0000149 let s:autoinstall= $HOME."/".s:dotvim
150 endif
Bram Moolenaar9964e462007-05-05 17:54:07 +0000151endif
152
153" ---------------------------------------------------------------------
154" Public Interface: {{{1
155com! -nargs=0 GetLatestVimScripts call getscript#GetLatestVimScripts()
156com! -nargs=0 GetScript call getscript#GetLatestVimScripts()
157silent! com -nargs=0 GLVS call getscript#GetLatestVimScripts()
158
159" ---------------------------------------------------------------------
Bram Moolenaar9964e462007-05-05 17:54:07 +0000160" GetLatestVimScripts: this function gets the latest versions of {{{1
161" scripts based on the list in
162" (first dir in runtimepath)/GetLatest/GetLatestVimScripts.dat
163fun! getscript#GetLatestVimScripts()
Bram Moolenaar9964e462007-05-05 17:54:07 +0000164
Bram Moolenaar9964e462007-05-05 17:54:07 +0000165 if executable(g:GetLatestVimScripts_wget) != 1
166 echoerr "GetLatestVimScripts needs ".g:GetLatestVimScripts_wget." which apparently is not available on your system"
Bram Moolenaar9964e462007-05-05 17:54:07 +0000167 return
168 endif
169
170 " Find the .../GetLatest subdirectory under the runtimepath
171 for datadir in split(&rtp,',') + ['']
172 if isdirectory(datadir."/GetLatest")
Bram Moolenaar9964e462007-05-05 17:54:07 +0000173 let datadir= datadir . "/GetLatest"
174 break
175 endif
176 if filereadable(datadir."GetLatestVimScripts.dat")
Bram Moolenaar82038d72007-05-10 17:15:45 +0000177 break
Bram Moolenaar9964e462007-05-05 17:54:07 +0000178 endif
179 endfor
Bram Moolenaar82038d72007-05-10 17:15:45 +0000180
Bram Moolenaar9964e462007-05-05 17:54:07 +0000181 " Sanity checks: readability and writability
182 if datadir == ""
183 echoerr 'Missing "GetLatest/" on your runtimepath - see :help glvs-dist-install'
Bram Moolenaar9964e462007-05-05 17:54:07 +0000184 return
185 endif
Bram Moolenaar9964e462007-05-05 17:54:07 +0000186 if filewritable(datadir) != 2
187 echoerr "(getLatestVimScripts) Your ".datadir." isn't writable"
Bram Moolenaar9964e462007-05-05 17:54:07 +0000188 return
189 endif
190 let datafile= datadir."/GetLatestVimScripts.dat"
191 if !filereadable(datafile)
192 echoerr "Your data file<".datafile."> isn't readable"
Bram Moolenaar9964e462007-05-05 17:54:07 +0000193 return
194 endif
195 if !filewritable(datafile)
196 echoerr "Your data file<".datafile."> isn't writable"
Bram Moolenaar9964e462007-05-05 17:54:07 +0000197 return
198 endif
Bram Moolenaar5c736222010-01-06 20:54:52 +0100199 " --------------------
200 " Passed sanity checks
201 " --------------------
202
Bram Moolenaar5c736222010-01-06 20:54:52 +0100203 " don't let any event handlers interfere (like winmanager's, taglist's, etc)
204 let eikeep = &ei
205 let hlskeep = &hls
206 let acdkeep = &acd
207 set ei=all hls&vim noacd
Bram Moolenaar9964e462007-05-05 17:54:07 +0000208
Bram Moolenaar5c736222010-01-06 20:54:52 +0100209 " Edit the datafile (ie. GetLatestVimScripts.dat):
210 " 1. record current directory (origdir),
211 " 2. change directory to datadir,
212 " 3. split window
213 " 4. edit datafile
Bram Moolenaar9964e462007-05-05 17:54:07 +0000214 let origdir= getcwd()
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000215 exe "cd ".fnameescape(substitute(datadir,'\','/','ge'))
Bram Moolenaar9964e462007-05-05 17:54:07 +0000216 split
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000217 exe "e ".fnameescape(substitute(datafile,'\','/','ge'))
Bram Moolenaar9964e462007-05-05 17:54:07 +0000218 res 1000
219 let s:downloads = 0
220 let s:downerrors= 0
Christian Brabandt74e8f282025-05-11 14:43:11 +0200221 let s:message = []
Bram Moolenaar9964e462007-05-05 17:54:07 +0000222
223 " Check on dependencies mentioned in plugins
Bram Moolenaar9964e462007-05-05 17:54:07 +0000224 let lastline = line("$")
GuyBrushc854efc2024-09-26 16:14:08 +0200225 let firstdir = substitute(&rtp,',.*$','','')
Bram Moolenaar8d043172014-01-23 14:24:41 +0100226 let plugins = split(globpath(firstdir,"plugin/**/*.vim"),'\n')
GuyBrush609599c2024-09-08 19:54:43 +0200227 let plugins += split(globpath(firstdir,"ftplugin/**/*.vim"),'\n')
228 let plugins += split(globpath(firstdir,"AsNeeded/**/*.vim"),'\n')
GuyBrushc854efc2024-09-26 16:14:08 +0200229 let plugins += split(globpath(firstdir,"pack/*/start/*/plugin/**/*.vim"),'\n')
230 let plugins += split(globpath(firstdir,"pack/*/opt/*/plugin/**/*.vim"),'\n')
231 let plugins += split(globpath(firstdir,"pack/*/start/*/ftplugin/**/*.vim"),'\n')
232 let plugins += split(globpath(firstdir,"pack/*/opt/*/ftplugin/**/*.vim"),'\n')
Bram Moolenaar9964e462007-05-05 17:54:07 +0000233 let foundscript = 0
234
Bram Moolenaar5c736222010-01-06 20:54:52 +0100235 " this loop updates the GetLatestVimScripts.dat file
236 " with dependencies explicitly mentioned in the plugins
237 " via GetLatestVimScripts: ... lines
238 " It reads the plugin script at the end of the GetLatestVimScripts.dat
239 " file, examines it, and then removes it.
Bram Moolenaar82038d72007-05-10 17:15:45 +0000240 for plugin in plugins
241
Bram Moolenaar82038d72007-05-10 17:15:45 +0000242 " read plugin in
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000243 " evidently a :r creates a new buffer (the "#" buffer) that is subsequently unused -- bwiping it
Bram Moolenaar9964e462007-05-05 17:54:07 +0000244 $
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000245 exe "silent r ".fnameescape(plugin)
246 exe "silent bwipe ".bufnr("#")
Bram Moolenaar82038d72007-05-10 17:15:45 +0000247
Bram Moolenaar9964e462007-05-05 17:54:07 +0000248 while search('^"\s\+GetLatestVimScripts:\s\+\d\+\s\+\d\+','W') != 0
Bram Moolenaar5c736222010-01-06 20:54:52 +0100249 let depscript = substitute(getline("."),'^"\s\+GetLatestVimScripts:\s\+\d\+\s\+\d\+\s\+\(.*\)$','\1','e')
250 let depscriptid = substitute(getline("."),'^"\s\+GetLatestVimScripts:\s\+\(\d\+\)\s\+.*$','\1','')
251 let llp1 = lastline+1
Bram Moolenaar9964e462007-05-05 17:54:07 +0000252
Bram Moolenaar5c736222010-01-06 20:54:52 +0100253 " found a "GetLatestVimScripts: # #" line in the script;
Bram Moolenaar8024f932020-01-14 19:29:13 +0100254 " check if it's already in the datafile by searching backwards from llp1,
Bram Moolenaar5c736222010-01-06 20:54:52 +0100255 " the (prior to reading in the plugin script) last line plus one of the GetLatestVimScripts.dat file,
256 " for the script-id with no wrapping allowed.
257 let curline = line(".")
258 let noai_script = substitute(depscript,'\s*:AutoInstall:\s*','','e')
259 exe llp1
260 let srchline = search('^\s*'.depscriptid.'\s\+\d\+\s\+.*$','bW')
261 if srchline == 0
262 " this second search is taken when, for example, a 0 0 scriptname is to be skipped over
263 let srchline= search('\<'.noai_script.'\>','bW')
Bram Moolenaar82038d72007-05-10 17:15:45 +0000264 endif
Bram Moolenaar5c736222010-01-06 20:54:52 +0100265
266 if srchline == 0
267 " found a new script to permanently include in the datafile
268 let keep_rega = @a
269 let @a = substitute(getline(curline),'^"\s\+GetLatestVimScripts:\s\+','','')
270 echomsg "Appending <".@a."> to ".datafile." for ".depscript
Bram Moolenaar5c736222010-01-06 20:54:52 +0100271 exe lastline."put a"
272 let @a = keep_rega
273 let lastline = llp1
274 let curline = curline + 1
275 let foundscript = foundscript + 1
Bram Moolenaar5c736222010-01-06 20:54:52 +0100276 endif
277
278 let curline = curline + 1
279 exe curline
Bram Moolenaar9964e462007-05-05 17:54:07 +0000280 endwhile
Bram Moolenaar82038d72007-05-10 17:15:45 +0000281
Bram Moolenaar5c736222010-01-06 20:54:52 +0100282 " llp1: last line plus one
Bram Moolenaar9964e462007-05-05 17:54:07 +0000283 let llp1= lastline + 1
Bram Moolenaar9964e462007-05-05 17:54:07 +0000284 exe "silent! ".llp1.",$d"
Bram Moolenaar82038d72007-05-10 17:15:45 +0000285 endfor
Bram Moolenaar9964e462007-05-05 17:54:07 +0000286
287 if foundscript == 0
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000288 setlocal nomod
Bram Moolenaar9964e462007-05-05 17:54:07 +0000289 endif
290
Bram Moolenaar5c736222010-01-06 20:54:52 +0100291 " --------------------------------------------------------------------
Bram Moolenaar9964e462007-05-05 17:54:07 +0000292 " Check on out-of-date scripts using GetLatest/GetLatestVimScripts.dat
Bram Moolenaar5c736222010-01-06 20:54:52 +0100293 " --------------------------------------------------------------------
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000294 setlocal lz
Bram Moolenaar9964e462007-05-05 17:54:07 +0000295 1
Bram Moolenaar82038d72007-05-10 17:15:45 +0000296 /^-----/,$g/^\s*\d/call s:GetOneScript()
Bram Moolenaar9964e462007-05-05 17:54:07 +0000297
298 " Final report (an echomsg)
299 try
300 silent! ?^-------?
301 catch /^Vim\%((\a\+)\)\=:E114/
Bram Moolenaar9964e462007-05-05 17:54:07 +0000302 return
303 endtry
304 exe "norm! kz\<CR>"
305 redraw!
Christian Brabandt74e8f282025-05-11 14:43:11 +0200306 if !empty(s:message)
307 echohl WarningMsg
308 for mess in s:message
309 echom mess
310 endfor
311 let s:downerrors += len(s:message)
312 endif
Bram Moolenaar9964e462007-05-05 17:54:07 +0000313 let s:msg = ""
314 if s:downloads == 1
315 let s:msg = "Downloaded one updated script to <".datadir.">"
Bram Moolenaar9964e462007-05-05 17:54:07 +0000316 elseif s:downloads > 1
317 let s:msg= "Downloaded ".s:downloads." updated scripts to <".datadir.">"
318 else
Christian Brabandt74e8f282025-05-11 14:43:11 +0200319 let s:msg= empty(s:message) ? "Everything was already current" : "There were some errors"
Bram Moolenaar9964e462007-05-05 17:54:07 +0000320 endif
321 if s:downerrors > 0
322 let s:msg= s:msg." (".s:downerrors." downloading errors)"
323 endif
324 echomsg s:msg
325 " save the file
326 if &mod
327 silent! w!
328 endif
Bram Moolenaarff034192013-04-24 18:51:19 +0200329 q!
Bram Moolenaar9964e462007-05-05 17:54:07 +0000330
331 " restore events and current directory
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000332 exe "cd ".fnameescape(substitute(origdir,'\','/','ge'))
Bram Moolenaar5c736222010-01-06 20:54:52 +0100333 let &ei = eikeep
334 let &hls = hlskeep
335 let &acd = acdkeep
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000336 setlocal nolz
Bram Moolenaar9964e462007-05-05 17:54:07 +0000337endfun
Bram Moolenaar9964e462007-05-05 17:54:07 +0000338
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000339" ---------------------------------------------------------------------
h-easta4205472024-10-13 19:16:42 +0200340" GetOneScript: (Get Latest Vim script) this function operates {{{1
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000341" on the current line, interpreting two numbers and text as
342" ScriptID, SourceID, and Filename.
Bram Moolenaar5c736222010-01-06 20:54:52 +0100343" It downloads any scripts that have newer versions from vim.sourceforge.net.
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000344fun! s:GetOneScript(...)
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000345 " set options to allow progress to be shown on screen
346 let rega= @a
347 let t_ti= &t_ti
348 let t_te= &t_te
349 let rs = &rs
GuyBrush13a66052024-11-12 20:18:14 +0100350 let ssl = &ssl
351
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000352 set t_ti= t_te= nors
GuyBrush13a66052024-11-12 20:18:14 +0100353 " avoid issues with shellescape() on Windows
354 if s:is_windows && &shell =~? '\<cmd\>'
355 set noshellslash
356 endif
357
358 " restore valures afterwards
359 defer execute("let @a = rega | let &t_ti = t_ti | let &t_te = t_te | let &rs = rs | let &ssl = ssl")
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000360
361 " put current line on top-of-screen and interpret it into
Bram Moolenaar6c391a72021-09-09 21:55:11 +0200362 " a script identifier : used to obtain webpage
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000363 " source identifier : used to identify current version
364 " and an associated comment: used to report on what's being considered
365 if a:0 >= 3
366 let scriptid = a:1
367 let srcid = a:2
368 let fname = a:3
369 let cmmnt = ""
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000370 else
371 let curline = getline(".")
372 if curline =~ '^\s*#'
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000373 return
374 endif
375 let parsepat = '^\s*\(\d\+\)\s\+\(\d\+\)\s\+\(.\{-}\)\(\s*#.*\)\=$'
376 try
377 let scriptid = substitute(curline,parsepat,'\1','e')
378 catch /^Vim\%((\a\+)\)\=:E486/
379 let scriptid= 0
380 endtry
381 try
382 let srcid = substitute(curline,parsepat,'\2','e')
383 catch /^Vim\%((\a\+)\)\=:E486/
384 let srcid= 0
385 endtry
386 try
387 let fname= substitute(curline,parsepat,'\3','e')
388 catch /^Vim\%((\a\+)\)\=:E486/
389 let fname= ""
390 endtry
391 try
392 let cmmnt= substitute(curline,parsepat,'\4','e')
393 catch /^Vim\%((\a\+)\)\=:E486/
394 let cmmnt= ""
395 endtry
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000396 endif
397
Bram Moolenaar5c736222010-01-06 20:54:52 +0100398 " plugin author protection from downloading his/her own scripts atop their latest work
Christian Brabandt74e8f282025-05-11 14:43:11 +0200399 " When looking for :AutoInstall: lines, skip scripts that have 0 0 scriptname
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000400 if scriptid == 0 || srcid == 0
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000401 return
402 endif
403
404 let doautoinstall= 0
405 if fname =~ ":AutoInstall:"
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000406 let aicmmnt= substitute(fname,'\s\+:AutoInstall:\s\+',' ','')
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000407 if s:autoinstall != ""
408 let doautoinstall = g:GetLatestVimScripts_allowautoinstall
409 endif
410 else
411 let aicmmnt= fname
412 endif
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000413
414 exe "norm z\<CR>"
415 redraw!
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000416 echo 'considering <'.aicmmnt.'> scriptid='.scriptid.' srcid='.srcid
417
Bram Moolenaar5c736222010-01-06 20:54:52 +0100418 " grab a copy of the plugin's vim.sourceforge.net webpage
Bram Moolenaarff034192013-04-24 18:51:19 +0200419 let scriptaddr = g:GetLatestVimScripts_scriptaddr.scriptid
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000420 let tmpfile = tempname()
421 let v:errmsg = ""
422
Christian Brabandt74e8f282025-05-11 14:43:11 +0200423 " Check if URLs are reachable
424 if !CheckVimScriptURL(scriptid, srcid)
425 return
426 endif
427
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000428 " make up to three tries at downloading the description
429 let itry= 1
430 while itry <= 3
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000431 if has("win32") || has("win16") || has("win95")
Bram Moolenaar5c736222010-01-06 20:54:52 +0100432 new|exe "silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(tmpfile).' '.shellescape(scriptaddr)|bw!
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000433 else
Bram Moolenaar5c736222010-01-06 20:54:52 +0100434 exe "silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(tmpfile)." ".shellescape(scriptaddr)
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000435 endif
436 if itry == 1
437 exe "silent vsplit ".fnameescape(tmpfile)
438 else
439 silent! e %
440 endif
441 setlocal bh=wipe
442
443 " find the latest source-id in the plugin's webpage
444 silent! 1
445 let findpkg= search('Click on the package to download','W')
446 if findpkg > 0
447 break
448 endif
449 let itry= itry + 1
450 endwhile
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000451
452 " testing: did finding "Click on the package..." fail?
453 if findpkg == 0 || itry >= 4
454 silent q!
455 call delete(tmpfile)
456 " restore options
457 let &t_ti = t_ti
458 let &t_te = t_te
459 let &rs = rs
460 let s:downerrors = s:downerrors + 1
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000461 echomsg "***warning*** couldn'".'t find "Click on the package..." in description page for <'.aicmmnt.">"
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000462 return
463 endif
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000464
465 let findsrcid= search('src_id=','W')
466 if findsrcid == 0
467 silent q!
468 call delete(tmpfile)
469 " restore options
470 let &t_ti = t_ti
471 let &t_te = t_te
472 let &rs = rs
473 let s:downerrors = s:downerrors + 1
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000474 echomsg "***warning*** couldn'".'t find "src_id=" in description page for <'.aicmmnt.">"
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000475 return
476 endif
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000477
478 let srcidpat = '^\s*<td class.*src_id=\(\d\+\)">\([^<]\+\)<.*$'
479 let latestsrcid= substitute(getline("."),srcidpat,'\1','')
480 let sname = substitute(getline("."),srcidpat,'\2','') " script name actually downloaded
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000481 silent q!
482 call delete(tmpfile)
483
484 " convert the strings-of-numbers into numbers
485 let srcid = srcid + 0
486 let latestsrcid = latestsrcid + 0
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000487
Bram Moolenaar5c736222010-01-06 20:54:52 +0100488 " has the plugin's most-recent srcid increased, which indicates that it has been updated
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000489 if latestsrcid > srcid
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000490
491 let s:downloads= s:downloads + 1
492 if sname == bufname("%")
493 " GetLatestVimScript has to be careful about downloading itself
494 let sname= "NEW_".sname
495 endif
496
Bram Moolenaar5c736222010-01-06 20:54:52 +0100497 " -----------------------------------------------------------------------------
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000498 " the plugin has been updated since we last obtained it, so download a new copy
Bram Moolenaar5c736222010-01-06 20:54:52 +0100499 " -----------------------------------------------------------------------------
Bram Moolenaar5c736222010-01-06 20:54:52 +0100500 echomsg ".downloading new <".sname.">"
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000501 if has("win32") || has("win16") || has("win95")
GuyBrush13a66052024-11-12 20:18:14 +0100502 new|exe "silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(sname)." ".shellescape(g:GetLatestVimScripts_downloadaddr.latestsrcid)|bw!
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000503 else
GuyBrush13a66052024-11-12 20:18:14 +0100504 exe "silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(sname)." ".shellescape(g:GetLatestVimScripts_downloadaddr.latestsrcid)
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000505 endif
506
Bram Moolenaar5c736222010-01-06 20:54:52 +0100507 " --------------------------------------------------------------------------
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000508 " AutoInstall: only if doautoinstall has been requested by the plugin itself
Bram Moolenaar5c736222010-01-06 20:54:52 +0100509 " --------------------------------------------------------------------------
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000510 if doautoinstall
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000511 if filereadable(sname)
Bram Moolenaar5c736222010-01-06 20:54:52 +0100512 exe "silent !".g:GetLatestVimScripts_mv." ".shellescape(sname)." ".shellescape(s:autoinstall)
Bram Moolenaar251e1912011-06-19 05:09:16 +0200513 let curdir = fnameescape(substitute(getcwd(),'\','/','ge'))
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000514 let installdir= curdir."/Installed"
515 if !isdirectory(installdir)
516 call mkdir(installdir)
517 endif
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000518 exe "cd ".fnameescape(s:autoinstall)
Bram Moolenaar5c736222010-01-06 20:54:52 +0100519
520 " determine target directory for moves
521 let firstdir= substitute(&rtp,',.*$','','')
522 let pname = substitute(sname,'\..*','.vim','')
Bram Moolenaar5c736222010-01-06 20:54:52 +0100523 if filereadable(firstdir.'/AsNeeded/'.pname)
524 let tgtdir= "AsNeeded"
525 else
526 let tgtdir= "plugin"
527 endif
Jim Zhou56957ed2025-02-28 18:06:14 +0100528
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000529 " decompress
530 if sname =~ '\.bz2$'
GuyBrushc854efc2024-09-26 16:14:08 +0200531 exe "sil !".g:GetLatestVimScripts_bunzip2." ".shellescape(sname)
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000532 let sname= substitute(sname,'\.bz2$','','')
Jim Zhou56957ed2025-02-28 18:06:14 +0100533 elseif sname =~ '\.bz3$'
534 exe "sil !".g:GetLatestVimScripts_bunzip3." ".shellescape(sname)
535 let sname= substitute(sname,'\.bz3$','','')
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000536 elseif sname =~ '\.gz$'
GuyBrushc854efc2024-09-26 16:14:08 +0200537 exe "sil !".g:GetLatestVimScripts_gunzip." ".shellescape(sname)
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000538 let sname= substitute(sname,'\.gz$','','')
Bram Moolenaar251e1912011-06-19 05:09:16 +0200539 elseif sname =~ '\.xz$'
GuyBrushc854efc2024-09-26 16:14:08 +0200540 exe "sil !".g:GetLatestVimScripts_unxz." ".shellescape(sname)
Bram Moolenaar251e1912011-06-19 05:09:16 +0200541 let sname= substitute(sname,'\.xz$','','')
Bram Moolenaar5c736222010-01-06 20:54:52 +0100542 else
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000543 endif
Jim Zhou56957ed2025-02-28 18:06:14 +0100544
GuyBrush609599c2024-09-08 19:54:43 +0200545 " distribute archive(.zip, .tar, .vba, .vmb, ...) contents
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000546 if sname =~ '\.zip$'
GuyBrushc854efc2024-09-26 16:14:08 +0200547 exe "silent !".g:GetLatestVimScripts_unzip." -o ".shellescape(sname)
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000548 elseif sname =~ '\.tar$'
Bram Moolenaar5c736222010-01-06 20:54:52 +0100549 exe "silent !tar -xvf ".shellescape(sname)
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100550 elseif sname =~ '\.tgz$'
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100551 exe "silent !tar -zxvf ".shellescape(sname)
552 elseif sname =~ '\.taz$'
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100553 exe "silent !tar -Zxvf ".shellescape(sname)
554 elseif sname =~ '\.tbz$'
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100555 exe "silent !tar -jxvf ".shellescape(sname)
556 elseif sname =~ '\.txz$'
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100557 exe "silent !tar -Jxvf ".shellescape(sname)
GuyBrush609599c2024-09-08 19:54:43 +0200558 elseif sname =~ '\.vba$\|\.vmb$'
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000559 silent 1split
Bram Moolenaar5c736222010-01-06 20:54:52 +0100560 if exists("g:vimball_home")
561 let oldvimballhome= g:vimball_home
562 endif
563 let g:vimball_home= s:autoinstall
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000564 exe "silent e ".fnameescape(sname)
565 silent so %
566 silent q
Bram Moolenaar5c736222010-01-06 20:54:52 +0100567 if exists("oldvimballhome")
568 let g:vimball_home= oldvimballhome
569 else
570 unlet g:vimball_home
571 endif
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000572 endif
Jim Zhou56957ed2025-02-28 18:06:14 +0100573
Bram Moolenaar5c736222010-01-06 20:54:52 +0100574 " ---------------------------------------------
575 " move plugin to plugin/ or AsNeeded/ directory
576 " ---------------------------------------------
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000577 if sname =~ '.vim$'
Bram Moolenaar5c736222010-01-06 20:54:52 +0100578 exe "silent !".g:GetLatestVimScripts_mv." ".shellescape(sname)." ".tgtdir
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000579 else
Bram Moolenaar5c736222010-01-06 20:54:52 +0100580 exe "silent !".g:GetLatestVimScripts_mv." ".shellescape(sname)." ".installdir
581 endif
582 if tgtdir != "plugin"
GuyBrush13a66052024-11-12 20:18:14 +0100583 exe "silent !".g:GetLatestVimScripts_mv." ".shellescape("plugin/".pname)." ".tgtdir
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000584 endif
Jim Zhou56957ed2025-02-28 18:06:14 +0100585
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000586 " helptags step
587 let docdir= substitute(&rtp,',.*','','e')."/doc"
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000588 exe "helptags ".fnameescape(docdir)
589 exe "cd ".fnameescape(curdir)
590 endif
591 if fname !~ ':AutoInstall:'
592 let modline=scriptid." ".latestsrcid." :AutoInstall: ".fname.cmmnt
593 else
594 let modline=scriptid." ".latestsrcid." ".fname.cmmnt
595 endif
596 else
597 let modline=scriptid." ".latestsrcid." ".fname.cmmnt
598 endif
599
600 " update the data in the <GetLatestVimScripts.dat> file
601 call setline(line("."),modline)
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000602 endif
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000603endfun
604
Christian Brabandt74e8f282025-05-11 14:43:11 +0200605" CheckVimScriptURL: Check Network Connection {{{1
606" Check status code of scriptaddr and downloadaddr
607" return v:true if the script is downloadable or v:false in case of errors
608fun CheckVimScriptURL(script_id, src_id)
609 if !executable('curl')
610 return v:true
611 endif
612 let output = has("win32") ? ' -o NUL ' : ' -o /dev/null '
613
614 " Handle PowerShell differently
615 if &shell =~? '\<pwsh\>\|\<powershell\>'
616 " For PowerShell, use direct command output
617 let script_url = g:GetLatestVimScripts_scriptaddr . a:script_id
618 let script_cmd = 'curl -s -I -w "%{http_code}"' . output . shellescape(script_url)
619 let script_status = system(script_cmd)
620 let script_status = substitute(script_status, '\n$', '', '')
621
622 let download_url = g:GetLatestVimScripts_downloadaddr . a:src_id
623 let download_cmd = 'curl -s -I -w "%{http_code}"' . output . shellescape(download_url)
624 let download_status = system(download_cmd)
625 let download_status = substitute(download_status, '\n$', '', '')
626 else
627 " For other shells, use temporary files
628 let temp_script = tempname()
629 let temp_download = tempname()
630
631 let script_url = g:GetLatestVimScripts_scriptaddr . a:script_id
632 let script_cmd = 'curl -s -I -w "%{http_code}"' . output . shellescape(script_url) . ' >' . shellescape(temp_script)
633 call system(script_cmd)
634 let script_status = readfile(temp_script, 'b')[0]
635 call delete(temp_script)
636
637 let download_url = g:GetLatestVimScripts_downloadaddr . a:src_id
638 let download_cmd = 'curl -s -I -w "%{http_code}"' . output . shellescape(download_url) . ' >' . shellescape(temp_download)
639 call system(download_cmd)
640 let download_status = readfile(temp_download, 'b')[0]
641 call delete(temp_download)
642 endif
643
644 if script_status !=# '200'
645 let s:message += [ printf('Error: Failed to reach script: %s', a:script_id) ]
646 return v:false
647 endif
648
649 if download_status !=# '200'
650 let s:message += [ printf('Error: Failed to download script %s', a:script_id) ]
651 return v:false
652 endif
653 return v:true
654endfunction
655
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000656" ---------------------------------------------------------------------
Bram Moolenaar9964e462007-05-05 17:54:07 +0000657" Restore Options: {{{1
Bram Moolenaar9964e462007-05-05 17:54:07 +0000658let &cpo= s:keepcpo
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000659unlet s:keepcpo
Bram Moolenaar9964e462007-05-05 17:54:07 +0000660
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000661" ---------------------------------------------------------------------
662" Modelines: {{{1
Bram Moolenaar9964e462007-05-05 17:54:07 +0000663" vim: ts=8 sts=2 fdm=marker nowrap