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