2 " Author: Chris Russell
7 " This script defineds functions and key mappings to block comment code.
10 " In brief, use '.c' to comment and '.C' to uncomment.
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
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.
20 " Simply drop this file into your plugin directory.
33 "--------------------------------------------------
34 " Avoid multiple sourcing
35 "--------------------------------------------------
36 if exists( "loaded_block_comment" )
39 let loaded_block_comment = 1
42 "--------------------------------------------------
44 "--------------------------------------------------
45 noremap <silent> .c :call Comment()<CR>
46 noremap <silent> .C :call UnComment()<CR>
49 "--------------------------------------------------
50 " Set comment characters by filetype
51 "--------------------------------------------------
52 function! CommentStr()
53 let s:comment_pad = '--------------------------------------------------'
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
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
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 = '-- >'
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
109 "--------------------------------------------------
110 " Comment a block of code
111 "--------------------------------------------------
112 function! Comment() range
114 let l:firstln = a:firstline
115 let l:lastln = a:lastline
118 " get tab indent level
119 let l:indent = indent( l:firstln ) / &tabstop
120 " loop to get padding str
124 let l:pad = l:pad . "\t"
129 let l:midline = l:firstln
130 while l:midline <= l:lastln
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
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
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" )
149 call setline( l:midline, l:pad . s:comment_mid0 . l:line )
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
157 let l:midline = l:midline + 1
161 call append( l:lastln, l:pad . s:comment_mid1 . s:comment_pad . s:comment_stop )
163 " return to first line of comment
167 "--------------------------------------------------
168 " Uncomment a block of code
169 "--------------------------------------------------
170 function! UnComment() range
172 let l:firstln = a:firstline
173 let l:lastln = a:lastline
176 " get length of comment string
177 let l:clen = strlen( s:comment_mid0 )
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" )
203 call setline( l:midline, l:pad . l:line )
205 let l:midline = l:midline + 1
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
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 )