Skip to content

Commit 85a020f

Browse files
committed
Add ability to create a line of comment characters
Add functionality to insert a line from comment characters and to toggle back to a blank line. This requires the following modifications: Simple function to insert the line of comment characters. Modify UncommentNormalLine() to detect a line of pure comment characters and remove all of them (i.e. toggle). Create default mapping (<Leader>c_) Add option NERDNumCommentCharsHR to specify the width of the line made from comment characters. Update help documentation for new functionality, default key mapping, and new option.
1 parent 0b3d928 commit 85a020f

File tree

2 files changed

+156
-54
lines changed

2 files changed

+156
-54
lines changed

doc/NERD_commenter.txt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ CONTENTS *NERDCommenterContents*
2828
3.2.11 Use alternate delims map...|NERDComAltDelim|
2929
3.2.12 Comment aligned maps.......|NERDComAlignedComment|
3030
3.2.13 Uncomment line map.........|NERDComUncommentLine|
31+
3.2.14 Comment horiz. line........|NERDComCommentHorizontalRule|
3132
3.4 Sexy Comments.....................|NERDComSexyComments|
3233
3.5 The NERDComment function..........|NERDComNERDComment|
3334
4.Options.................................|NERDComOptions|
@@ -140,6 +141,9 @@ left side (|<Leader>|cl) or both sides (|<Leader>|cb).
140141
Uncomments the selected line(s).
141142

142143

144+
[count]|<Leader|c_ |NERDComCommentHR|
145+
Will create a line or horizontal rule out of comment characters.
146+
143147
With the optional repeat.vim plugin (vimscript #2136), the mappings can also
144148
be repeated via |.|
145149

@@ -354,7 +358,21 @@ lines were selected in visual-line mode.
354358
Related options:
355359
|'NERDRemoveAltComs'|
356360
|'NERDRemoveExtraSpaces'|
361+
------------------------------------------------------------------------------
362+
3.2.14 Make horiz. line of comments *NERDComCommentHorizontalRule*
363+
364+
Default mappings: [count]|<Leader>|c_
365+
Mapped to: <plug>NERDCommenterCommentHorizontalRule
366+
Applicable modes: normal visual-line.
367+
368+
Will create a line or horizontal rule out of comment characters. The width of
369+
the rule is determined as follows:
370+
1. If NERDNumCommentCharsHR is defined and greater than 0, use that value.
371+
2. If &wrap is set and &textwidth is greater than 0, use that value.
372+
3. Default to 72
357373

374+
Related options:
375+
|'NERDNumCommentCharsHR'|
358376
------------------------------------------------------------------------------
359377
3.3 Sexy Comments *NERDComSexyComments*
360378
These are comments that use one set of multipart comment delimiters as well as
@@ -433,6 +451,8 @@ then the script would do a sexy comment on the last visual selection.
433451
uncommenting.
434452
|'NERDCompactSexyComs'| Specifies whether to use the compact
435453
style sexy comments.
454+
|'NERDNumCommentCharsHR'| Specifies how many comment characters to
455+
use to create a horizontal rule.
436456

437457
------------------------------------------------------------------------------
438458
4.3 Options details *NERDComOptionsDetails*
@@ -710,6 +730,18 @@ you hit |<Leader>|cc on a line that is already commented it will be commented
710730
again.
711731

712732
------------------------------------------------------------------------------
733+
*'NERDNumCommentCharsHR'*
734+
Values: Any number.
735+
Default 0.
736+
737+
When this option is something besides 0, it specifies how many comment
738+
characters we'll use for creating a horizontal rule out of comments i.e. when
739+
we use the |<Leader>|c_. If it is zero, the CommentHorizontalRule command
740+
will determine the number of characters to use by using the &textwidth option
741+
if it is greater than 0 and &wrap is set. Otherwise, it defaults to 72.
742+
743+
------------------------------------------------------------------------------
744+
713745
3.3 Default delimiter customisation *NERDComDefaultDelims*
714746

715747
If you want the NERD commenter to use the alternative delimiters for a

plugin/NERD_commenter.vim

Lines changed: 124 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ call s:InitVariable("g:NERDRemoveAltComs", 1)
6161
call s:InitVariable("g:NERDRemoveExtraSpaces", 0)
6262
call s:InitVariable("g:NERDRPlace", "<]")
6363
call s:InitVariable("g:NERDSpaceDelims", 0)
64+
call s:InitVariable("g:NERDNumCommentCharsHR", 0)
6465

6566
let s:NERDFileNameEscape="[]#*$%'\" ?`!&();<>\\"
6667

@@ -671,6 +672,35 @@ function s:CommentBlock(top, bottom, lSide, rSide, forceNested )
671672
endif
672673
endfunction
673674

675+
" Function: s:CommentHorizontalRule(firstLine, lastLine) {{{2
676+
" This function creates a "horizontal rule" out of comment characters for each
677+
" line specified
678+
"
679+
" Args:
680+
" -firstLine/lastLine: the top and bottom lines to comment
681+
function s:CommentHorizontalRule(firstLine, lastLine)
682+
let currentLine = a:firstLine
683+
let lastLine = a:lastLine
684+
685+
while currentLine <= lastLine
686+
let theLine = getline(currentLine)
687+
688+
" if this is a blank line, let's just insert the comment HR
689+
if theLine =~ '\v^\s*$'
690+
call setline(currentLine, s:GetCommentCharsHR())
691+
" if the line isn't blank, we insert our comment HR, and then add the existing line just below this one and increment our currentLine AND our lastLine counter by one so that we don't end up repeating lines
692+
else
693+
call setline(currentLine, s:GetCommentCharsHR())
694+
call append(currentLine, theLine)
695+
let currentLine = currentLine + 1
696+
let lastLine = lastLine + 1
697+
endif
698+
699+
let currentLine = currentLine + 1
700+
endwhile
701+
702+
endfunction
703+
674704
" Function: s:CommentLines(forceNested, alignLeft, alignRight, firstLine, lastLine) {{{2
675705
" This function comments a range of lines.
676706
"
@@ -1139,6 +1169,8 @@ function! NERDComment(mode, type) range
11391169
normal! yy
11401170
endif
11411171
execute firstLine .','. lastLine .'call NERDComment("'. a:mode .'", "Comment")'
1172+
elseif a:type ==? 'CommentHorizontalRule'
1173+
call s:CommentHorizontalRule(firstLine, lastLine)
11421174
endif
11431175

11441176
let &ignorecase = oldIgnoreCase
@@ -1427,60 +1459,69 @@ function s:UncommentLineNormal(line)
14271459
let indxRight = s:FindDelimiterIndex(s:Right(), line)
14281460
let indxRightAlt = s:FindDelimiterIndex(s:Right({'alt': 1}), line)
14291461

1430-
"get the comment status on the line so we know how it is commented
1431-
let lineCommentStatus = s:IsCommentedOuttermost(s:Left(), s:Right(), s:Left({'alt': 1}), s:Right({'alt': 1}), line)
1432-
1433-
"it is commented with s:Left() and s:Right() so remove these delims
1434-
if lineCommentStatus == 1
1435-
let line = s:RemoveDelimiters(s:Left(), s:Right(), line)
1436-
1437-
"it is commented with s:Left({'alt': 1}) and s:Right({'alt': 1}) so remove these delims
1438-
elseif lineCommentStatus == 2 && g:NERDRemoveAltComs
1439-
let line = s:RemoveDelimiters(s:Left({'alt': 1}), s:Right({'alt': 1}), line)
1440-
1441-
"it is not properly commented with any delims so we check if it has
1442-
"any random left or right delims on it and remove the outtermost ones
1443-
else
1444-
"remove the outter most left comment delim
1445-
if indxLeft != -1 && (indxLeft < indxLeftAlt || indxLeftAlt == -1)
1446-
let line = s:RemoveDelimiters(s:Left(), '', line)
1447-
elseif indxLeftAlt != -1 && g:NERDRemoveAltComs
1448-
let line = s:RemoveDelimiters(s:Left({'alt': 1}), '', line)
1449-
endif
1450-
1451-
"remove the outter most right comment delim
1452-
if indxRight != -1 && (indxRight < indxRightAlt || indxRightAlt == -1)
1453-
let line = s:RemoveDelimiters('', s:Right(), line)
1454-
elseif indxRightAlt != -1 && g:NERDRemoveAltComs
1455-
let line = s:RemoveDelimiters('', s:Right({'alt': 1}), line)
1456-
endif
1457-
endif
1458-
1459-
1460-
let indxLeftPlace = s:FindDelimiterIndex(g:NERDLPlace, line)
1461-
let indxRightPlace = s:FindDelimiterIndex(g:NERDRPlace, line)
1462-
1463-
let right = s:Right()
1464-
let left = s:Left()
1465-
if !s:Multipart()
1466-
let right = s:Right({'alt': 1})
1467-
let left = s:Left({'alt': 1})
1468-
endif
1469-
1470-
1471-
"if there are place-holders on the line then we check to see if they are
1472-
"the outtermost delimiters on the line. If so then we replace them with
1473-
"real delimiters
1474-
if indxLeftPlace != -1
1475-
if (indxLeftPlace < indxLeft || indxLeft==-1) && (indxLeftPlace < indxLeftAlt || indxLeftAlt==-1)
1476-
let line = s:ReplaceDelims(g:NERDLPlace, g:NERDRPlace, left, right, line)
1477-
endif
1478-
elseif indxRightPlace != -1
1479-
if (indxRightPlace < indxLeft || indxLeft==-1) && (indxLeftPlace < indxLeftAlt || indxLeftAlt==-1)
1480-
let line = s:ReplaceDelims(g:NERDLPlace, g:NERDRPlace, left, right, line)
1481-
endif
1482-
1483-
endif
1462+
" here is an easy scenario for toggling horizontal rules: if the line
1463+
" consists solely of repetitions of s:Left(), then just set the entire
1464+
" line to be blank
1465+
" our comment string
1466+
if line =~ '\V\^\s\*\('. escape(s:Left(),'\/') . '\)\+\s\*\$'
1467+
let line = ''
1468+
else
1469+
"get the comment status on the line so we know how it is commented
1470+
let lineCommentStatus = s:IsCommentedOuttermost(s:Left(), s:Right(), s:Left({'alt': 1}), s:Right({'alt': 1}), line)
1471+
1472+
"it is commented with s:Left() and s:Right() so remove these delims
1473+
if lineCommentStatus == 1
1474+
let line = s:RemoveDelimiters(s:Left(), s:Right(), line)
1475+
1476+
"it is commented with s:Left({'alt': 1}) and s:Right({'alt': 1}) so remove these delims
1477+
elseif lineCommentStatus == 2 && g:NERDRemoveAltComs
1478+
let line = s:RemoveDelimiters(s:Left({'alt': 1}), s:Right({'alt': 1}), line)
1479+
1480+
"it is not properly commented with any delims so we check if it has
1481+
"any random left or right delims on it and remove the outtermost ones
1482+
else
1483+
"remove the outter most left comment delim
1484+
if indxLeft != -1 && (indxLeft < indxLeftAlt || indxLeftAlt == -1)
1485+
let line = s:RemoveDelimiters(s:Left(), '', line)
1486+
elseif indxLeftAlt != -1 && g:NERDRemoveAltComs
1487+
let line = s:RemoveDelimiters(s:Left({'alt': 1}), '', line)
1488+
endif
1489+
1490+
"remove the outter most right comment delim
1491+
if indxRight != -1 && (indxRight < indxRightAlt || indxRightAlt == -1)
1492+
let line = s:RemoveDelimiters('', s:Right(), line)
1493+
elseif indxRightAlt != -1 && g:NERDRemoveAltComs
1494+
let line = s:RemoveDelimiters('', s:Right({'alt': 1}), line)
1495+
endif
1496+
endif
1497+
1498+
1499+
let indxLeftPlace = s:FindDelimiterIndex(g:NERDLPlace, line)
1500+
let indxRightPlace = s:FindDelimiterIndex(g:NERDRPlace, line)
1501+
1502+
let right = s:Right()
1503+
let left = s:Left()
1504+
if !s:Multipart()
1505+
let right = s:Right({'alt': 1})
1506+
let left = s:Left({'alt': 1})
1507+
endif
1508+
1509+
1510+
"if there are place-holders on the line then we check to see if they are
1511+
"the outtermost delimiters on the line. If so then we replace them with
1512+
"real delimiters
1513+
if indxLeftPlace != -1
1514+
if (indxLeftPlace < indxLeft || indxLeft==-1) && (indxLeftPlace < indxLeftAlt || indxLeftAlt==-1)
1515+
let line = s:ReplaceDelims(g:NERDLPlace, g:NERDRPlace, left, right, line)
1516+
endif
1517+
elseif indxRightPlace != -1
1518+
if (indxRightPlace < indxLeft || indxLeft==-1) && (indxLeftPlace < indxLeftAlt || indxLeftAlt==-1)
1519+
let line = s:ReplaceDelims(g:NERDLPlace, g:NERDRPlace, left, right, line)
1520+
endif
1521+
1522+
endif
1523+
1524+
endif
14841525

14851526
let line = s:ConvertLeadingWhiteSpace(line)
14861527

@@ -2465,6 +2506,34 @@ function s:NumberOfLeadingTabs(s)
24652506
return strlen(substitute(a:s, '^\(\t*\).*$', '\1', ""))
24662507
endfunction
24672508

2509+
" Function: s:GetCommentCharsHR() {{{2
2510+
" returns a string of just left comment characters, the length of which is
2511+
" determined via the following rules:
2512+
function s:GetCommentCharsHR()
2513+
" this width of the horizontal rule gets set in one of three ways:
2514+
" 1. NERDCommenter setting: NERDNumCommentCharsHR
2515+
" 2. looking at text width variable (only if textwrap is set)
2516+
" 3. hard-coded value of 72
2517+
if g:NERDNumCommentCharsHR == 0
2518+
if &wrap && &textwidth > 0
2519+
let numCharsForHR = &textwidth
2520+
else
2521+
let numCharsForHR = 72
2522+
endif
2523+
else
2524+
let numCharsForHR = g:NERDNumCommentCharsHR
2525+
endif
2526+
let commentHR = repeat( s:Left(), numCharsForHR)
2527+
2528+
" this handles the case where s:Left() actually contains more than two
2529+
" characters.
2530+
if strlen(commentHR) > numCharsForHR
2531+
let commentHR = strpart(commentHR, 0, numCharsForHR)
2532+
endif
2533+
2534+
return commentHR
2535+
endfunction
2536+
24682537
" Function: s:NumLinesInBuf() {{{2
24692538
" Returns the number of lines in the current buffer
24702539
function s:NumLinesInBuf()
@@ -2763,6 +2832,7 @@ call s:CreateMaps('nx', 'Uncomment', 'Uncomment', 'cu')
27632832
call s:CreateMaps('n', 'AltDelims', 'Switch Delimiters', 'ca')
27642833
call s:CreateMaps('i', 'Insert', 'Insert Comment Here', '')
27652834
call s:CreateMaps('', ':', '-Sep3-', '')
2835+
call s:CreateMaps('nx', 'CommentHorizontalRule', 'Make a horizontal rule of comment chars', 'c_')
27662836
call s:CreateMaps('', ':help NERDCommenterContents<CR>', 'Help', '')
27672837

27682838
inoremap <silent> <plug>NERDCommenterInsert <SPACE><BS><ESC>:call NERDComment('i', "insert")<CR>

0 commit comments

Comments
 (0)