Automatic real nesting for languages with support

Removes the placeholder workaround (forceNested) for languages which
allow truly nested comments and automatically applies them.
Enabled for haskell, racket, scheme, scala, lisp, ocaml, sml.
Fixes issue #131
This commit is contained in:
Klaas Boesche 2014-05-21 17:52:04 +02:00
parent 2b3714bff6
commit c2fc065b33

View File

@ -195,7 +195,7 @@ let s:delimiterMap = {
\ 'groovy': { 'left': '//', 'leftAlt': '/*', 'rightAlt': '*/' },
\ 'gsp': { 'left': '<%--', 'right': '--%>', 'leftAlt': '<!--','rightAlt': '-->'},
\ 'gtkrc': { 'left': '#' },
\ 'haskell': { 'left': '{-','right': '-}', 'leftAlt': '--' },
\ 'haskell': { 'left': '{-','right': '-}', 'nested': 1, 'leftAlt': '--', 'nestedAlt': 1 },
\ 'hb': { 'left': '#' },
\ 'h': { 'left': '//', 'leftAlt': '/*', 'rightAlt': '*/' },
\ 'haml': { 'left': '-#', 'leftAlt': '/' },
@ -240,7 +240,7 @@ let s:delimiterMap = {
\ 'lilo': { 'left': '#' },
\ 'lilypond': { 'left': '%' },
\ 'liquid': { 'left': '{% comment %}', 'right': '{% endcomment %}' },
\ 'lisp': { 'left': ';', 'leftAlt': '#|', 'rightAlt': '|#' },
\ 'lisp': { 'left': ';', 'nested': 1, 'leftAlt': '#|', 'rightAlt': '|#', 'nestedAlt': 1 },
\ 'llvm': { 'left': ';' },
\ 'lotos': { 'left': '(*', 'right': '*)' },
\ 'lout': { 'left': '#' },
@ -288,7 +288,7 @@ let s:delimiterMap = {
\ 'objc': { 'left': '//', 'leftAlt': '/*', 'rightAlt': '*/' },
\ 'objcpp': { 'left': '//', 'leftAlt': '/*', 'rightAlt': '*/' },
\ 'objj': { 'left': '//', 'leftAlt': '/*', 'rightAlt': '*/' },
\ 'ocaml': { 'left': '(*', 'right': '*)' },
\ 'ocaml': { 'left': '(*', 'right': '*)', 'nested': 1 },
\ 'occam': { 'left': '--' },
\ 'octave': { 'left': '%', 'leftAlt': '#' },
\ 'omlet': { 'left': '(*', 'right': '*)' },
@ -329,7 +329,7 @@ let s:delimiterMap = {
\ 'puppet': { 'left': '#' },
\ 'pyrex': { 'left': '# ', 'leftAlt': '#' },
\ 'python': { 'left': '# ', 'leftAlt': '#' },
\ 'racket': { 'left': ';', 'leftAlt': '#|', 'rightAlt': '|#' },
\ 'racket': { 'left': ';', 'nested': 1, 'leftAlt': '#|', 'rightAlt': '|#', 'nestedAlt': 1 },
\ 'radiance': { 'left': '#' },
\ 'ratpoison': { 'left': '#' },
\ 'r': { 'left': '#' },
@ -349,9 +349,9 @@ let s:delimiterMap = {
\ 'samba': { 'left': ';', 'leftAlt': '#' },
\ 'sass': { 'left': '//', 'leftAlt': '/*' },
\ 'sather': { 'left': '--' },
\ 'scala': { 'left': '//', 'leftAlt': '/*', 'rightAlt': '*/' },
\ 'scala': { 'left': '//', 'nested': 1, 'leftAlt': '/*', 'rightAlt': '*/', 'nestedAlt': 1 },
\ 'scons': { 'left': '#' },
\ 'scheme': { 'left': ';', 'leftAlt': '#|', 'rightAlt': '|#' },
\ 'scheme': { 'left': ';', 'nested': 1, 'leftAlt': '#|', 'rightAlt': '|#', 'nestedAlt': 1 },
\ 'scilab': { 'left': '//' },
\ 'scsh': { 'left': ';' },
\ 'scss': { 'left': '//', 'leftAlt': '/*', 'rightAlt': '*/'},
@ -373,7 +373,7 @@ let s:delimiterMap = {
\ 'smarty': { 'left': '{*', 'right': '*}' },
\ 'smil': { 'left': '<!', 'right': '>' },
\ 'smith': { 'left': ';' },
\ 'sml': { 'left': '(*', 'right': '*)' },
\ 'sml': { 'left': '(*', 'right': '*)', 'nested': 1 },
\ 'snippets': { 'left': '#' },
\ 'snnsnet': { 'left': '#' },
\ 'snnspat': { 'left': '#' },
@ -505,6 +505,11 @@ function s:SetUpForNewFiletype(filetype, forceReset)
let b:NERDCommenterDelims[i] = ''
endif
endfor
for i in ['nested', 'nestedAlt']
if !has_key(b:NERDCommenterDelims, i)
let b:NERDCommenterDelims[i] = 0
endif
endfor
else
let b:NERDCommenterDelims = s:CreateDelimMapFromCms()
endif
@ -524,8 +529,10 @@ function s:CreateDelimMapFromCms()
return {
\ 'left': substitute(&commentstring, '\([^ \t]*\)\s*%s.*', '\1', ''),
\ 'right': substitute(&commentstring, '.*%s\s*\(.*\)', '\1', 'g'),
\ 'nested': 0,
\ 'leftAlt': '',
\ 'rightAlt': '' }
\ 'rightAlt': '',
\ 'nestedAlt': 0}
endfunction
" Function: s:SwitchToAlternativeDelimiters(printMsgs) function {{{2
@ -550,14 +557,18 @@ function s:SwitchToAlternativeDelimiters(printMsgs)
"save the current delimiters
let tempLeft = s:Left()
let tempRight = s:Right()
let tempNested = s:Nested()
"swap current delimiters for alternative
let b:NERDCommenterDelims['left'] = b:NERDCommenterDelims['leftAlt']
let b:NERDCommenterDelims['right'] = b:NERDCommenterDelims['rightAlt']
"set information on whether these are nested
let b:NERDCommenterDelims['nested'] = b:NERDCommenterDelims['nestedAlt']
"set the previously current delimiters to be the new alternative ones
let b:NERDCommenterDelims['leftAlt'] = tempLeft
let b:NERDCommenterDelims['rightAlt'] = tempRight
let b:NERDCommenterDelims['nestedAlt'] = tempNested
"tell the user what comment delimiters they are now using
if a:printMsgs
@ -755,7 +766,7 @@ function s:CommentLines(forceNested, align, firstLine, lastLine)
if s:CanCommentLine(a:forceNested, currentLine)
"if the user has specified forceNesting then we check to see if we
"need to switch delimiters for place-holders
if a:forceNested && g:NERDUsePlaceHolders
if a:forceNested && g:NERDUsePlaceHolders && !s:Nested()
let theLine = s:SwapOuterMultiPartDelimsForPlaceHolders(theLine)
endif
@ -801,9 +812,11 @@ function s:CommentLinesMinimal(firstLine, lastLine)
throw 'NERDCommenter.Delimiters exception: Minimal comments can only be used for filetypes that have multipart delimiters'
endif
let sexyNested = s:SexyNested()
"if we need to use place holders for the comment, make sure they are
"enabled for this filetype
if !g:NERDUsePlaceHolders && s:DoesBlockHaveMultipartDelim(a:firstLine, a:lastLine)
"enabled for this filetype, or the delims allow nesting
if !g:NERDUsePlaceHolders && !sexyNested && s:DoesBlockHaveMultipartDelim(a:firstLine, a:lastLine)
throw 'NERDCommenter.Settings exception: Place holders are required but disabled.'
endif
@ -813,13 +826,15 @@ function s:CommentLinesMinimal(firstLine, lastLine)
"make sure all multipart delimiters on the lines are replaced with
"placeholders to prevent illegal syntax
let currentLine = a:firstLine
while(currentLine <= a:lastLine)
let theLine = getline(currentLine)
let theLine = s:ReplaceDelims(left, right, g:NERDLPlace, g:NERDRPlace, theLine)
call setline(currentLine, theLine)
let currentLine = currentLine + 1
endwhile
if !sexyNested
let currentLine = a:firstLine
while(currentLine <= a:lastLine)
let theLine = getline(currentLine)
let theLine = s:ReplaceDelims(left, right, g:NERDLPlace, g:NERDRPlace, theLine)
call setline(currentLine, theLine)
let currentLine = currentLine + 1
endwhile
endif
"add the delimiter to the top line
let theLine = getline(a:firstLine)
@ -859,7 +874,7 @@ function s:CommentLinesSexy(topline, bottomline)
throw 'NERDCommenter.Delimiters exception: cannot perform sexy comments with available delimiters.'
endif
"make sure the lines aren't already commented sexually
"make sure the lines aren't already commented sexually or we can nest
if !s:CanSexyCommentLines(a:topline, a:bottomline)
throw 'NERDCommenter.Nesting exception: cannot nest sexy comments'
endif
@ -884,7 +899,9 @@ function s:CommentLinesSexy(topline, bottomline)
if lineHasTabs
let theLine = s:ConvertLeadingTabsToSpaces(theLine)
endif
let theLine = s:SwapOuterMultiPartDelimsForPlaceHolders(theLine)
if !s:SexyNested()
let theLine = s:SwapOuterMultiPartDelimsForPlaceHolders(theLine)
endif
let theLine = s:AddLeftDelimAligned(left . spaceString, theLine, leftAlignIndx)
if lineHasTabs
let theLine = s:ConvertLeadingSpacesToTabs(theLine)
@ -898,7 +915,9 @@ function s:CommentLinesSexy(topline, bottomline)
if lineHasTabs
let theLine = s:ConvertLeadingTabsToSpaces(theLine)
endif
let theLine = s:SwapOuterMultiPartDelimsForPlaceHolders(theLine)
if !s:SexyNested()
let theLine = s:SwapOuterMultiPartDelimsForPlaceHolders(theLine)
endif
endif
let theLine = s:AddRightDelim(spaceString . right, theLine)
if lineHasTabs
@ -943,7 +962,9 @@ function s:CommentLinesSexy(topline, bottomline)
let theLine = s:ConvertLeadingTabsToSpaces(theLine)
endif
let theLine = s:SwapOuterMultiPartDelimsForPlaceHolders(theLine)
if !s:SexyNested()
let theLine = s:SwapOuterMultiPartDelimsForPlaceHolders(theLine)
endif
" add the sexyComMarker
let theLine = repeat(' ', leftAlignIndx) . repeat(' ', strlen(left)-strlen(sexyComMarker)) . sexyComMarkerSpaced . strpart(theLine, leftAlignIndx)
@ -985,7 +1006,7 @@ function s:CommentLinesToggle(forceNested, firstLine, lastLine)
"if the user has specified forceNesting then we check to see if we
"need to switch delimiters for place-holders
if g:NERDUsePlaceHolders
if g:NERDUsePlaceHolders && !s:Nested()
let theLine = s:SwapOuterMultiPartDelimsForPlaceHolders(theLine)
endif
@ -1305,7 +1326,7 @@ function s:RemoveDelimiters(left, right, line)
endif
"look for the right delimiter, if we find it, remove it
let rightIndx = s:FindDelimiterIndex(a:right, line)
let rightIndx = s:LastIndexOfDelim(a:right, line)
if rightIndx != -1
let line = strpart(line, 0, rightIndx) . strpart(line, rightIndx+lenRight)
@ -1537,8 +1558,8 @@ function s:UncommentLineNormal(line)
"get the positions of all delimiter types on the line
let indxLeft = s:FindDelimiterIndex(s:Left(), line)
let indxLeftAlt = s:FindDelimiterIndex(s:Left({'alt': 1}), line)
let indxRight = s:FindDelimiterIndex(s:Right(), line)
let indxRightAlt = s:FindDelimiterIndex(s:Right({'alt': 1}), line)
let indxRight = s:LastIndexOfDelim(s:Right(), line)
let indxRightAlt = s:LastIndexOfDelim(s:Right({'alt': 1}), line)
"get the comment status on the line so we know how it is commented
let lineCommentStatus = s:IsCommentedOutermost(s:Left(), s:Right(), s:Left({'alt': 1}), s:Right({'alt': 1}), line)
@ -1671,6 +1692,12 @@ function s:AltMultipart()
return b:NERDCommenterDelims['rightAlt'] != ''
endfunction
" Function: s:AltNested() {{{2
" returns 1 if the alternate multipart (if any) delims allow nesting
function s:AltNested()
return b:NERDCommenterDelims['nestedAlt']
endfunction
" Function: s:CanCommentLine(forceNested, line) {{{2
"This function is used to determine whether the given line can be commented.
"It returns 1 if it can be and 0 otherwise
@ -1701,7 +1728,7 @@ function s:CanCommentLine(forceNested, lineNum)
endif
"if the line is commented but nesting is allowed then return true
if a:forceNested && (!s:Multipart() || g:NERDUsePlaceHolders)
if s:Nested() || (a:forceNested && (!s:Multipart() || g:NERDUsePlaceHolders))
return 1
endif
@ -1723,6 +1750,11 @@ endfunction
" Return: 1 if the given lines can be commented sexually, 0 otherwise
function s:CanSexyCommentLines(topline, bottomline)
" see if the selected regions have any sexy comments
" however, if the language allows nested comments,
" we allow nested sexy comments
if s:SexyNested()
return 1
endif
let currentLine = a:topline
while(currentLine <= a:bottomline)
if s:IsInSexyComment(currentLine)
@ -2056,6 +2088,29 @@ function s:GetSexyComMarker(space, esc)
return sexyComMarker
endfunction
" Function: s:SexyNested() {{{2
" Returns 1 if the sexy delimeters allow nesting
" TODO this is ugly copy&paste from the GetSexyComLeft/Right functions,
" these could all be cleaned up
function s:SexyNested()
let lenLeft = strlen(s:Left())
let lenLeftAlt = strlen(s:Left({'alt': 1}))
"assume c style sexy comments if possible
if s:HasCStyleComments()
return (s:Left() == '/*' && s:Nested()) || (s:Left({'alt': 1}) == '/*' && s:AltNested())
else
"grab the longest left delim that has a right
if s:Multipart() && lenLeft >= lenLeftAlt
return s:Nested()
elseif s:AltMultipart()
return s:AltNested()
else
return 0
endif
endif
endfunction
" Function: s:GetSexyComLeft(space, esc) {{{2
" Returns the left delimiter for sexy comments for this filetype or -1 if
" there is none. C style sexy comments are used if possible
@ -2183,7 +2238,7 @@ endfunction
" -left/right: the left and right delimiters to check for
function s:IsCommented(left, right, line)
"if the line isn't commented return true
if s:FindDelimiterIndex(a:left, a:line) != -1 && (s:FindDelimiterIndex(a:right, a:line) != -1 || !s:Multipart())
if s:FindDelimiterIndex(a:left, a:line) != -1 && (s:LastIndexOfDelim(a:right, a:line) != -1 || !s:Multipart())
return 1
endif
return 0
@ -2407,7 +2462,7 @@ function s:IsSexyComment(topline, bottomline)
endif
"if there is a right delimiter on the top line then this isn't a sexy comment
if s:FindDelimiterIndex(right, getline(a:topline)) != -1
if s:LastIndexOfDelim(right, getline(a:topline)) != -1
return 0
endif
@ -2436,7 +2491,7 @@ function s:IsSexyComment(topline, bottomline)
"if there is a right delimiter in an intermediate line then the block isn't
"a sexy comment
if s:FindDelimiterIndex(right, theLine) != -1
if s:LastIndexOfDelim(right, theLine) != -1
return 0
endif
@ -2573,6 +2628,12 @@ function s:NerdEcho(msg, typeOfMsg)
endif
endfunction
" Function: s:Nested() {{{2
" returns 1 if the current multipart (if any) delims allow nesting
function s:Nested()
return b:NERDCommenterDelims['nested']
endfunction
" Function: s:NumberOfLeadingTabs(s) {{{2
" returns the number of leading tabs in the given string
function s:NumberOfLeadingTabs(s)