1 " EnhancedCommentify.vim
2 " Maintainer: Meikel Brandmeyer <Brandels_Mikesh@web.de>
4 " Last Change: Wednesday, February 20th, 2008
7 " Copyright (c) 2008 Meikel Brandmeyer, Frankfurt am Main
10 " Redistribution and use in source and binary form are permitted provided
11 " that the following conditions are met:
13 " 1. Redistribition of source code must retain the above copyright
14 " notice, this list of conditions and the following disclaimer.
16 " 2. Redistributions in binary form must reproduce the above copyright
17 " notice, this list of conditions and the following disclaimer in the
18 " documentation and/or other materials provided with the distribution.
20 " THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS "AS IS" AND
21 " ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 " IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 " ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
24 " FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 " DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 " OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 " HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 " LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 " OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 " This is a (well... more or less) simple script to comment lines in a program.
34 " Currently supported languages are C, C++, PHP, the vim scripting
35 " language, python, HTML, Perl, LISP, Tex, Shell, CAOS and others.
39 " Fixed type 'apacha' -> 'apache' (thanks to Brian Neu)
40 " Fixed nested comment escapes strings. (thanks to Samuel Ferencik)
41 " Fixed broken keyboard mappings when wcm was set to <Tab>.
42 " (thanks to xpatriotx)
44 " Fixed problem with UseSyntax (thanks to Pieter Naaijkens)
45 " Fixed typo in ParseCommentsOp (commstr -> commStr).
46 " Fixed support for ocaml (thanks to Zhang Le)
48 " Fixed problems with alignement when a line contains tabs
49 " Fixed (resp. cleaned up) issues with overrideEL (thanks to Steve Hall)
50 " Fixed problems with javascript detection (thanks to Brian Neu)
51 " Changed Buffer init to BufWinEnter in order to use the modelines.
53 " Fixed invalid expression '\'' -> "'" (thanks to Zak Beck)
54 " Setting AltOpen/AltClose to '' (ie. disabling it) would
55 " insert '/*' resp. '*/' for character in a line (thanks to Ben Kibbey)
57 " Backslashes in comment symbols should not be escaped.
58 " typo (commensSymbol -> commentSymbol) (thanks to Steve Butts)
60 " Fixed hardwired '|+'-'+|' pair.
62 " Lines were not correctly decommentified, when there was whitespace
63 " at the beginning of the line. (thanks to Xiangjiang Ma)
64 " Fixed error detecting '*sh' filetypes.
66 " hlsearch was set unconditionally (thanks to Mary Ellen Foster)
67 " made function silent (thanks to Mare Ellen Foster)
71 " Added support for viki/deplate (thanks to Thomas Link)
72 " Added support for xslt/xsd/mail (thanks to Stefano Zacchiroli)
73 " Added callback-functionality to enable extensions without the
74 " need of modification directly in the script.
76 " Added possibility to override the modes, in which keybindings are
78 " Keybindings may be defined local to every buffer now.
79 " If a filetype is unknown, one can turn off the keybindings now.
81 " Removed any cursor movement. The script should now be free of
83 " The script now uses &commentstring to determine the right
84 " comment strings. Fallback is still the ugly if-thingy.
85 " Script can now interpret &comments in order to add a middle
87 " Added EnhancedCommentifySet for use by other scripts. (Necessary?)
88 " Added MultiPartBlocks for languages with multipart-comments.
89 " Added parsing for comments option if using MultiPartBlocks.
91 " IMPORTANT: EnhancedCommentify is now licensed under BSD license
92 " for distribution with Cream! However this shouldn't
94 " useBlockIndent does no longer depend on respectIndent.
95 " Added code to cope with 'C' in '&cpo'. (thanks to Luc Hermitte
96 " for pointing this out!)
97 " Added EnhCommentifyIdentFrontOnly option.
98 " All options are now handled on a per buffer basis. So options
99 " can be overriden for different buffers.
101 " Filetype is now recognized via regular expressions.
102 " All known filetypes are (more or less) supported.
103 " Decomments multipart-block comments.
104 " Added RespectIndent, AlignRight and synID-guessing.
105 " Switched to buffer variables.
107 " Added Ada support. (thanks to Preben Randhol)
108 " Added Latte support.
109 " Added blocksupport and possibility to specify action (comment or
110 " decomment). It's also possible to guess the action line by line or
111 " using the first line of a block.
112 " Thanks to Xiangjiang Ma and John Orr for the rich feedback on these
114 " Decomments /*foo();*/, when PrettyComments is set.
115 " Added 'vhdl' and 'verilog'. (thanks to Steve Butts)
117 " Added different options to control behaviour of the plugin.
118 " Changed default Keybindings to proper plugin settings.
120 " Now supports 'm4', 'config', 'automake'
121 " 'vb', 'aspvbs', 'plsql' (thanks to Zak Beck)
123 " Now supports 'java', 'xml', 'jproperties'. (thanks to Scott Stirling)
125 " Lines containing only whitespace are now considered empty.
127 " Multipart comments are now escaped with configurable alternative
128 " strings. Prevents nesting errors (eg. /**/*/ in C)
130 " Doesn't break lines like
132 " when doing commentify.
135 " Simply drop this file into your $HOME/.vim/plugin directory.
137 if exists("DidEnhancedCommentify")
140 let DidEnhancedCommentify = 1
142 let s:savedCpo = &cpo
145 " Note: These must be defined here, since they are used during
148 " InitBooleanVariable(confVar, scriptVar, defaultVal)
149 " confVar -- name of the configuration variable
150 " scriptVar -- name of the variable to set
151 " defaultVal -- default value
153 " Tests on existence of configuration variable and sets scriptVar
154 " according to its contents.
156 function s:InitBooleanVariable(confVar, scriptVar, defaultVal)
157 let regex = a:defaultVal ? 'no*' : 'ye*s*'
159 if exists(a:confVar) && {a:confVar} =~? regex
160 let {a:scriptVar} = !a:defaultVal
162 let {a:scriptVar} = a:defaultVal
167 " InitStringVariable(confVar, scriptVar, defaultVal)
168 " confVar -- name of the configuration variable
169 " scriptVar -- name of the variable to set
170 " defaultVal -- default value
172 " Tests on existence of configuration variable and sets scriptVar
175 function s:InitStringVariable(confVar, scriptVar, defaultVal)
177 execute "let ". a:scriptVar ." = ". a:confVar
179 let {a:scriptVar} = a:defaultVal
184 " InitScriptVariables(nameSpace)
185 " nameSpace -- may be "g" for global or "b" for local
187 " Initialises the script variables.
189 function s:InitScriptVariables(nameSpace)
190 let ns = a:nameSpace " just for abbreviation
191 let lns = (ns == "g") ? "s" : "b" " 'local namespace'
193 " Comment escape strings...
194 call s:InitStringVariable(ns .":EnhCommentifyAltOpen", lns .":ECaltOpen",
196 call s:InitStringVariable(ns .":EnhCommentifyAltClose", lns .":ECaltClose",
199 call s:InitBooleanVariable(ns .":EnhCommentifyIgnoreWS", lns .":ECignoreWS",
202 " Adding a space between comment strings and code...
203 if exists(ns .":EnhCommentifyPretty")
204 if {ns}:EnhCommentifyPretty =~? 'ye*s*'
205 let {lns}:ECprettyComments = ' '
206 let {lns}:ECprettyUnComments = ' \='
208 let {lns}:ECprettyComments = ''
209 let {lns}:ECprettyUnComments = ''
212 let {lns}:ECprettyComments = s:ECprettyComments
213 let {lns}:ECprettyUnComments = s:ECprettyUnComments
216 " Identification string settings...
217 call s:InitStringVariable(ns .":EnhCommentifyIdentString",
218 \ lns .":ECidentFront", s:ECidentFront)
219 let {lns}:ECidentBack =
220 \ (exists(ns .":EnhCommentifyIdentFrontOnly")
221 \ && {ns}:EnhCommentifyIdentFrontOnly =~? 'ye*s*')
223 \ : {lns}:ECidentFront
225 " Wether to use syntax items...
226 call s:InitBooleanVariable(ns .":EnhCommentifyUseSyntax",
227 \ lns .":ECuseSyntax", s:ECuseSyntax)
229 " Should the script respect line indentation, when inserting strings?
230 call s:InitBooleanVariable(ns .":EnhCommentifyRespectIndent",
231 \ lns .":ECrespectIndent", s:ECrespectIndent)
234 call s:InitBooleanVariable(ns .":EnhCommentifyUseAltKeys",
235 \ lns .":ECuseAltKeys", s:ECuseAltKeys)
236 call s:InitBooleanVariable(ns .":EnhCommentifyBindPerBuffer",
237 \ lns .":ECbindPerBuffer", s:ECbindPerBuffer)
238 call s:InitBooleanVariable(ns .":EnhCommentifyBindInNormal",
239 \ lns .":ECbindInNormal", s:ECbindInNormal)
240 call s:InitBooleanVariable(ns .":EnhCommentifyBindInInsert",
241 \ lns .":ECbindInInsert", s:ECbindInInsert)
242 call s:InitBooleanVariable(ns .":EnhCommentifyBindInVisual",
243 \ lns .":ECbindInVisual", s:ECbindInVisual)
244 call s:InitBooleanVariable(ns .":EnhCommentifyUserBindings",
245 \ lns .":ECuserBindings", s:ECuserBindings)
246 call s:InitBooleanVariable(ns .":EnhCommentifyTraditionalMode",
247 \ lns .":ECtraditionalMode", s:ECtraditionalMode)
248 call s:InitBooleanVariable(ns .":EnhCommentifyFirstLineMode",
249 \ lns .":ECfirstLineMode", s:ECfirstLineMode)
250 call s:InitBooleanVariable(ns .":EnhCommentifyUserMode",
251 \ lns .":ECuserMode", s:ECuserMode)
252 call s:InitBooleanVariable(ns .":EnhCommentifyBindUnknown",
253 \ lns .":ECbindUnknown", s:ECbindUnknown)
256 call s:InitBooleanVariable(ns .":EnhCommentifyAlignRight",
257 \ lns .":ECalignRight", s:ECalignRight)
258 call s:InitBooleanVariable(ns .":EnhCommentifyUseBlockIndent",
259 \ lns .":ECuseBlockIndent", s:ECuseBlockIndent)
260 call s:InitBooleanVariable(ns .":EnhCommentifyMultiPartBlocks",
261 \ lns .":ECuseMPBlock", s:ECuseMPBlock)
262 call s:InitBooleanVariable(ns .":EnhCommentifyCommentsOp",
263 \ lns .":ECuseCommentsOp", s:ECuseCommentsOp)
265 let {lns}:ECsaveWhite = ({lns}:ECrespectIndent
266 \ || {lns}:ECignoreWS || {lns}:ECuseBlockIndent)
270 if !{lns}:ECrespectIndent
271 let {lns}:ECuseBlockIndent = 0
274 if {lns}:ECrespectIndent
275 let {lns}:ECrespectWhite = '\1'
276 let {lns}:ECignoreWhite = ''
277 elseif {lns}:ECignoreWS
278 let {lns}:ECrespectWhite = ''
279 let {lns}:ECignoreWhite = '\1'
281 let {lns}:ECrespectWhite = ''
282 let {lns}:ECignoreWhite = ''
285 " Using comments option, doesn't make sense without useMPBlock
286 "if lns == 'b' && b:ECuseCommentsOp
287 " let b:ECuseMPBlock = 1
292 " EnhancedCommentifySet(option, value, ...)
293 " option -- which option
294 " value -- value which will be asigned to the option
296 " The purpose of this function is mainly to act as an interface to the
297 " outer world. It hides the internally used variables.
299 function EnhancedCommentifySet(option, value)
300 if a:option == 'AltOpen'
301 let oldval = b:ECaltOpen
302 let b:ECaltOpen = a:value
303 elseif a:option == 'AltClose'
304 let oldval = b:ECaltClose
305 let b:ECaltClose = a:value
306 elseif a:option == 'IdentString'
307 let oldval = b:ECidentFront
308 let b:ECidentFront = a:value
309 elseif a:option == 'IdentFrontOnly'
310 let oldval = (b:ECidentBack == '') ? 'Yes' : 'No'
311 let b:ECidentBack = (a:value =~? 'ye*s*') ? '' : b:ECidentFront
312 elseif a:option == 'RespectIndent'
313 let oldval = b:ECrespectIndent
314 let b:ECrespectIndent = (a:value =~? 'ye*s*') ? 1 : 0
315 elseif a:option == 'IgnoreWS'
316 let oldval = b:ECignoreWS
317 let b:ECignoreWS = (a:value =~? 'ye*s*') ? 1 : 0
318 elseif a:option == 'Pretty'
319 let oldval = (b:ECprettyComments == ' ') ? 'Yes' : 'No'
320 if a:value =~? 'ye*s*'
321 let b:ECprettyComments = ' '
322 let b:ECprettyUnComments = ' \='
324 let b:ECprettyComments = ''
325 let b:ECprettyUnComments = ''
327 elseif a:option == 'MultiPartBlocks'
328 let oldval = b:ECuseMPBlock
329 let b:ECuseMPBlock = (a:value =~? 'ye*s*') ? 1 : 0
330 elseif a:option == 'CommentsOp'
331 let oldval = b:ECuseCommentsOp
332 let b:ECuseCommentsOp = (a:value =~? 'ye*s*') ? 1 : 0
333 elseif a:option == 'UseBlockIndent'
334 let oldval = b:ECuseBlockIndent
335 let b:ECuseBlockIndent = (a:value =~? 'ye*s*') ? 1 : 0
336 elseif a:option == 'AlignRight'
337 let oldval = b:ECalignRight
338 let b:ECalignRight = (a:value =~? 'ye*s*') ? 1 : 0
339 elseif a:option == 'UseSyntax'
340 let oldval = b:ECuseSyntax
341 let b:ECuseSyntax = (a:value =~? 'ye*s*') ? 1 : 0
343 if (has("dialog_gui") && has("gui_running"))
344 call confirm("EnhancedCommentifySet: Unknwon option '"
348 echo "EnhancedCommentifySet: Unknown option '". option ."'"
364 " Setting the default options resp. taking user preferences.
365 if !exists("g:EnhCommentifyUserMode")
366 \ && !exists("g:EnhCommentifyFirstLineMode")
367 \ && !exists("g:EnhCommentifyTraditionalMode")
368 \ && !exists("g:EnhCommentifyUserBindings")
369 let g:EnhCommentifyTraditionalMode = 'Yes'
372 " These will be the default settings for the script:
373 let s:ECaltOpen = "|+"
374 let s:ECaltClose = "+|"
376 let s:ECprettyComments = ''
377 let s:ECprettyUnComments = ''
378 let s:ECidentFront = ''
379 let s:ECuseSyntax = 0
380 let s:ECrespectIndent = 0
381 let s:ECalignRight = 0
382 let s:ECuseBlockIndent = 0
383 let s:ECuseMPBlock = 0
384 let s:ECuseCommentsOp = 0
385 let s:ECuseAltKeys = 0
386 let s:ECbindPerBuffer = 0
387 let s:ECbindInNormal = 1
388 let s:ECbindInInsert = 1
389 let s:ECbindInVisual = 1
390 let s:ECuserBindings = 0
391 let s:ECtraditionalMode = 0
392 let s:ECfirstLineMode = 0
394 let s:ECbindUnknown = 1
396 " Now initialise the global defaults with the preferences set
397 " by the user in his .vimrc. Settings local to a buffer will be
398 " done later on, when the script is first called in a buffer.
400 call s:InitScriptVariables("g")
402 " Globally used variables with some initialisation.
403 " FIXME: explain what they are good for
405 let s:Action = 'guess'
406 let s:firstOfBlock = 1
407 let s:blockAction = 'comment'
408 let s:blockIndentRegex = ''
409 let s:blockIndent = 0
411 let s:tabConvert = ''
412 let s:overrideEmptyLines = 0
413 let s:emptyLines = 'no'
416 function EnhancedCommentifyInitBuffer()
417 if !exists("b:ECdidBufferInit")
418 call s:InitScriptVariables("b")
420 if !exists("b:EnhCommentifyFallbackTest")
421 let b:EnhCommentifyFallbackTest = 0
424 call s:GetFileTypeSettings(&ft)
425 call s:CheckPossibleEmbedding(&ft)
428 " If the filetype is not supported and the user wants us to, we do not
432 if b:ECcommentOpen != "" || b:ECbindUnknown
433 call s:SetKeybindings("l")
437 let b:ECdidBufferInit = 1
442 autocmd BufWinEnter,BufNewFile * call EnhancedCommentifyInitBuffer()
445 " EnhancedCommentify(emptyLines, action, ...)
446 " overrideEL -- commentify empty lines
447 " may be 'yes', 'no' or '' for guessing
448 " action -- action which should be executed:
450 " toggle commetification (old behaviour)
456 " use first line of block to determine action
457 " a:1, a:2 -- first and last line of block, which should be
460 " Commentifies the current line.
462 function EnhancedCommentify(overrideEL, action, ...)
463 if a:overrideEL != ''
464 let s:overrideEmptyLines = 1
467 " Now do the buffer initialisation. Every buffer will get
468 " it's pendant to a global variable (eg. s:ECalignRight -> b:ECalignRight).
469 " The local variable is actually used, whereas the global variable
470 " holds the defaults from the user's .vimrc. In this way the settings
471 " can be overriden for single buffers.
473 " NOTE: Buffer init is done by autocommands now.
476 let b:ECemptyLines = a:overrideEL
478 " The language is not supported.
479 if b:ECcommentOpen == ''
480 if (has("dialog_gui") && has("gui_running"))
481 call confirm("This filetype is currently _not_ supported!\n"
482 \ ."Please consider contacting the author in order"
483 \ ." to add this filetype.", "", 1, "Error")
486 echo "This filetype is currently _not_ supported!"
487 echo "Please consider contacting the author in order to add"
488 echo "this filetype in future releases!"
496 " Now some initialisations...
497 let s:Action = a:action
499 " FIXME: Is there really _no_ function to simplify this???
500 " (Maybe something like 'let foo = 8x" "'?)
501 if s:tabConvert == '' && strlen(s:tabConvert) != &tabstop
502 let s:tabConvert = ''
505 let s:tabConvert = s:tabConvert .' '
511 let s:startBlock = a:1
517 let s:startBlock = lnum
519 let s:endBlock = lnum
524 if b:ECuseSyntax && b:ECpossibleEmbedding
525 let column = indent(s:startBlock) + 1
527 let rem = column % &tabstop
528 let column = ((column - rem) / &tabstop) + rem
530 call s:CheckSyntax(s:startBlock, column)
533 " Get the indent of the less indented line of the block.
534 if s:inBlock && (b:ECuseBlockIndent || b:ECalignRight)
535 call s:DoBlockComputations(s:startBlock, s:endBlock)
538 while s:i <= s:endBlock
539 let lineString = getline(s:i)
540 let lineString = s:TabsToSpaces(lineString)
542 " If we should comment "empty" lines, we have to add
543 " the correct indent, if we use blockIndent.
544 if b:ECemptyLines =~? 'ye*s*'
545 \ && b:ECuseBlockIndent
546 \ && lineString =~ "^\s*$"
548 while i < s:blockIndent
549 let lineString = " " . lineString
554 " Don't comment empty lines.
555 if lineString !~ "^\s*$"
556 \ || b:ECemptyLines =~? 'ye*s*'
557 if b:ECcommentClose != ''
558 let lineString = s:CommentifyMultiPart(lineString,
563 let lineString = s:CommentifySinglePart(lineString,
568 " Revert the above: If the line is "empty" and we
569 " used blockIndent, we remove the spaces.
570 " FIXME: Why does "^\s*$" not work?
571 if b:ECemptyLines =~? 'ye*s*'
572 \ && b:ECuseBlockIndent
573 \ && lineString =~ "^" . s:blockIndentRegex ."\s*$"
575 \ substitute(lineString, s:blockIndentRegex,
579 let lineString = s:SpacesToTabs(lineString)
580 call setline(s:i, lineString)
583 let s:firstOfBlock = 0
586 let s:firstOfBlock = 1
590 " DoBlockComputations(start, end)
591 " start -- number of first line
592 " end -- number of last line
594 " This function does some computations which are necessary for useBlockIndent
595 " and alignRight. ie. find smallest indent and longest line.
597 function s:DoBlockComputations(start, end)
600 let amount = 100000 " this should be enough ...
603 if b:ECuseBlockIndent && getline(i) !~ '^\s*$'
611 let cur = s:GetLineLen(s:TabsToSpaces(getline(i)),
612 \ s:GetLineLen(b:ECcommentOpen, 0)
613 \ + strlen(b:ECprettyComments))
615 let cur = cur + s:GetLineLen(b:ECcommentOpen, 0)
616 \ + strlen(b:ECprettyComments)
627 if b:ECuseBlockIndent
629 let regex = '\( \{'. amount .'}\)'
633 let s:blockIndentRegex = regex
634 let s:blockIndent = amount
643 " CheckSyntax(line, column)
644 " line -- line of line
645 " column -- column of line
646 " Check what syntax is active during call of main function. First hit
647 " wins. If the filetype changes during the block, we ignore that.
648 " Adjust the filetype if necessary.
650 function s:CheckSyntax(line, column)
652 let synFiletype = synIDattr(synID(a:line, a:column, 1), "name")
654 " FIXME: This feature currently relies on a certain format
655 " of the names of syntax items: the filetype must be prepended
656 " in lowwer case letters, followed by at least one upper case
658 if match(synFiletype, '\l\+\u') == 0
659 let ft = substitute(synFiletype, '^\(\l\+\)\u.*$', '\1', "")
663 execute "let specialCase = ". b:EnhCommentifyFallbackTest
666 let ft = b:EnhCommentifyFallbackValue
668 " Fallback: If nothing holds, use normal filetype!
679 call s:GetFileTypeSettings(ft)
683 " GetFileTypeSettings(ft)
686 " This functions sets some buffer-variables, which control the comment
687 " strings and 'empty lines'-handling.
689 function s:GetFileTypeSettings(ft)
692 " If we find nothing appropriate this is the default.
693 let b:ECcommentOpen = ''
694 let b:ECcommentClose = ''
696 if exists("g:EnhCommentifyCallbackExists")
697 call EnhCommentifyCallback(fileType)
699 " Check whether the callback did yield a result.
700 " If so we use it. The user nows, what he's doing.
701 if b:ECcommentOpen != ''
706 " I learned about the commentstring option. Let's use it.
707 " For now we ignore it, if it is "/*%s*/". This is the
708 " default. We cannot check wether this is default or C or
709 " something other like CSS, etc. We have to wait, until the
710 " filetypes adopt this option.
711 if &commentstring != "/*%s*/" && !b:ECuseSyntax
712 let b:ECcommentOpen =
713 \ substitute(&commentstring, '%s.*', "", "")
714 let b:ECcommentClose =
715 \ substitute(&commentstring, '.*%s', "", "")
716 " Multipart comments:
717 elseif fileType =~ '^\(c\|b\|css\|csc\|cupl\|indent\|jam\|lex\|lifelines\|'.
718 \ 'lite\|nqc\|phtml\|progress\|rexx\|rpl\|sas\|sdl\|sl\|'.
719 \ 'strace\|xpm\|yacc\)$'
720 let b:ECcommentOpen = '/*'
721 let b:ECcommentClose = '*/'
722 elseif fileType =~ '^\(html\|xhtml\|xml\|xslt\|xsd\|dtd\|sgmllnx\)$'
723 let b:ECcommentOpen = '<!--'
724 let b:ECcommentClose = '-->'
725 elseif fileType =~ '^\(sgml\|smil\)$'
726 let b:ECcommentOpen = '<!'
727 let b:ECcommentClose = '>'
728 elseif fileType == 'atlas'
729 let b:ECcommentOpen = 'C'
730 let b:ECcommentClose = '$'
731 elseif fileType =~ '^\(catalog\|sgmldecl\)$'
732 let b:ECcommentOpen = '--'
733 let b:ECcommentClose = '--'
734 elseif fileType == 'dtml'
735 let b:ECcommentOpen = '<dtml-comment>'
736 let b:ECcommentClose = '</dtml-comment>'
737 elseif fileType == 'htmlos'
738 let b:ECcommentOpen = '#'
739 let b:ECcommentClose = '/#'
740 elseif fileType =~ '^\(jgraph\|lotos\|mma\|modula2\|modula3\|pascal\|'.
742 let b:ECcommentOpen = '(*'
743 let b:ECcommentClose = '*)'
744 elseif fileType == 'jsp'
745 let b:ECcommentOpen = '<%--'
746 let b:ECcommentClose = '--%>'
747 elseif fileType == 'model'
748 let b:ECcommentOpen = '$'
749 let b:ECcommentClose = '$'
750 elseif fileType == 'st'
751 let b:ECcommentOpen = '"'
752 let b:ECcommentClose = '"'
753 elseif fileType =~ '^\(tssgm\|tssop\)$'
754 let b:ECcommentOpen = 'comment = "'
755 let b:ECcommentClose = '"'
756 " Singlepart comments:
757 elseif fileType =~ '^\(ox\|cpp\|php\|java\|verilog\|acedb\|ch\|clean\|'.
758 \ 'clipper\|cs\|dot\|dylan\|hercules\|idl\|ishd\|javascript\|'.
759 \ 'kscript\|mel\|named\|openroad\|pccts\|pfmain\|pike\|'.
760 \ 'pilrc\|plm\|pov\|rc\|scilab\|specman\|tads\|tsalt\|uc\|'.
762 let b:ECcommentOpen = '//'
763 let b:ECcommentClose = ''
764 elseif fileType =~ '^\(vim\|abel\)$'
765 let b:ECcommentOpen = '"'
766 let b:ECcommentClose = ''
767 elseif fileType =~ '^\(lisp\|scheme\|scsh\|amiga\|asm\|asm68k\|bindzone\|'.
768 \ 'def\|dns\|dosini\|dracula\|dsl\|idlang\|iss\|jess\|kix\|'.
769 \ 'masm\|monk\|nasm\|ncf\|omnimark\|pic\|povini\|rebol\|'.
770 \ 'registry\|samba\|skill\|smith\|tags\|tasm\|tf\|winbatch\|'.
772 let b:ECcommentOpen = ';'
773 let b:ECcommentClose = ''
774 elseif fileType =~ '^\(python\|perl\|[^w]*sh$\|tcl\|jproperties\|make\|'.
775 \ 'robots\|apache\|apachestyle\|awk\|bc\|cfg\|cl\|conf\|'.
776 \ 'crontab\|diff\|ecd\|elmfilt\|eterm\|expect\|exports\|'.
777 \ 'fgl\|fvwm\|gdb\|gnuplot\|gtkrc\|hb\|hog\|ia64\|icon\|'.
778 \ 'inittab\|lftp\|lilo\|lout\|lss\|lynx\|maple\|mush\|'.
779 \ 'muttrc\|nsis\|ora\|pcap\|pine\|po\|procmail\|'.
780 \ 'psf\|ptcap\|r\|radiance\|ratpoison\|readline\remind\|'.
781 \ 'ruby\|screen\|sed\|sm\|snnsnet\|snnspat\|snnsres\|spec\|'.
782 \ 'squid\|terminfo\|tidy\|tli\|tsscl\|vgrindefs\|vrml\|'.
783 \ 'wget\|wml\|xf86conf\|xmath\)$'
784 let b:ECcommentOpen = '#'
785 let b:ECcommentClose = ''
786 elseif fileType == 'webmacro'
787 let b:ECcommentOpen = '##'
788 let b:ECcommentClose = ''
789 elseif fileType == 'ppwiz'
790 let b:ECcommentOpen = ';;'
791 let b:ECcommentClose = ''
792 elseif fileType == 'latte'
793 let b:ECcommentOpen = '\\;'
794 let b:ECcommentClose = ''
795 elseif fileType =~ '^\(tex\|abc\|erlang\|ist\|lprolog\|matlab\|mf\|'.
796 \ 'postscr\|ppd\|prolog\|simula\|slang\|slrnrc\|slrnsc\|'.
797 \ 'texmf\|viki\|virata\)$'
798 let b:ECcommentOpen = '%'
799 let b:ECcommentClose = ''
800 elseif fileType =~ '^\(caos\|cterm\|form\|foxpro\|sicad\|snobol4\)$'
801 let b:ECcommentOpen = '*'
802 let b:ECcommentClose = ''
803 elseif fileType =~ '^\(m4\|config\|automake\)$'
804 let b:ECcommentOpen = 'dnl '
805 let b:ECcommentClose = ''
806 elseif fileType =~ '^\(vb\|aspvbs\|ave\|basic\|elf\|lscript\)$'
807 let b:ECcommentOpen = "'"
808 let b:ECcommentClose = ''
809 elseif fileType =~ '^\(plsql\|vhdl\|ahdl\|ada\|asn\|csp\|eiffel\|gdmo\|'.
810 \ 'haskell\|lace\|lua\|mib\|sather\|sql\|sqlforms\|sqlj\|'.
812 let b:ECcommentOpen = '--'
813 let b:ECcommentClose = ''
814 elseif fileType == 'abaqus'
815 let b:ECcommentOpen = '**'
816 let b:ECcommentClose = ''
817 elseif fileType =~ '^\(aml\|natural\|vsejcl\)$'
818 let b:ECcommentOpen = '/*'
819 let b:ECcommentClose = ''
820 elseif fileType == 'ampl'
821 let b:ECcommentOpen = '\\#'
822 let b:ECcommentClose = ''
823 elseif fileType == 'bdf'
824 let b:ECcommentOpen = 'COMMENT '
825 let b:ECcommentClose = ''
826 elseif fileType == 'btm'
827 let b:ECcommentOpen = '::'
828 let b:ECcommentClose = ''
829 elseif fileType == 'dcl'
830 let b:ECcommentOpen = '$!'
831 let b:ECcommentClose = ''
832 elseif fileType == 'dosbatch'
833 let b:ECcommentOpen = 'rem '
834 let b:ECcommentClose = ''
835 elseif fileType == 'focexec'
836 let b:ECcommentOpen = '-*'
837 let b:ECcommentClose = ''
838 elseif fileType == 'forth'
839 let b:ECcommentOpen = '\\ '
840 let b:ECcommentClose = ''
841 elseif fileType =~ '^\(fortran\|inform\|sqr\|uil\|xdefaults\|'.
843 let b:ECcommentOpen = '!'
844 let b:ECcommentClose = ''
845 elseif fileType == 'gp'
846 let b:ECcommentOpen = '\\\\'
847 let b:ECcommentClose = ''
848 elseif fileType =~ '^\(master\|nastran\|sinda\|spice\|tak\|trasys\)$'
849 let b:ECcommentOpen = '$'
850 let b:ECcommentClose = ''
851 elseif fileType == 'nroff' || fileType == 'groff'
852 let b:ECcommentOpen = ".\\\\\""
853 let b:ECcommentClose = ''
854 elseif fileType == 'opl'
855 let b:ECcommentOpen = 'REM '
856 let b:ECcommentClose = ''
857 elseif fileType == 'texinfo'
858 let b:ECcommentOpen = '@c '
859 let b:ECcommentClose = ''
860 elseif fileType == 'mail'
861 let b:ECcommentOpen = '>'
862 let b:ECcommentClose = ''
866 let b:ECcommentMiddle =
867 \ s:ParseCommentsOp(b:ECcommentOpen, b:ECcommentClose)
868 if b:ECcommentMiddle == ''
869 let b:ECuseCommentsOp = 0
872 let b:ECcommentMiddle = ''
875 if !s:overrideEmptyLines
876 call s:CommentEmptyLines(fileType)
881 " ParseCommentsOp(commentOpen, commentClose)
882 " commentOpen -- comment-open string
883 " commentClose-- comment-close string
885 " Try to extract the middle comment string from &comments. First hit wins.
886 " If nothing is found '' is returned.
888 function s:ParseCommentsOp(commentOpen, commentClose)
889 let commStr = &comments
891 let commentMiddle = ''
895 " First decompose &omments into consecutive s-, m- and e-parts.
897 let s = stridx(commStr, 's')
902 let commStr = strpart(commStr, s)
903 let comma = stridx(commStr, ',')
907 let sPart = strpart(commStr, 0, comma)
909 let commStr = strpart(commStr, comma)
910 let m = stridx(commStr, 'm')
915 let commStr = strpart(commStr, m)
916 let comma = stridx(commStr, ',')
920 let mPart = strpart(commStr, 0, comma)
922 let commStr = strpart(commStr, comma)
923 let e = stridx(commStr, 'e')
928 let commStr = strpart(commStr, e)
929 let comma = stridx(commStr, ',')
931 let comma = strlen(commStr)
933 let ePart = strpart(commStr, 0, comma)
935 let commStr = strpart(commStr, comma)
938 " Now check wether this is what we want:
939 " Are the comment string the same?
941 let sColon = stridx(sPart, ':')
942 let eColon = stridx(ePart, ':')
943 if sColon == -1 || eColon == -1
946 if strpart(sPart, sColon + 1) != a:commentOpen
947 \ || strpart(ePart, eColon + 1) != a:commentClose
951 let mColon = stridx(mPart, ':')
955 let commentMiddle = strpart(mPart, mColon + 1)
958 " Check for any alignement.
961 while sPart[i] != ':'
963 let offset = strlen(a:commentOpen) - strlen(commentMiddle)
965 elseif sPart[i] == 'l'
968 elseif s:isDigit(sPart[i])
970 while s:isDigit(sPart[i + j])
973 let offset = 1 * strpart(sPart, i, j)
981 while ePart[i] != ':'
983 let offset = strlen(a:commentClose) - strlen(commentMiddle)
985 elseif ePart[i] == 'l'
988 elseif s:isDigit(ePart[i])
990 while s:isDigit(ePart[i + j])
993 let offset = 1 * strpart(ePart, i, j)
1002 let commentMiddle = " " . commentMiddle
1003 let offset = offset - 1
1009 return commentMiddle
1017 function s:isDigit(char)
1020 let charVal = char2nr(a:char)
1022 if charVal >= 48 && charVal <= 57
1030 " CommentEmptyLines(ft)
1031 " ft -- filetype of current buffer
1033 " Decides, if empty lines should be commentified or not. Add the filetype,
1034 " you want to change, to the apropriate if-clause.
1036 function s:CommentEmptyLines(ft)
1037 " FIXME: Quick hack (tm)!
1039 " Add special filetypes here.
1040 elseif b:ECcommentClose == ''
1041 let b:ECemptyLines = 'yes'
1043 let b:ECemptyLines = 'no'
1048 " CheckPossibleEmbedding(ft)
1049 " ft -- the filetype of current buffer
1051 " Check wether it makes sense to allow checking for the synIDs.
1052 " Eg. C will never have embedded code...
1054 function s:CheckPossibleEmbedding(ft)
1055 if a:ft =~ '^\(php\|vim\|latte\|html\)$'
1056 let b:ECpossibleEmbedding = 1
1058 " Since getting the synID is slow, we set the default to 'no'!
1059 " There are also some 'broken' languages like the filetype for
1060 " autoconf's configure.in's ('config').
1061 let b:ECpossibleEmbedding = 0
1066 " CommentifyMultiPart(lineString, commentStart, commentEnd, action)
1067 " lineString -- line to commentify
1068 " commentStart -- comment-start string, eg '/*'
1069 " commentEnd -- comment-end string, eg. '*/'
1070 " commentMiddle -- comment-middle string, eg. ' *'
1072 " This function commentifies code of languages, which have multipart
1073 " comment strings, eg. '/*' - '*/' of C.
1075 function s:CommentifyMultiPart(lineString, commentStart,
1076 \ commentEnd, commentMiddle)
1077 if s:Action == 'guess' || s:Action == 'first' || b:ECuseMPBlock
1078 let todo = s:DecideWhatToDo(a:lineString, a:commentStart, a:commentEnd)
1083 if todo == 'decomment'
1084 return s:UnCommentify(a:lineString, a:commentStart,
1085 \ a:commentEnd, a:commentMiddle)
1087 return s:Commentify(a:lineString, a:commentStart,
1088 \ a:commentEnd, a:commentMiddle)
1093 " CommentifySinglePart(lineString, commentSymbol)
1094 " lineString -- line to commentify
1095 " commentSymbol -- comment string, eg '#'
1097 " This function is used for all languages, whose comment strings
1098 " consist only of one string at the beginning of a line.
1100 function s:CommentifySinglePart(lineString, commentSymbol)
1101 if s:Action == 'guess' || s:Action == 'first'
1102 let todo = s:DecideWhatToDo(a:lineString, a:commentSymbol)
1107 if todo == 'decomment'
1108 return s:UnCommentify(a:lineString, a:commentSymbol)
1110 return s:Commentify(a:lineString, a:commentSymbol)
1115 " Escape(lineString, commentStart, commentEnd)
1117 " Escape already present symbols.
1119 function s:Escape(lineString, commentStart, commentEnd)
1120 let line = a:lineString
1122 if b:ECaltOpen != ''
1123 let line = substitute(line, s:EscapeString(a:commentStart),
1126 if b:ECaltClose != ''
1127 let line = substitute(line, s:EscapeString(a:commentEnd),
1128 \ b:ECaltClose, "g")
1135 " UnEscape(lineString, commentStart, commentEnd)
1137 " Unescape already present escape symbols.
1139 function s:UnEscape(lineString, commentStart, commentEnd)
1140 let line = a:lineString
1142 " We translate only the first and the last occurrence
1143 " of this resp. escape string. Commenting a line several
1144 " times and decommenting it again breaks things.
1145 if b:ECaltOpen != ''
1146 let line = substitute(line, s:EscapeString(b:ECaltOpen),
1147 \ a:commentStart, "")
1149 if b:ECaltClose != ''
1150 let esAltClose = s:EscapeString(b:ECaltClose)
1151 let line = substitute(line, esAltClose
1152 \ . "\\(.*" . esAltClose . "\\)\\@!",
1160 " Commentify(lineString, commentSymbol, [commentEnd])
1161 " lineString -- the line in work
1162 " commentSymbol -- string to insert at the beginning of the line
1163 " commentEnd -- string to insert at the end of the line
1166 " This function inserts the start- (and if given the end-) string of the
1167 " comment in the current line.
1169 function s:Commentify(lineString, commentSymbol, ...)
1170 let line = a:lineString
1173 " If a end string is present, insert it too.
1175 " First we have to escape any comment already contained in the line,
1176 " since (at least for C) comments are not allowed to nest.
1177 let line = s:Escape(line, a:commentSymbol, a:1)
1179 if b:ECuseCommentsOp && b:ECuseMPBlock
1181 \ && s:i > s:startBlock
1182 let line = substitute(line, s:LookFor('commentmiddle'),
1183 \ s:SubstituteWith('commentmiddle', a:2), "")
1186 if !b:ECuseMPBlock || (b:ECuseMPBlock && s:i == s:endBlock)
1187 " Align the closing part to the right.
1188 if b:ECalignRight && s:inBlock
1189 let len = s:GetLineLen(line, strlen(a:commentSymbol)
1190 \ + strlen(b:ECprettyComments))
1191 while j < s:maxLen - len
1192 let line = line .' '
1197 let line = substitute(line, s:LookFor('commentend'),
1198 \ s:SubstituteWith('commentend', a:1), "")
1202 " insert the comment symbol
1203 if !b:ECuseMPBlock || a:0 == 0 || (b:ECuseMPBlock && s:i == s:startBlock)
1204 let line = substitute(line, s:LookFor('commentstart'),
1205 \ s:SubstituteWith('commentstart', a:commentSymbol), "")
1212 " UnCommentify(lineString, commentSymbol, [commentEnd])
1213 " lineString -- the line in work
1214 " commentSymbol -- string to remove at the beginning of the line
1215 " commentEnd -- string to remove at the end of the line
1218 " This function removes the start- (and if given the end-) string of the
1219 " comment in the current line.
1221 function s:UnCommentify(lineString, commentSymbol, ...)
1222 let line = a:lineString
1224 " remove the first comment symbol found on a line
1225 if a:0 == 0 || !b:ECuseMPBlock || (b:ECuseMPBlock && s:i == s:startBlock)
1226 let line = substitute(line, s:LookFor('decommentstart',
1228 \ s:SubstituteWith('decommentstart'), "")
1231 " If a end string is present, we have to remove it, too.
1233 " First, we remove the trailing comment symbol.
1234 if !b:ECuseMPBlock || (b:ECuseMPBlock && s:i == s:endBlock)
1235 let line = substitute(line, s:LookFor('decommentend', a:1),
1236 \ s:SubstituteWith('decommentend'), "")
1238 " Remove any trailing whitespace, if we used alignRight.
1240 let line = substitute(line, ' *$', '', "")
1244 " Maybe we added a middle string. Remove it here.
1245 if b:ECuseCommentsOp && b:ECuseMPBlock
1247 \ && s:i > s:startBlock
1248 let line = substitute(line, s:LookFor('decommentmiddle', a:2),
1249 \ s:SubstituteWith('decommentmiddle'), "")
1252 " Remove escaped inner comments.
1253 let line = s:UnEscape(line, a:commentSymbol, a:1)
1260 " GetLineLen(line, offset)
1261 " line -- line of which length should be computed
1262 " offset -- maybe a shift of the line to the right
1264 " Expands '\t' to it's tabstop value.
1266 function s:GetLineLen(line, offset)
1270 while a:line[i] != ""
1271 if a:line[i] == "\t"
1272 let len = (((len / &tabstop) + 1) * &tabstop)
1283 " EscapeString(string)
1284 " string -- string to process
1286 " Escapes characters in 'string', which have some function in
1287 " regular expressions, with a '\'.
1289 " Returns the escaped string.
1291 function s:EscapeString(string)
1292 return escape(a:string, "*{}[]$^-")
1296 " LookFor(what, ...)
1297 " what -- what type of regular expression
1300 " check for comment at start/end of line
1303 " insert comment strings
1306 " remove comment strings
1307 " a:1 -- comment string
1309 function s:LookFor(what, ...)
1310 if b:ECuseBlockIndent && s:inBlock
1311 let handleWhitespace = s:blockIndentRegex
1313 let handleWhitespace = b:ECsaveWhite
1316 if a:what == 'checkstart'
1317 let regex = '^'. b:ECsaveWhite . s:EscapeString(a:1)
1318 \ . s:EscapeString(b:ECidentFront)
1319 elseif a:what == 'checkend'
1320 let regex = s:EscapeString(b:ECidentBack)
1321 \ . s:EscapeString(a:1) . b:ECsaveWhite . '$'
1322 elseif a:what == 'commentstart'
1323 let regex = '^'. handleWhitespace
1324 elseif a:what == 'commentmiddle'
1325 let regex = '^'. handleWhitespace
1326 elseif a:what == 'commentend'
1328 elseif a:what == 'decommentstart'
1329 let regex = '^'. b:ECsaveWhite . s:EscapeString(a:1)
1330 \ . s:EscapeString(b:ECidentFront) . b:ECprettyUnComments
1331 elseif a:what == 'decommentmiddle'
1332 let regex = '^'. b:ECsaveWhite . s:EscapeString(a:1)
1333 \ . s:EscapeString(b:ECidentFront) . b:ECprettyUnComments
1334 elseif a:what == 'decommentend'
1335 let regex = b:ECprettyUnComments . s:EscapeString(b:ECidentBack)
1336 \ . s:EscapeString(a:1) . b:ECsaveWhite .'$'
1343 " SubstituteWith(what, ...)
1344 " what -- what type of regular expression
1347 " insert comment strings
1350 " remove comment strings
1351 " a:1 -- comment string
1353 function s:SubstituteWith(what, ...)
1354 if a:what == 'commentstart'
1355 \ || a:what == 'commentmiddle'
1356 \ || a:what == 'commentend'
1357 let commentSymbol = a:1
1359 let commentSymbol = ''
1362 if b:ECuseBlockIndent && s:inBlock
1363 let handleWhitespace = '\1' . commentSymbol
1365 let handleWhitespace = b:ECrespectWhite . commentSymbol
1369 if a:what == 'commentstart'
1370 let regex = handleWhitespace . b:ECidentFront
1371 \ . b:ECprettyComments
1372 elseif a:what == 'commentmiddle'
1373 let regex = handleWhitespace . b:ECidentFront
1374 \ . b:ECprettyComments
1375 elseif a:what == 'commentend'
1376 let regex = b:ECprettyComments . b:ECidentBack . a:1
1377 elseif a:what == 'decommentstart'
1378 \ || a:what == 'decommentmiddle'
1379 \ || a:what == 'decommentend'
1380 let regex = handleWhitespace
1388 " DecideWhatToDo(lineString, commentStart, ...)
1389 " lineString -- first line of block
1390 " commentStart -- comment start symbol
1391 " a:1 -- comment end symbol
1393 function s:DecideWhatToDo(lineString, commentStart, ...)
1394 " If we checked already, we return our previous result.
1396 \ && (s:Action == 'first'
1397 \ || (b:ECuseMPBlock && s:inBlock && a:0))
1398 return s:blockAction
1401 let s:blockAction = 'comment'
1403 if s:inBlock && a:0 && b:ECuseMPBlock
1404 let first = getline(s:startBlock)
1405 let last = getline(s:endBlock)
1407 if first =~ s:LookFor('checkstart', a:commentStart)
1408 \ && first !~ s:LookFor('checkend', a:1)
1409 \ && last !~ s:LookFor('checkstart', a:commentStart)
1410 \ && last =~ s:LookFor('checkend', a:1)
1411 let s:blockAction = 'decomment'
1414 return s:blockAction
1417 if a:lineString =~ s:LookFor('checkstart', a:commentStart)
1418 let s:blockAction = 'decomment'
1422 if a:lineString !~ s:LookFor('checkend', a:1)
1423 let s:blockAction = 'comment'
1427 let s:firstOfBlock = 0
1428 return s:blockAction
1433 " str -- string to convert
1435 " Convert leading tabs of given string to spaces.
1437 function s:TabsToSpaces(str)
1440 " FIXME: Can we use something like retab? I don't think so,
1441 " because retab changes every whitespace in the line, but we
1442 " wan't to modify only the leading spaces. Is this a problem?
1443 while string =~ '^\( *\)\t'
1444 let string = substitute(string, '^\( *\)\t', '\1'. s:tabConvert, "")
1452 " str -- string to convert
1454 " Convert leading spaces of given string to tabs.
1456 function s:SpacesToTabs(str)
1460 while string =~ '^\(\t*\)'. s:tabConvert
1461 let string = substitute(string, '^\(\t*\)'. s:tabConvert,
1470 " EnhCommentifyFallback4Embedded(test, fallback)
1471 " test -- test for the special case
1472 " fallback -- filetype instead of normal fallback
1474 " This function is global. It should be called from filetype
1475 " plugins like php, where the normal fallback behaviour may
1476 " not work. One may use 'synFiletype' to reference the guessed
1477 " filetype via synID.
1479 function EnhCommentifyFallback4Embedded(test, fallback)
1480 let b:EnhCommentifyFallbackTest = a:test
1481 let b:EnhCommentifyFallbackValue = a:fallback
1485 " Keyboard mappings.
1487 noremap <Plug>Comment
1488 \ :call EnhancedCommentify('', 'comment')<CR>
1489 noremap <Plug>DeComment
1490 \ :call EnhancedCommentify('', 'decomment')<CR>
1491 noremap <Plug>Traditional
1492 \ :call EnhancedCommentify('', 'guess')<CR>
1493 noremap <Plug>FirstLine
1494 \ :call EnhancedCommentify('', 'first')<CR>
1496 noremap <Plug>VisualComment
1497 \ <Esc>:call EnhancedCommentify('', 'comment',
1498 \ line("'<"), line("'>"))<CR>
1499 noremap <Plug>VisualDeComment
1500 \ <Esc>:call EnhancedCommentify('', 'decomment',
1501 \ line("'<"), line("'>"))<CR>
1502 noremap <Plug>VisualTraditional
1503 \ <Esc>:call EnhancedCommentify('', 'guess',
1504 \ line("'<"), line("'>"))<CR>
1505 noremap <Plug>VisualFirstLine
1506 \ <Esc>:call EnhancedCommentify('', 'first',
1507 \ line("'<"), line("'>"))<CR>
1509 " Finally set keybindings.
1511 " SetKeybindings(where)
1512 " where -- "l" for local to the buffer, "g" for global
1514 function s:SetKeybindings(where)
1516 let where = "<buffer>"
1523 execute "let userBindings = ". ns .":ECuserBindings"
1524 execute "let useAltKeys = ". ns .":ECuseAltKeys"
1525 execute "let traditionalMode = ". ns .":ECtraditionalMode"
1526 execute "let firstLineMode = ". ns .":ECfirstLineMode"
1527 execute "let bindInNormal = ". ns .":ECbindInNormal"
1528 execute "let bindInInsert = ". ns .":ECbindInInsert"
1529 execute "let bindInVisual = ". ns .":ECbindInVisual"
1533 " *** Put your personal bindings here! ***
1542 let s:c = '<Leader>c'
1543 let s:x = '<Leader>x'
1544 let s:C = '<Leader>C'
1545 let s:X = '<Leader>X'
1549 let s:Method = 'Traditional'
1550 elseif firstLineMode
1551 let s:Method = 'FirstLine'
1553 let s:Method = 'Comment'
1555 " Decomment must be defined here. Everything else is mapped below.
1557 execute 'nmap '. where .' <silent> <unique> '. s:C
1558 \ .' <Plug>DeCommentj'
1559 execute 'nmap '. where .' <silent> <unique> '. s:X
1560 \ .' <Plug>DeComment'
1564 execute 'imap '. where .' <silent> <unique> '. s:C
1565 \ .' <Esc><Plug>DeCommentji'
1566 execute 'imap '. where .' <silent> <unique> '. s:X
1567 \ .' <Esc><Plug>DeCommenti'
1571 execute 'vmap '. where .' <silent> <unique> '. s:C
1572 \ .' <Plug>VisualDeCommentj'
1573 execute 'vmap '. where .' <silent> <unique> '. s:X
1574 \ .' <Plug>VisualDeComment'
1579 execute 'nmap '. where .' <silent> <unique> '. s:c
1580 \ .' <Plug>'. s:Method .'j'
1581 execute 'nmap '. where .' <silent> <unique> '. s:x
1582 \ .' <Plug>'. s:Method
1586 execute 'imap '. where .' <silent> <unique> '. s:c
1587 \ .' <Esc><Plug>'. s:Method .'ji'
1588 execute 'imap '. where .' <silent> <unique> '. s:x
1589 \ .' <Esc><Plug>'. s:Method
1593 execute 'vmap <silent> <unique> '. s:c
1594 \ .' <Plug>Visual'. s:Method .'j'
1595 execute 'vmap '. where .' <silent> <unique> '. s:x
1596 \ .' <Plug>Visual'. s:Method
1601 if !s:ECbindPerBuffer
1602 call s:SetKeybindings("g")
1605 let &cpo = s:savedCpo
1607 " vim: set sts=4 sw=4 ts=8 :