165bb148b7ae24dffd0ef964bc4f63bf70b08a35
[~madcoder/dotfiles.git] / vim / plugin / BlockComment.vim
1 " BlockComment.vim
2 " Author: Chris Russell
3 " Version: 1.1
4 " License: GPL v2.0 
5
6 " Description:
7 " This script defineds functions and key mappings to block comment code.
8
9 " Help: 
10 " In brief, use '.c' to comment and '.C' to uncomment.
11
12 " Both commenting and uncommenting can be run on N lines at a time by 
13 " using a number before the command.  They both support visual mode and 
14 " ranges.
15
16 " This script will not comment lines with an indent level less that the 
17 " initial line of the comment to preserve the control structure of code.
18 "
19 " Installation:
20 " Simply drop this file into your plugin directory.
21
22 " Changelog:
23 " 2002-11-08 v1.1
24 "       Convert to Unix eol
25 " 2002-11-05 v1.0
26 "       Initial release
27
28 " TODO:
29 " Add more file types
30
31
32
33 "--------------------------------------------------
34 " Avoid multiple sourcing
35 "-------------------------------------------------- 
36 if exists( "loaded_block_comment" )
37         finish
38 endif
39 let loaded_block_comment = 1
40
41
42 "--------------------------------------------------
43 " Key mappings
44 "-------------------------------------------------- 
45 noremap <silent> .c :call Comment()<CR>
46 noremap <silent> .C :call UnComment()<CR>
47
48
49 "--------------------------------------------------
50 " Set comment characters by filetype
51 "-------------------------------------------------- 
52 function! CommentStr()
53         let s:comment_pad = '--------------------------------------------------'
54         if &ft == "vim"
55                 let s:comment_strt = '"'
56                 let s:comment_mid0 = '" '
57                 let s:comment_mid1 = '"'
58                 let s:comment_stop = ' '
59                 let s:comment_bkup = 0
60         elseif &ft == "c" || &ft == "css"
61                 let s:comment_strt = '/*'
62                 let s:comment_mid0 = '* '
63                 let s:comment_mid1 = '*'
64                 let s:comment_stop = '*/'
65                 let s:comment_bkup = 1
66                 let s:comment_strtbak = '/ *'
67                 let s:comment_stopbak = '* /'
68         elseif &ft == "cpp" || &ft == "java" || &ft == "javascript" || &ft == "php"
69                 let s:comment_strt = '//'
70                 let s:comment_mid0 = '// '
71                 let s:comment_mid1 = '//'
72                 let s:comment_stop = ' '
73                 let s:comment_bkup = 0
74         elseif &ft == "tex"
75                 let s:comment_strt = '%'
76                 let s:comment_mid0 = '% '
77                 let s:comment_mid1 = '%'
78                 let s:comment_stop = ' '
79                 let s:comment_bkup = 0
80         elseif &ft == "asm" || &ft == "lisp" || &ft == "scheme"
81                 let s:comment_strt = ';'
82                 let s:comment_mid0 = '; '
83                 let s:comment_mid1 = ';'
84                 let s:comment_stop = ' '
85                 let s:comment_bkup = 0
86         elseif &ft == "vb"
87                 let s:comment_strt = '\''
88                 let s:comment_mid0 = '\' '
89                 let s:comment_mid1 = '\''
90                 let s:comment_stop = ' '
91                 let s:comment_bkup = 0
92         elseif &ft == "html" || &ft == "xml" || &ft == "entity"
93                 let s:comment_strt = '<!--'
94                 let s:comment_mid0 = '! '
95                 let s:comment_mid1 = '!'
96                 let s:comment_stop = '-->'
97                 let s:comment_bkup = 1
98                 let s:comment_strtbak = '< !--'
99                 let s:comment_stopbak = '-- >'
100         else
101                 let s:comment_strt = '#'
102                 let s:comment_mid0 = '# '
103                 let s:comment_mid1 = '#'
104                 let s:comment_stop = ' '
105                 let s:comment_bkup = 0
106         endif
107 endfunction
108
109 "--------------------------------------------------
110 " Comment a block of code
111 "-------------------------------------------------- 
112 function! Comment() range
113         " range variables
114         let l:firstln = a:firstline
115         let l:lastln = a:lastline
116         " get comment chars
117         call CommentStr()
118         " get tab indent level
119         let l:indent = indent( l:firstln ) / &tabstop
120         " loop to get padding str
121         let l:pad = ""
122         let l:i = 0
123         while l:i < l:indent
124                 let l:pad = l:pad . "\t"
125                 let l:i = l:i + 1
126         endwhile
127         " loop for each line
128         let l:block = 0
129         let l:midline = l:firstln
130         while l:midline <= l:lastln
131                 " get line
132                 let l:line = getline( l:midline )
133                 " check if padding matches
134                 if strpart( l:line, 0, l:indent ) == l:pad
135                         " start comment block
136                         if l:block == 0
137                                 call append( l:midline - 1, l:pad . s:comment_strt . s:comment_pad )
138                                 let l:midline = l:midline + 1
139                                 let l:lastln = l:lastln + 1
140                                 let l:block = 1
141                         endif
142                         " append comment between indent and code
143                         let l:line = strpart( l:line, l:indent )
144                         " handle comments within comments
145                         if s:comment_bkup == 1
146                                 let l:line = substitute( l:line, escape( s:comment_strt, '\*^$.~[]' ), s:comment_strtbak, "g" )
147                                 let l:line = substitute( l:line, escape( s:comment_stop, '\*^$.~[]' ), s:comment_stopbak, "g" )
148                         endif
149                         call setline( l:midline, l:pad . s:comment_mid0 . l:line )
150                 " else end block
151                 elseif l:block == 1
152                         call append( l:midline - 1, l:pad . s:comment_mid1 . s:comment_pad . s:comment_stop )
153                         let l:midline = l:midline + 1
154                         let l:lastln = l:lastln + 1
155                         let l:block = 0
156                 endif
157                 let l:midline = l:midline + 1
158         endwhile
159         " end block
160         if l:block == 1
161                 call append( l:lastln, l:pad . s:comment_mid1 . s:comment_pad . s:comment_stop )
162         endif
163         " return to first line of comment
164         execute l:firstln
165 endfunction
166
167 "--------------------------------------------------
168 " Uncomment a block of code
169 "-------------------------------------------------- 
170 function! UnComment() range
171         " range variables
172         let l:firstln = a:firstline
173         let l:lastln = a:lastline
174         " get comment chars
175         call CommentStr()
176         " get length of comment string
177         let l:clen = strlen( s:comment_mid0 )
178         " loop for each line
179         let l:midline = l:firstln
180         while l:midline <= l:lastln
181                 " get indent level - process indent for each line instead of by block
182                 let l:indent = indent( l:midline ) / &tabstop
183                 let l:line = getline( l:midline )
184                 " begin comment block line - delete line
185                 if strpart( l:line, l:indent ) == s:comment_strt . s:comment_pad
186                         execute l:midline . "d"
187                         let l:midline = l:midline - 1
188                         let l:lastln = l:lastln - 1 
189                 " end comment block line - delete line
190                 elseif strpart( l:line, l:indent ) == s:comment_mid1 . s:comment_pad . s:comment_stop
191                         execute l:midline . "d"
192                         let l:midline = l:midline - 1
193                         let l:lastln = l:lastln - 1
194                 " commented code line - remove comment
195                 elseif strpart( l:line, l:indent, l:clen ) == s:comment_mid0
196                         let l:pad = strpart( l:line, 0, l:indent )
197                         let l:line = strpart( l:line, l:indent + l:clen )
198                         " handle comments within comments
199                         if s:comment_bkup == 1
200                                 let l:line = substitute( l:line, escape( s:comment_strtbak, '\*^$.~[]' ), s:comment_strt, "g" )
201                                 let l:line = substitute( l:line, escape( s:comment_stopbak, '\*^$.~[]' ), s:comment_stop, "g" )
202                         endif
203                         call setline( l:midline, l:pad . l:line )
204                 endif
205                 let l:midline = l:midline + 1
206         endwhile
207         " look at line above block
208         let l:indent = indent( l:firstln - 1 ) / &tabstop
209         let l:line = getline( l:firstln - 1 )
210         " abandoned begin comment block line - delete line
211         if strpart( l:line, l:indent ) == s:comment_strt . s:comment_pad
212                 execute ( l:firstln - 1 ) . "d"
213                 let l:firstln = l:firstln - 1
214                 let l:lastln = l:lastln - 1
215         " abandoned commented code line - insert end comment block line
216         elseif strpart( l:line, l:indent, l:clen ) == s:comment_mid0
217                 let l:pad = strpart( l:line, 0, l:indent )
218                 call append( l:firstln - 1, l:pad . s:comment_mid1 . s:comment_pad . s:comment_stop )
219                 let l:lastln = l:lastln + 1
220         endif
221         " look at line belowe block
222         let l:indent = indent( l:lastln + 1 ) / &tabstop
223         let l:line = getline( l:lastln + 1 )
224         " abandoned end comment block line - delete line
225         if strpart( l:line, l:indent ) == s:comment_mid1 . s:comment_pad . s:comment_stop
226                 execute ( l:lastln + 1 ) . "d"
227                 let l:lastln = l:lastln - 1
228         " abandoned commented code line - insert begin comment block line
229         elseif strpart( l:line, l:indent, l:clen ) == s:comment_mid0
230                 let l:pad = strpart( l:line, 0, l:indent )
231                 call append( l:lastln, l:pad . s:comment_strt . s:comment_pad )
232         endif
233 endfunction
234