Merge pull request #151 from klaasb/realnesting

Support automatic real nesting of comments without placeholders, if supported by the language.
This commit is contained in:
Caleb Maclennan 2016-05-24 16:17:09 +03:00
commit ec802fe1d3
No known key found for this signature in database
GPG Key ID: 63CC496475267693

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)