summaryrefslogtreecommitdiff
path: root/runtime/plugin/tar.vim
blob: 26fade4d275e10fbe498bffcab53b1b79dbf578c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
" vim:set ts=4 sw=4 ai nobackup:

" tar.vim -- a vim plugin for browsing tarfiles
" Copyright (c) 2002, Michael C. Toren <mct@toren.net>
"
" Updates are available from <http://michael.toren.net/code/>.  If you
" find this script useful, or have suggestions for improvements, please
" let me know.
"
" Usage:
" Once this script is installed, attempting to edit a tarfile will present
" the user with a list of files contained in the tar archive.  By moving the
" cursor over a filename and pressing ENTER, the contents of a file can be
" viewed in read-only mode, in a new window.  Unfortunately, write support
" for tarfile components is not currently possible.
" 
" Requirements:
" GNU tar, or a tar implementation that supports the "P" (don't strip
" out leading /'s from filenames), and "O" (extract files to standard
" output) options.  Additionally, gzip is required for handling *.tar.Z,
" *.tar.gz, and *.tgz compressed tarfiles, and bzip2 is required for
" handling *.tar.bz2 compressed tarfiles.  A unix-like operating system
" is probably also required.
" 
" Installation:
" Place this file, tar.vim, in your $HOME/.vim/plugin directory, and
" either restart vim, or execute ":source $HOME/.vim/plugin/tar.vim"
"
" Todo:
" - Handle zipfiles?
" - Implement write support, somehow.
"
" License:
" This program is free software; you can redistribute it and/or modify it
" under the terms of the GNU General Public License, version 2, as published
" by the Free Software Foundation.
"
" This program is distributed in the hope that it will be useful, but
" WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
" or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
" for more details.
"
" A copy of the GNU GPL is available as /usr/doc/copyright/GPL on Debian
" systems, or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html
" You can also obtain it by writing to the Free Software Foundation, Inc.,
" 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
"
" Changelog:
" Tue Dec 31 13:38:08 EST 2002	First release to beta testers
" Sat Jan  4 14:06:19 EST 2003	Version 1.00 released

let s:version = "1.00"

if has("autocmd")
augroup tar
	au!
	au BufReadCmd	tarfile:*	call s:TarRead(expand("<afile>"), 1)
	au BufReadCmd	tarfile:*/*	call s:TarRead(expand("<afile>"), 1)
	au FileReadCmd	tarfile:*	call s:TarRead(expand("<afile>"), 0)
	au FileReadCmd	tarfile:*/*	call s:TarRead(expand("<afile>"), 0)

	au BufWriteCmd	tarfile:*	call s:TarWrite(expand("<afile>"))
	au BufWriteCmd	tarfile:*/*	call s:TarWrite(expand("<afile>"))
	au FileWriteCmd	tarfile:*	call s:TarWrite(expand("<afile>"))
	au FileWriteCmd	tarfile:*/*	call s:TarWrite(expand("<afile>"))

	au BufReadCmd	*.tar		call s:TarBrowse(expand("<afile>"))
	au BufReadCmd	*.tar.gz	call s:TarBrowse(expand("<afile>"))
	au BufReadCmd	*.tar.bz2	call s:TarBrowse(expand("<afile>"))
	au BufReadCmd	*.tar.Z		call s:TarBrowse(expand("<afile>"))
	au BufReadCmd	*.tgz		call s:TarBrowse(expand("<afile>"))
augroup END
endif

function! s:TarWrite(argument)
	echo "ERROR: Sorry, no write support for tarfiles yet"
endfunction

function! s:TarRead(argument, cleanup)
	let l:argument = a:argument
	let l:argument = substitute(l:argument, '^tarfile:', '', '')
	let l:argument = substitute(l:argument, '^\~', $HOME, '')

	let l:tarfile = l:argument
	while 1
		if (l:tarfile == "" || l:tarfile == "/")
			echo "ERROR: Could not find a readable tarfile in path:" l:argument
			return
		endif

		if filereadable(l:tarfile) " found it!
			break
		endif

		let l:tarfile = fnamemodify(l:tarfile, ":h")
	endwhile

	let l:toextract = strpart(l:argument, strlen(l:tarfile) + 1)

	if (l:toextract == "")
		return
	endif

	let l:cat = s:TarCatCommand(l:tarfile)
	execute "r !" . l:cat . " < '" . l:tarfile . "'"
		\ " | tar OPxf - '" . l:toextract . "'"

	if (a:cleanup)
		0d "blank line
		execute "doautocmd BufReadPost " . expand("%")
		setlocal readonly
		silent preserve
	endif
endfunction

function! s:TarBrowse(tarfile)
	setlocal noswapfile
	setlocal buftype=nofile
	setlocal bufhidden=hide
	setlocal filetype=
	setlocal nobuflisted
	setlocal buftype=nofile
	setlocal wrap

	let l:tarfile = a:tarfile
	let b:tarfile = l:tarfile
	let l:cat = s:TarCatCommand(l:tarfile)

	if ! filereadable(l:tarfile)
		let l:tarfile = substitute(l:tarfile, '^tarfile:', '', '')
	endif

	if ! filereadable(l:tarfile)
		echo "ERROR: File not readable:" l:tarfile
		return
	endif

	call s:Say("\" tar.vim version " . s:version)
	call s:Say("\" Browsing tarfile " . l:tarfile)
	call s:Say("\" Hit ENTER to view contents in new window")
	call s:Say("")

	silent execute "r!" . l:cat . "<'" . l:tarfile . "'| tar Ptf - "
	0d "blank line
	/^$/1

	setlocal readonly
	setlocal nomodifiable
	noremap <silent> <buffer> <cr> :call <SID>TarBrowseSelect()<cr>
endfunction

function! s:TarBrowseSelect()
	let l:line = getline(".")

	if (l:line =~ '^" ')
		return
	endif

	if (l:line =~ '/$')
		echo "Please specify a file, not a directory"
		return
	endif

	let l:selection = "tarfile:" .  b:tarfile . "/" . l:line
	new
	wincmd _
	execute "e " . l:selection
endfunction

" kludge to deal with compressed archives
function! s:TarCatCommand(tarfile)
	if a:tarfile =~# '\.\(gz\|tgz\|Z\)$'
		let l:cat = "gzip -d -c"
	elseif a:tarfile =~# '\.bz2$'
		let l:cat = "bzip2 -d -c"
	else
		let l:cat = "cat"
	endif
	return l:cat
endfunction

function! s:Say(string)
	let @" = a:string
	$ put
endfunction