]> ruderich.org/simon Gitweb - config/dotfiles.git/blob - vim/vim/bundle/deb/autoload/deb.vim
vim: deb: sync with current version in Debian sid
[config/dotfiles.git] / vim / vim / bundle / deb / autoload / deb.vim
1 " Vim autoload file for browsing debian package.
2 " copyright (C) 2007-2008, arno renevier <arenevier@fdn.fr>
3 " Distributed under the GNU General Public License (version 2 or above)
4 " Last Change: 2008 april 1
5
6 " Inspired by autoload/tar.vim by Charles E Campbell
7 "
8 " Latest version of that file can be found at
9 " http://www.fdn.fr/~arenevier/vim/autoload/deb.vim
10 " It should also be available at
11 " http://www.vim.org/scripts/script.php?script_id=1970
12
13 if &cp || exists("g:loaded_deb") || v:version < 700
14     finish
15 endif
16 let g:loaded_deb= "v1.4"
17
18 fun! deb#read(debfile, member)
19
20     " checks if ar and tar are installed
21     if !s:hascmd("ar") || !s:hascmd("tar")
22         return
23     endif
24
25     let l:target = a:member
26
27     let l:archmember = s:dataFileName(a:debfile) " default archive member to extract
28     if l:archmember == ""
29         echohl WarningMsg | echo "***error*** (deb#read) no valid data file found in debian archive"
30         return
31     elseif l:archmember == "data.tar.gz"
32         let l:unpcmp = "tar zxfO "
33     elseif l:archmember == "data.tar.bz2"
34         let l:unpcmp = "tar jxfO "
35     elseif l:archmember == "data.tar.xz"
36         let l:unpcmp = "tar JxfO "
37     elseif l:archmember == "data.tar.lzma"
38         if !s:hascmd("lzma")
39             return
40         endif
41         let l:unpcmp = "lzma -d | tar xfO "
42     elseif l:archmember == "data.tar"
43         let l:unpcmp = "tar xfO "
44     endif
45
46     if a:member =~ '^\* ' " information control file
47         let l:archmember = "control.tar.gz"
48         let l:target = substitute(l:target, "^\* ", "", "")
49         let l:unpcmp = "tar zxfO "
50     elseif a:member =~ ' -> ' " symbolic link
51         let l:target = split(a:member,' -> ')[0]
52         let l:linkname = split(a:member,' -> ')[1]
53
54         if l:linkname =~ "^\/" " direct symlink: path is already absolute
55             let l:target = ".".l:linkname
56
57         else 
58         " transform relative path to absolute path
59
60             " first, get basename for target
61             let l:target = substitute(l:target, "\/[^/]*$", "", "")
62
63             " while it begins with ../
64             while l:linkname =~ "^\.\.\/" 
65
66                 " removes one level of ../ in linkname
67                 let l:linkname = substitute(l:linkname, "^\.\.\/", "", "")
68
69                 " go one directory up in target
70                 let l:target = substitute(l:target, "\/[^/]*$", "", "")
71             endwhile
72
73             let l:target = l:target."/".l:linkname
74         endif
75     endif
76     
77     " we may preprocess some files (such as man pages, or changelogs)
78     let l:preproccmd = ""
79         
80     "
81     " unzip man pages
82     "
83     if l:target =~ "\.\/usr\/share\/man\/.*\.gz$"
84         
85         " try to fail gracefully if a command is not available
86         if !s:hascmd("gzip")
87             return
88         elseif !s:hascmd("nroff") 
89             let l:preproccmd = "| gzip -cd"
90         elseif !s:hascmd("col")
91             let l:preproccmd = "| gzip -cd | nroff -mandoc"
92         else
93             let l:preproccmd = "| gzip -cd | nroff -mandoc | col -b"
94         endif
95     
96     "
97     " unzip other .gz files
98     "
99     elseif l:target =~ '.*\.gz$'
100         if !s:hascmd("gzip")
101             return
102         endif
103         let l:preproccmd = "| gzip -cd"
104     endif
105
106     " read content
107     exe "silent r! ar p " . s:QuoteFile(a:debfile) . " " . s:QuoteFile(l:archmember) . " | " . l:unpcmp . " - " . s:QuoteFile(l:target) . l:preproccmd
108     " error will be treated in calling function
109     if v:shell_error != 0
110         return
111     endif
112
113     exe "file deb:".l:target
114
115     0d
116
117     setlocal nomodifiable nomodified readonly
118
119 endfun
120
121 fun! deb#browse(file)
122
123     " checks if necessary utils are installed
124     if !s:hascmd("dpkg") || !s:hascmd("ar") || !s:hascmd("tar")
125         return
126     endif
127
128     " checks if file is readable
129     if !filereadable(a:file)
130         return
131     endif
132     if a:file =~ "'"
133         echohl WarningMsg | echo "***error*** (deb#Browse) filename cannot contain quote character (" . a:file . ")"
134         return
135     endif
136
137     let keepmagic = &magic
138     set magic
139
140     " set filetype to "deb"
141     set ft=deb
142
143     setlocal modifiable noreadonly
144
145     " set header
146     exe "$put ='".'\"'." deb.vim version ".g:loaded_deb."'"
147     exe "$put ='".'\"'." Browsing debian package ".a:file."'"
148     $put=''
149
150     " package info
151     "exe "silent read! dpkg -I ".a:file
152     "$put=''
153
154     " display information control files
155     let l:infopos = line(".")
156     exe "silent read! ar p " . s:QuoteFile(a:file) . " control.tar.gz | tar zt"
157
158     $put=''
159
160     " display data files
161     let l:listpos = line(".")
162     exe "silent read! dpkg -c ". s:QuoteFile(a:file)
163
164     " format information control list
165     " removes '* ./' line
166     exe (l:infopos + 1). 'd'
167     " add a star before each line
168     exe "silent " . (l:infopos + 1). ',' . (l:listpos - 2) . 's/^/\* /'
169     
170     " format data list
171     exe "silent " . l:listpos . ',$s/^.*\s\(\.\/\(\S\|\).*\)$/\1/'
172     
173     if v:shell_error != 0
174         echohl WarningMsg | echo "***warning*** (deb#Browse) error when listing content of " . a:file
175         let &magic = keepmagic
176         return
177     endif
178
179     0d
180
181     setlocal nomodifiable readonly
182     noremap <silent> <buffer> <cr> :call <SID>DebBrowseSelect()<cr>
183     let &magic = keepmagic
184
185 endfun
186
187 fun! s:DebBrowseSelect()
188     let l:fname= getline(".")
189
190     " sanity check
191     if (l:fname !~ '^\.\/') && (l:fname !~ '^\* \.\/')
192         return
193     endif
194     if l:fname =~ "'"
195         echohl WarningMsg | echo "***error*** (DebBrowseSelect) filename cannot contain quote character (" . l:fname . ")"
196         return
197     endif
198
199     " do nothing on directories
200     " TODO: find a way to detect symlinks to directories, to be able not to
201     " open them
202     if (l:fname =~ '\/$')
203         return
204     endif
205
206     " need to get it now since a new window will open
207     let l:curfile= expand("%")
208    
209     " open new window
210     new
211     wincmd _
212
213     call deb#read(l:curfile, l:fname)
214
215     if v:shell_error != 0
216         echohl WarningMsg | echo "***warning*** (DebBrowseSelect) error when reading " . l:fname
217         return
218     endif
219
220     filetype detect
221
222     " zipped files, are unziped in deb#read, but filetype may not
223     " automatically work.
224     if l:fname =~ "\.\/usr\/share\/man\/.*\.gz$"
225         set filetype=man
226     elseif l:fname =~ "\.\/usr\/share\/doc\/.*\/changelog.Debian.gz$"
227         set filetype=debchangelog
228     endif
229
230 endfun
231
232 " return data file name for debian package. This can be either data.tar.gz,
233 " data.tar.bz2 or data.tar.lzma
234 fun s:dataFileName(deb)
235     for fn in ["data.tar.gz", "data.tar.bz2", "data.tar.lzma", "data.tar.xz", "data.tar"]
236         " [0:-2] is to remove trailing null character from command output
237         if (system("ar t " . "'" . a:deb . "'" . " " . fn))[0:-2] == fn
238             return fn
239         endif
240     endfor
241     return "" " no debian data format in this archive
242 endfun
243
244 fun s:QuoteFile(file)
245     " we need to escape %, #, <, and >
246     " see :help cmdline-specialk
247     return "'" .  substitute(a:file, '\([%#<>]\)', '\\\1', 'g') . "'"
248 endfun
249
250 " return 1 if cmd exists
251 " display error message and return 0 otherwise
252 fun s:hascmd(cmd)
253     if executable(a:cmd)
254         return 1
255     else
256         echohl Error | echo "***error*** " . a:cmd . " not available on your system"
257         return 0
258     else
259 endfu
260