xref: /vim-8.2.3635/runtime/autoload/vimball.vim (revision 3577c6fa)
1" vimball.vim : construct a file containing both paths and files
2" Author:	Charles E. Campbell, Jr.
3" Date:		Jun 05, 2008
4" Version:	27
5" GetLatestVimScripts: 1502 1 :AutoInstall: vimball.vim
6" Copyright: (c) 2004-2008 by Charles E. Campbell, Jr.
7"            The VIM LICENSE applies to Vimball.vim, and Vimball.txt
8"            (see |copyright|) except use "Vimball" instead of "Vim".
9"            No warranty, express or implied.
10"  *** ***   Use At-Your-Own-Risk!   *** ***
11
12" ---------------------------------------------------------------------
13"  Load Once: {{{1
14if &cp || exists("g:loaded_vimball") || v:version < 700
15 finish
16endif
17let s:keepcpo        = &cpo
18let g:loaded_vimball = "v27"
19set cpo&vim
20"DechoTabOn
21
22" =====================================================================
23" Constants: {{{1
24if !exists("s:USAGE")
25 let s:USAGE   = 0
26 let s:WARNING = 1
27 let s:ERROR   = 2
28
29 " determine if cygwin is in use or not
30 if !exists("g:netrw_cygwin")
31  if has("win32") || has("win95") || has("win64") || has("win16")
32   if &shell =~ '\%(\<bash\>\|\<zsh\>\)\%(\.exe\)\=$'
33    let g:netrw_cygwin= 1
34   else
35    let g:netrw_cygwin= 0
36   endif
37  else
38   let g:netrw_cygwin= 0
39  endif
40 endif
41
42 " set up g:vimball_mkdir if the mkdir() call isn't defined
43 if !exists("*mkdir")
44  if exists("g:netrw_local_mkdir")
45   let g:vimball_mkdir= g:netrw_local_mkdir
46  elseif executable("mkdir")
47   let g:vimball_mkdir= "mkdir"
48  elseif executable("makedir")
49   let g:vimball_mkdir= "makedir"
50  endif
51  if !exists(g:vimball_mkdir)
52   call vimball#ShowMesg(s:WARNING,"(vimball) g:vimball_mkdir undefined")
53  endif
54 endif
55
56 " set up shell quoting character
57 if exists("g:vimball_shq") && !exists("g:netrw_shq")
58  let g:netrw_shq= g:vimball_shq
59 endif
60 if !exists("g:netrw_shq")
61  if exists("&shq") && &shq != ""
62   let g:netrw_shq= &shq
63  elseif has("win32") || has("win95") || has("win64") || has("win16")
64   if g:netrw_cygwin
65    let g:netrw_shq= "'"
66   else
67    let g:netrw_shq= '"'
68   endif
69  else
70   let g:netrw_shq= "'"
71  endif
72" call Decho("g:netrw_shq<".g:netrw_shq.">")
73 endif
74
75 " set up escape string (used to protect paths)
76 if !exists("g:vimball_path_escape")
77  let g:vimball_path_escape= ' ;#%'
78 endif
79endif
80
81" =====================================================================
82"  Functions: {{{1
83
84" ---------------------------------------------------------------------
85" vimball#MkVimball: creates a vimball given a list of paths to files {{{2
86" Input:
87"     line1,line2: a range of lines containing paths to files to be included in the vimball
88"     writelevel : if true, force a write to filename.vba, even if it exists
89"                  (usually accomplished with :MkVimball! ...
90"     filename   : base name of file to be created (ie. filename.vba)
91" Output: a filename.vba using vimball format:
92"     path
93"     filesize
94"     [file]
95"     path
96"     filesize
97"     [file]
98fun! vimball#MkVimball(line1,line2,writelevel,...) range
99"  call Dfunc("MkVimball(line1=".a:line1." line2=".a:line2." writelevel=".a:writelevel." vimballname<".a:1.">) a:0=".a:0)
100  if a:1 =~ '\.vim$' || a:1 =~ '\.txt$'
101   let vbname= substitute(a:1,'\.\a\{3}$','.vba','')
102  else
103   let vbname= a:1
104  endif
105  if vbname !~ '\.vba$'
106   let vbname= vbname.'.vba'
107  endif
108"  call Decho("vbname<".vbname.">")
109  if a:1 =~ '[\/]'
110   call vimball#ShowMesg(s:ERROR,"(MkVimball) vimball name<".a:1."> should not include slashes")
111"   call Dret("MkVimball : vimball name<".a:1."> should not include slashes")
112   return
113  endif
114  if !a:writelevel && filereadable(vbname)
115   call vimball#ShowMesg(s:ERROR,"(MkVimball) file<".vbname."> exists; use ! to insist")
116"   call Dret("MkVimball : file<".vbname."> already exists; use ! to insist")
117   return
118  endif
119
120  " user option bypass
121  call vimball#SaveSettings()
122
123  if a:0 >= 2
124   " allow user to specify where to get the files
125   let home= expand(a:2)
126  else
127   " use first existing directory from rtp
128   let home= s:VimballHome()
129  endif
130
131  " save current directory
132  let curdir = getcwd()
133  call s:ChgDir(home)
134
135  " record current tab, initialize while loop index
136  let curtabnr = tabpagenr()
137  let linenr   = a:line1
138"  call Decho("curtabnr=".curtabnr)
139
140  while linenr <= a:line2
141   let svfile  = getline(linenr)
142"   call Decho("svfile<".svfile.">")
143
144   if !filereadable(svfile)
145    call vimball#ShowMesg(s:ERROR,"unable to read file<".svfile.">")
146	call s:ChgDir(curdir)
147	call vimball#RestoreSettings()
148"    call Dret("MkVimball")
149    return
150   endif
151
152   " create/switch to mkvimball tab
153   if !exists("vbtabnr")
154    tabnew
155    silent! file Vimball
156    let vbtabnr= tabpagenr()
157   else
158    exe "tabn ".vbtabnr
159   endif
160
161   let lastline= line("$") + 1
162   if lastline == 2 && getline("$") == ""
163	call setline(1,'" Vimball Archiver by Charles E. Campbell, Jr., Ph.D.')
164	call setline(2,'UseVimball')
165	call setline(3,'finish')
166	let lastline= line("$") + 1
167   endif
168   call setline(lastline  ,substitute(svfile,'$','	[[[1',''))
169   call setline(lastline+1,0)
170
171   " write the file from the tab
172   let svfilepath= s:Path(svfile,'')
173"   call Decho("exe $r ".fnameescape(svfilepath))
174   exe "$r ".fnameescape(svfilepath)
175
176   call setline(lastline+1,line("$") - lastline - 1)
177"   call Decho("lastline=".lastline." line$=".line("$"))
178
179  " restore to normal tab
180   exe "tabn ".curtabnr
181   let linenr= linenr + 1
182  endwhile
183
184  " write the vimball
185  exe "tabn ".vbtabnr
186  call s:ChgDir(curdir)
187  setlocal ff=unix
188  if a:writelevel
189   let vbnamepath= s:Path(vbname,'')
190"   call Decho("exe w! ".fnameescape(vbnamepath))
191   exe "w! ".fnameescape(vbnamepath)
192  else
193   let vbnamepath= s:Path(vbname,'')
194"   call Decho("exe w ".fnameescape(vbnamepath))
195   exe "w ".fnameescape(vbnamepath)
196  endif
197"  call Decho("Vimball<".vbname."> created")
198  echo "Vimball<".vbname."> created"
199
200  " remove the evidence
201  setlocal nomod bh=wipe
202  exe "tabn ".curtabnr
203  exe "tabc ".vbtabnr
204
205  " restore options
206  call vimball#RestoreSettings()
207
208"  call Dret("MkVimball")
209endfun
210
211" ---------------------------------------------------------------------
212" vimball#Vimball: extract and distribute contents from a vimball {{{2
213"                  (invoked the the UseVimball command embedded in
214"                  vimballs' prologue)
215fun! vimball#Vimball(really,...)
216"  call Dfunc("vimball#Vimball(really=".a:really.") a:0=".a:0)
217
218  if v:version < 701 || (v:version == 701 && !has("patch299"))
219   echoerr "This version of vimball requires vim 7.1 with patch 299"
220"   call Dret("vimball#Vimball : needs 7.1 with patch 299")
221   return
222  endif
223
224  if getline(1) !~ '^" Vimball Archiver by Charles E. Campbell, Jr., Ph.D.$'
225   echoerr "(Vimball) The current file does not appear to be a Vimball!"
226"   call Dret("vimball#Vimball")
227   return
228  endif
229
230  " set up standard settings
231  call vimball#SaveSettings()
232  let curtabnr    = tabpagenr()
233  let vimballfile = expand("%:tr")
234
235  " set up vimball tab
236"  call Decho("setting up vimball tab")
237  tabnew
238  silent! file Vimball
239  let vbtabnr= tabpagenr()
240  let didhelp= ""
241
242  " go to vim plugin home
243  if a:0 > 0
244   let home= expand(a:1)
245  else
246   let home= s:VimballHome()
247  endif
248"  call Decho("home<".home.">")
249
250  " save current directory and remove older same-named vimball, if any
251  let curdir = getcwd()
252"  call Decho("home<".home.">")
253"  call Decho("curdir<".curdir.">")
254
255  call s:ChgDir(home)
256  let s:ok_unablefind= 1
257  call vimball#RmVimball(vimballfile)
258  unlet s:ok_unablefind
259
260  let linenr  = 4
261  let filecnt = 0
262
263  " give title to listing of (extracted) files from Vimball Archive
264  if a:really
265   echohl Title     | echomsg "Vimball Archive"         | echohl None
266  else
267   echohl Title     | echomsg "Vimball Archive Listing" | echohl None
268   echohl Statement | echomsg "files would be placed under: ".home | echohl None
269  endif
270
271  " apportion vimball contents to various files
272"  call Decho("exe tabn ".curtabnr)
273  exe "tabn ".curtabnr
274"  call Decho("linenr=".linenr." line$=".line("$"))
275  while 1 < linenr && linenr < line("$")
276   let fname   = substitute(getline(linenr),'\t\[\[\[1$','','')
277   let fname   = substitute(fname,'\\','/','g')
278   let fsize   = getline(linenr+1)+0
279   let filecnt = filecnt + 1
280"   call Decho("fname<".fname."> fsize=".fsize." filecnt=".filecnt)
281
282   if a:really
283    echomsg "extracted <".fname.">: ".fsize." lines"
284   else
285    echomsg "would extract <".fname.">: ".fsize." lines"
286   endif
287"   call Decho("using L#".linenr.": will extract file<".fname.">")
288"   call Decho("using L#".(linenr+1).": fsize=".fsize)
289
290   " Allow AsNeeded/ directory to take place of plugin/ directory
291   " when AsNeeded/filename is filereadable or was present in VimballRecord
292   if fname =~ '\<plugin/'
293   	let anfname= substitute(fname,'\<plugin/','AsNeeded/','')
294	if filereadable(anfname) || (exists("s:VBRstring") && s:VBRstring =~ anfname)
295"	 call Decho("using anfname<".anfname."> instead of <".fname.">")
296	 let fname= anfname
297	endif
298   endif
299
300   " make directories if they don't exist yet
301   if a:really
302"    call Decho("making directories if they don't exist yet (fname<".fname.">)")
303    let fnamebuf= substitute(fname,'\\','/','g')
304	let dirpath = substitute(home,'\\','/','g')
305    while fnamebuf =~ '/'
306     let dirname  = dirpath."/".substitute(fnamebuf,'/.*$','','')
307	 let dirpath  = dirname
308     let fnamebuf = substitute(fnamebuf,'^.\{-}/\(.*\)$','\1','')
309"	 call Decho("dirname<".dirname.">")
310     if !isdirectory(dirname)
311"      call Decho("making <".dirname.">")
312      if exists("g:vimball_mkdir")
313	   call system(g:vimball_mkdir." ".s:Escape(dirname))
314      else
315       call mkdir(dirname)
316      endif
317	  call s:RecordInVar(home,"rmdir('".dirname."')")
318     endif
319    endwhile
320   endif
321   call s:ChgDir(home)
322
323   " grab specified qty of lines and place into "a" buffer
324   " (skip over path/filename and qty-lines)
325   let linenr   = linenr + 2
326   let lastline = linenr + fsize - 1
327"   call Decho("exe ".linenr.",".lastline."yank a")
328   exe "silent ".linenr.",".lastline."yank a"
329
330   " copy "a" buffer into tab
331"   call Decho('copy "a buffer into tab#'.vbtabnr)
332   exe "tabn ".vbtabnr
333   setlocal ma
334   silent! %d
335   silent put a
336   1
337   silent d
338
339   " write tab to file
340   if a:really
341    let fnamepath= s:Path(home."/".fname,'')
342"    call Decho("exe w! ".fnameescape(fnamepath))
343	exe "silent w! ".fnameescape(fnamepath)
344    echo "wrote ".fnamepath
345	call s:RecordInVar(home,"call delete('".fnameescape(fnamepath)."')")
346   endif
347
348   " return to tab with vimball
349"   call Decho("exe tabn ".curtabnr)
350   exe "tabn ".curtabnr
351
352   " set up help if its a doc/*.txt file
353"   call Decho("didhelp<".didhelp."> fname<".fname.">")
354   if a:really && didhelp == "" && fname =~ 'doc/[^/]\+\.\(txt\|..x\)$'
355   	let didhelp= substitute(fname,'^\(.*\<doc\)[/\\][^.]*\.\(txt\|..x\)$','\1','')
356"	call Decho("didhelp<".didhelp.">")
357   endif
358
359   " update for next file
360"   call Decho("update linenr= [linenr=".linenr."] + [fsize=".fsize."] = ".(linenr+fsize))
361   let linenr= linenr + fsize
362  endwhile
363
364  " set up help
365"  call Decho("about to set up help: didhelp<".didhelp.">")
366  if didhelp != ""
367   let htpath= s:Path(home."/".didhelp,"")
368"   call Decho("exe helptags ".htpath)
369   exe "helptags ".htpath
370   echo "did helptags"
371  endif
372
373  " make sure a "Press ENTER..." prompt appears to keep the messages showing!
374  while filecnt <= &ch
375   echomsg " "
376   let filecnt= filecnt + 1
377  endwhile
378
379  " record actions in <.VimballRecord>
380  call s:RecordInFile(home)
381
382  " restore events, delete tab and buffer
383  exe "tabn ".vbtabnr
384  setlocal nomod bh=wipe
385  exe "tabn ".curtabnr
386  exe "tabc ".vbtabnr
387  call vimball#RestoreSettings()
388  call s:ChgDir(curdir)
389
390"  call Dret("vimball#Vimball")
391endfun
392
393" ---------------------------------------------------------------------
394" vimball#RmVimball: remove any files, remove any directories made by any {{{2
395"               previous vimball extraction based on a file of the current
396"               name.
397"  Usage:  RmVimball  (assume current file is a vimball; remove)
398"          RmVimball vimballname
399fun! vimball#RmVimball(...)
400"  call Dfunc("vimball#RmVimball() a:0=".a:0)
401  if exists("g:vimball_norecord")
402"   call Dret("vimball#RmVimball : (g:vimball_norecord)")
403   return
404  endif
405
406  if a:0 == 0
407   let curfile= expand("%:tr")
408"   call Decho("case a:0=0: curfile<".curfile."> (used expand(%:tr))")
409  else
410   if a:1 =~ '[\/]'
411    call vimball#ShowMesg(s:USAGE,"RmVimball vimballname [path]")
412"    call Dret("vimball#RmVimball : suspect a:1<".a:1.">")
413    return
414   endif
415   let curfile= a:1
416"   call Decho("case a:0=".a:0.": curfile<".curfile.">")
417  endif
418  if curfile =~ '\.vba$'
419   let curfile= substitute(curfile,'\.vba','','')
420  endif
421  if a:0 >= 2
422   let home= expand(a:2)
423  else
424   let home= s:VimballHome()
425  endif
426  let curdir = getcwd()
427"  call Decho("home   <".home.">")
428"  call Decho("curfile<".curfile.">")
429"  call Decho("curdir <".curdir.">")
430
431  call s:ChgDir(home)
432  if filereadable(".VimballRecord")
433"   call Decho(".VimballRecord is readable")
434"   call Decho("curfile<".curfile.">")
435   keepalt keepjumps 1split
436   silent! keepalt keepjumps e .VimballRecord
437   let keepsrch= @/
438"   call Decho("search for ^".curfile.".vba:")
439"   call Decho("search for ^".curfile."[-0-9.]*.vba:")
440   if search('^'.curfile.": ".'cw')
441	let foundit= 1
442   elseif search('^'.curfile.".vba: ",'cw')
443	let foundit= 1
444   elseif search('^'.curfile.'[-0-9.]*.vba: ','cw')
445	let foundit= 1
446   else
447    let foundit = 0
448   endif
449   if foundit
450	let exestring  = substitute(getline("."),'^'.curfile.'\S\{-}\.vba: ','','')
451    let s:VBRstring= substitute(exestring,'call delete(','','g')
452    let s:VBRstring= substitute(s:VBRstring,"[')]",'','g')
453"	call Decho("exe ".exestring)
454	silent! keepalt keepjumps exe exestring
455	silent! keepalt keepjumps d
456	let exestring= strlen(substitute(exestring,'call delete(.\{-})|\=',"D","g"))
457"	call Decho("exestring<".exestring.">")
458	echomsg "removed ".exestring." files"
459   else
460    let s:VBRstring= ''
461	let curfile    = substitute(curfile,'\.vba','','')
462"    call Decho("unable to find <".curfile."> in .VimballRecord")
463	if !exists("s:ok_unablefind")
464     call vimball#ShowMesg(s:WARNING,"(RmVimball) unable to find <".curfile."> in .VimballRecord")
465	endif
466   endif
467   silent! keepalt keepjumps g/^\s*$/d
468   silent! keepalt keepjumps wq!
469   let @/= keepsrch
470  endif
471  call s:ChgDir(curdir)
472
473"  call Dret("vimball#RmVimball")
474endfun
475
476" ---------------------------------------------------------------------
477" vimball#Decompress: attempts to automatically decompress vimballs {{{2
478fun! vimball#Decompress(fname)
479"  call Dfunc("Decompress(fname<".a:fname.">)")
480
481  " decompression:
482  if     expand("%") =~ '.*\.gz'  && executable("gunzip")
483   " handle *.gz with gunzip
484   silent exe "!gunzip ".s:Escape(a:fname)
485   if v:shell_error != 0
486	call vimball#ShowMesg(s:WARNING,"(vimball#Decompress) gunzip may have failed with <".a:fname.">")
487   endif
488   let fname= substitute(a:fname,'\.gz$','','')
489   exe "e ".escape(fname,' \')
490   call vimball#ShowMesg(s:USAGE,"Source this file to extract it! (:so %)")
491
492  elseif expand("%") =~ '.*\.gz' && executable("gzip")
493   " handle *.gz with gzip -d
494   silent exe "!gzip -d ".s:Escape(a:fname)
495   if v:shell_error != 0
496	call vimball#ShowMesg(s:WARNING,'(vimball#Decompress) "gzip -d" may have failed with <'.a:fname.">")
497   endif
498   let fname= substitute(a:fname,'\.gz$','','')
499   exe "e ".escape(fname,' \')
500   call vimball#ShowMesg(s:USAGE,"Source this file to extract it! (:so %)")
501
502  elseif expand("%") =~ '.*\.bz2' && executable("bunzip2")
503   " handle *.bz2 with bunzip2
504   silent exe "!bunzip2 ".s:Escape(a:fname)
505   if v:shell_error != 0
506	call vimball#ShowMesg(s:WARNING,"(vimball#Decompress) bunzip2 may have failed with <".a:fname.">")
507   endif
508   let fname= substitute(a:fname,'\.bz2$','','')
509   exe "e ".escape(fname,' \')
510   call vimball#ShowMesg(s:USAGE,"Source this file to extract it! (:so %)")
511
512  elseif expand("%") =~ '.*\.bz2' && executable("bzip2")
513   " handle *.bz2 with bzip2 -d
514   silent exe "!bzip2 -d ".s:Escape(a:fname)
515   if v:shell_error != 0
516	call vimball#ShowMesg(s:WARNING,'(vimball#Decompress) "bzip2 -d" may have failed with <'.a:fname.">")
517   endif
518   let fname= substitute(a:fname,'\.bz2$','','')
519   exe "e ".escape(fname,' \')
520   call vimball#ShowMesg(s:USAGE,"Source this file to extract it! (:so %)")
521
522  elseif expand("%") =~ '.*\.zip' && executable("unzip")
523   " handle *.zip with unzip
524   silent exe "!unzip ".s:Escape(a:fname)
525   if v:shell_error != 0
526	call vimball#ShowMesg(s:WARNING,"(vimball#Decompress) unzip may have failed with <".a:fname.">")
527   endif
528   let fname= substitute(a:fname,'\.zip$','','')
529   exe "e ".escape(fname,' \')
530   call vimball#ShowMesg(s:USAGE,"Source this file to extract it! (:so %)")
531  endif
532
533  set noma bt=nofile fmr=[[[,]]] fdm=marker
534
535"  call Dret("Decompress")
536endfun
537
538" ---------------------------------------------------------------------
539" vimball#ShowMesg: {{{2
540fun! vimball#ShowMesg(level,msg)
541"  call Dfunc("vimball#ShowMesg(level=".a:level." msg<".a:msg.">)")
542  let rulerkeep   = &ruler
543  let showcmdkeep = &showcmd
544  set noruler noshowcmd
545  redraw!
546
547  if &fo =~ '[ta]'
548   echomsg "***vimball*** " a:msg
549  else
550   if a:level == s:WARNING || a:level == s:USAGE
551    echohl WarningMsg
552   elseif a:level == s:ERROR
553    echohl Error
554   endif
555   echomsg "***vimball*** " a:msg
556   echohl None
557  endif
558
559  if a:level != s:USAGE
560   call inputsave()|let ok= input("Press <cr> to continue")|call inputrestore()
561  endif
562
563  let &ruler   = rulerkeep
564  let &showcmd = showcmdkeep
565
566"  call Dret("vimball#ShowMesg")
567endfun
568" =====================================================================
569" s:ChgDir: change directory (in spite of Windoze) {{{2
570fun! s:ChgDir(newdir)
571"  call Dfunc("ChgDir(newdir<".a:newdir.">)")
572  if (has("win32") || has("win95") || has("win64") || has("win16"))
573   exe 'silent cd '.fnameescape(substitute(a:newdir,'/','\\','g'))
574  else
575   exe 'silent cd '.fnameescape(a:newdir)
576  endif
577"  call Dret("ChgDir : curdir<".getcwd().">")
578endfun
579
580" ---------------------------------------------------------------------
581" s:Path: prepend and append quotes and do escaping {{{2
582fun! s:Path(cmd,quote)
583"  call Dfunc("Path(cmd<".a:cmd."> quote<".a:quote.">) vimball_path_escape<".g:vimball_path_escape.">")
584  if (has("win32") || has("win95") || has("win64") || has("win16"))
585"   let cmdpath= a:quote.substitute(a:cmd,'/','\\','g').a:quote
586   let cmdpath= a:quote.substitute(a:cmd,'\\','/','g').a:quote
587"   call Decho("cmdpath<".cmdpath."> (win32 mod)")
588  else
589   let cmdpath= a:quote.a:cmd.a:quote
590"   call Decho("cmdpath<".cmdpath."> (not-win32 mod)")
591  endif
592  if a:quote == "" && g:vimball_path_escape !~ ' '
593   let cmdpath= escape(cmdpath,' ')
594"   call Decho("cmdpath<".cmdpath."> (empty quote case)")
595  endif
596  let cmdpath= escape(cmdpath,g:vimball_path_escape)
597"  call Dret("Path <".cmdpath.">")
598  return cmdpath
599endfun
600
601" ---------------------------------------------------------------------
602" s:RecordInVar: record a un-vimball command in the .VimballRecord file {{{2
603fun! s:RecordInVar(home,cmd)
604"  call Dfunc("RecordInVar(home<".a:home."> cmd<".a:cmd.">)")
605  if a:cmd =~ '^rmdir'
606"   if !exists("s:recorddir")
607"    let s:recorddir= substitute(a:cmd,'^rmdir',"call s:Rmdir",'')
608"   else
609"    let s:recorddir= s:recorddir."|".substitute(a:cmd,'^rmdir',"call s:Rmdir",'')
610"   endif
611  elseif !exists("s:recordfile")
612   let s:recordfile= a:cmd
613  else
614   let s:recordfile= s:recordfile."|".a:cmd
615  endif
616"  call Dret("RecordInVar : s:recordfile<".(exists("s:recordfile")? s:recordfile : "")."> s:recorddir<".(exists("s:recorddir")? s:recorddir : "").">")
617endfun
618
619" ---------------------------------------------------------------------
620" s:RecordInFile: {{{2
621fun! s:RecordInFile(home)
622"  call Dfunc("s:RecordInFile()")
623  if exists("g:vimball_norecord")
624"   call Dret("s:RecordInFile : g:vimball_norecord")
625   return
626  endif
627
628  if exists("s:recordfile") || exists("s:recorddir")
629   let curdir= getcwd()
630   call s:ChgDir(a:home)
631   keepalt keepjumps 1split
632
633   let cmd= expand("%:tr").": "
634"   call Decho("cmd<".cmd.">")
635
636   silent! keepalt keepjumps e .VimballRecord
637   setlocal ma
638   $
639   if exists("s:recordfile") && exists("s:recorddir")
640   	let cmd= cmd.s:recordfile."|".s:recorddir
641   elseif exists("s:recorddir")
642   	let cmd= cmd.s:recorddir
643   elseif exists("s:recordfile")
644   	let cmd= cmd.s:recordfile
645   else
646"    call Dret("s:RecordInFile : neither recordfile nor recorddir exist")
647	return
648   endif
649"   call Decho("cmd<".cmd.">")
650
651   " put command into buffer, write .VimballRecord `file
652   keepalt keepjumps put=cmd
653   silent! keepalt keepjumps g/^\s*$/d
654   silent! keepalt keepjumps wq!
655   call s:ChgDir(curdir)
656
657   if exists("s:recorddir")
658"	call Decho("unlet s:recorddir<".s:recorddir.">")
659   	unlet s:recorddir
660   endif
661   if exists("s:recordfile")
662"	call Decho("unlet s:recordfile<".s:recordfile.">")
663   	unlet s:recordfile
664   endif
665  else
666"   call Decho("s:record[file|dir] doesn't exist")
667  endif
668
669"  call Dret("s:RecordInFile")
670endfun
671
672" ---------------------------------------------------------------------
673" s:VimballHome: determine/get home directory path (usually from rtp) {{{2
674fun! s:VimballHome()
675"  call Dfunc("VimballHome()")
676  if exists("g:vimball_home")
677   let home= g:vimball_home
678  else
679   " go to vim plugin home
680   for home in split(&rtp,',') + ['']
681    if isdirectory(home) && filewritable(home) | break | endif
682	let basehome= substitute(home,'[/\\]\.vim$','','')
683    if isdirectory(basehome) && filewritable(basehome)
684	 let home= basehome."/.vim"
685	 break
686	endif
687   endfor
688   if home == ""
689    " just pick the first directory
690    let home= substitute(&rtp,',.*$','','')
691   endif
692   if (has("win32") || has("win95") || has("win64") || has("win16"))
693    let home= substitute(home,'/','\\','g')
694   endif
695  endif
696  " insure that the home directory exists
697"  call Decho("picked home<".home.">")
698  if !isdirectory(home)
699   if exists("g:vimball_mkdir")
700"	call Decho("home<".home."> isn't a directory -- making it now with g:vimball_mkdir<".g:vimball_mkdir.">")
701"    call Decho("system(".g:vimball_mkdir." ".s:Escape(home).")")
702    call system(g:vimball_mkdir." ".s:Escape(home))
703   else
704"	call Decho("home<".home."> isn't a directory -- making it now with mkdir()")
705    call mkdir(home)
706   endif
707  endif
708"  call Dret("VimballHome <".home.">")
709  return home
710endfun
711
712" ---------------------------------------------------------------------
713" vimball#SaveSettings: {{{2
714fun! vimball#SaveSettings()
715"  call Dfunc("SaveSettings()")
716  let s:makeep  = getpos("'a")
717  let s:regakeep= @a
718  if exists("&acd")
719   let s:acdkeep = &acd
720  endif
721  let s:eikeep  = &ei
722  let s:fenkeep = &fen
723  let s:hidkeep = &hidden
724  let s:ickeep  = &ic
725  let s:lzkeep  = &lz
726  let s:pmkeep  = &pm
727  let s:repkeep = &report
728  let s:vekeep  = &ve
729  let s:ffkeep  = &ff
730  if exists("&acd")
731   setlocal ei=all ve=all noacd nofen noic report=999 nohid bt= ma lz pm= ff=unix
732  else
733   setlocal ei=all ve=all       nofen noic report=999 nohid bt= ma lz pm= ff=unix
734  endif
735  " vimballs should be in unix format
736  setlocal ff=unix
737"  call Dret("SaveSettings")
738endfun
739
740" ---------------------------------------------------------------------
741" vimball#RestoreSettings: {{{2
742fun! vimball#RestoreSettings()
743"  call Dfunc("RestoreSettings()")
744  let @a      = s:regakeep
745  if exists("&acd")
746   let &acd   = s:acdkeep
747  endif
748  let &fen    = s:fenkeep
749  let &hidden = s:hidkeep
750  let &ic     = s:ickeep
751  let &lz     = s:lzkeep
752  let &pm     = s:pmkeep
753  let &report = s:repkeep
754  let &ve     = s:vekeep
755  let &ei     = s:eikeep
756  let &ff     = s:ffkeep
757  if s:makeep[0] != 0
758   " restore mark a
759"   call Decho("restore mark-a: makeep=".string(makeep))
760   call setpos("'a",s:makeep)
761  endif
762  if exists("&acd")
763   unlet s:acdkeep
764  endif
765  unlet s:regakeep s:eikeep s:fenkeep s:hidkeep s:ickeep s:repkeep s:vekeep s:makeep s:lzkeep s:pmkeep s:ffkeep
766"  call Dret("RestoreSettings")
767endfun
768
769" ---------------------------------------------------------------------
770" s:Escape: {{{2
771fun s:Escape(name)
772  " shellescape() was added by patch 7.0.111
773  if exists("*shellescape")
774    return shellescape(a:name)
775  endif
776  return g:netrw_shq . a:name . g:netrw_shq
777endfun
778
779" ---------------------------------------------------------------------
780"  Restore:
781let &cpo= s:keepcpo
782unlet s:keepcpo
783
784" ---------------------------------------------------------------------
785" Modelines: {{{1
786" vim: fdm=marker
787